Reputation: 16640
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?
Upvotes: 3
Views: 1874
Reputation: 5988
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;
Upvotes: 9
Reputation: 3559
Apply static_cast<unsigned long>
to both left hand and right hand side expressions in your second assert:
ASSERT(static_cast<unsigned long>(count)
< static_cast<unsigned long>(std::numeric_limits<size_t>::max()));
(I presume that your count is integer, not float - if I am wrong, go for a largest float type).
Upvotes: 1