We excessively use templates and we cannot always tell the signedness of a type at hand, so we need techniques to hide warnings that will be eventually optimized out. I have a simple ASSERT(condition) macro which throws something if the condition not evalutes to true.
The goal is to check the range of a T typed count value. We need it to be at least zero, at most the max of size_t.
template<typename SomeIntegral>
SomeIntegral ZERO()
{
return SomeIntegral(0);
}
template<typename T>
class C
{
public:
void f(T count)
{
std::vector<std::string> ret;
ASSERT(count>=ZERO<T>()); // Check #1
ASSERT(count<std::numeric_limits<size_t>::max()); // Check #2
ret.reserve(size_t(count)); // Needs check #1 and #2 to succeed.
// ...
}
// ...
};
The #1 check compiles without warning, but the #2 check says comparison between signed and unsigned integer expressions, because in this particular case the count has a signed type. If I could say ASSERT((unsigned T) count < std::numeric_limits<size_t>::max()) or similar somehow... Converting to unsigned T is safe in this situation, because we know from check #1 that it is at least zero.
... or what other compiler agnostic approach can I use?
I think you can use std::make_signed or std::make_unsigned. Whichever fits the need.
Here is a custom implementation.
namespace internal {
#define MK_MAKESIGNED(T,V) \
template<> struct make_signed<T> { \
public: \
typedef V type; \
};
template<typename T>
struct make_signed {
typedef T type;
};
MK_MAKESIGNED(unsigned int, signed int);
MK_MAKESIGNED(unsigned char, signed char);
// .... can convert anything to anything.
#undef MK_MAKESIGNED
};
internal::make_signed<unsigned char>::type c;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With