I am checking numeric value range with type traits, and unsigned types generate warning.
Comparison of unsigned expression >= 0 is always true
How to disable some warning at specific code range? I used GCC style #pragma
with Clang but this doesn't work.
Here's my code.
template<typename originT, typename destinationT>
void
assertForNumericRange(const originT value)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits"
assertWithReason(value >= std::numeric_limits<destinationT>::min());
assertWithReason(value <= std::numeric_limits<destinationT>::max());
#pragma GCC diagnostic pop
}
Note
Currently, I divided the assertion into three groups, floating-point, unsigned int, signed int. But I wish to integrate them into one if possible.
I am using Xcode 5.0 beta. In command-line, it reports this:
Apple LLVM version
5.0 (clang-500.1.58) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.3.0
Thread model: posix
Wich version of Clang are you using? From the Clang User Manual it should work exaclty the way you did. But your range assertions won't work the way you probably want them to work:
That first assertion itself does not make much sense, if destinationT
is unsigned, so min gives 0. Either originT
is unsigned as well, then it's clearly not negative, wich is what the compiler warns you about. Or originT
is signed, the comparison will convert one or both of the operand to other types, e.g. possibly converting value
to an unsigned (and thus positive) representation.
Consider for example
assertForNumericRange<signed char, unsigned long>( (signed char)-1);
The comparisons between (signed char)-1
and unsigned long
will promote the -1 to unsigned long
, effectively giving following assertions for 32bit long:
assertWithReason((unsigned long)0xFFFFFFFF >= std::numeric_limits<destinationT>::min());
assertWithReason((unsigned long)0xFFFFFFFF <= std::numeric_limits<destinationT>::max());
Both comparisons will give true, while -1 is clearly not in the range of unsigned long
's values.
Check this Q&A I just posted. For me it compiles without warnings, you should check it on Clang. Extension to floating point types is possible.
First of all, be aware that for floating point types, e.g.
std::numeric_limits<float>::min()
returns the minimum positive normalized value (>0), while for integer types
std::numeric_limits<T>::min()
returns the smallest non positive number (<=0).
Minimum negative number for a floating point type is:
-std::numeric_limits<T>::max()
I think you have to combine different numeric_limits methods/members (like is_integer
and is_signed
) and if statements, also to get rid of your warnings. (From the efficiency point of view) You do not have to worry of getting a too complicated function, as most of the checks will be evaluated at compile time and will have no influence on the execution time. In fact, if you can avoid some unnecessary checks at running time because of some checks done at compile time, your program will be faster.
You should also use std::is_same<T,U>::value
, and avoid any further check if that is true.