I want to write a template that returns me the smallest signed integer type that can represent a given number. This is my solution:
/**
* Helper for IntTypeThatFits.
* Template parameters indicate whether the given number fits into 8, 16 or 32
* bits. If neither of them is true, it is assumed that it fits 64 bits.
*/
template <bool fits8, bool fits16, bool fits32>
struct IntTypeThatFitsHelper { };
// specializations for picking the right type
// these are all valid combinations of the flags
template<> struct IntTypeThatFitsHelper<true, true, true> { typedef int8_t Result; };
template<> struct IntTypeThatFitsHelper<false, true, true> { typedef int16_t Result; };
template<> struct IntTypeThatFitsHelper<false, false, true> { typedef int32_t Result; };
template<> struct IntTypeThatFitsHelper<false, false, false> { typedef int64_t Result; };
/// Finds the smallest integer type that can represent the given number.
template <int64_t n>
struct IntTypeThatFits
{
typedef typename IntTypeThatFitsHelper<
(n <= numeric_limits<int8_t>::max()) && (n >= numeric_limits<int8_t>::min()),
(n <= numeric_limits<int16_t>::max()) && (n >= numeric_limits<int16_t>::min()),
(n <= numeric_limits<int32_t>::max()) && (n >= numeric_limits<int32_t>::min())
>::Result Result;
};
However, GCC does not accept this code. I get an error “comparison is always true due to limited range of data type [-Werror=type-limits]”. Why does that happen? n is a signed 64bit integer, and all of the comparisons may be true or false for different values of n, or am I overlooking something?
I will be glad for any help.
Edit: I should mention that I am using C++11.
It’s an issue with gcc, warnings in templated code can be frustrating. You can either change the warning or use another approach.
As you may know, templated code is analyzed twice:
The problem here is that at instantiation, the check is trivial (yes
65fits into anintthank you), and the compiler fails to realize that this warning does not hold for all instantiations 🙁 It is very frustrating indeed for those of us who strive to have a warning-free compiling experience with warnings on.You have 3 possibilities:
Note that sometimes the 3rd possibility involves a massive change and much more complicated solution. I advise against complicated one’s code just to get rid of clueless warnings.
EDIT:
One possible workaround:
… by changing the type of the data used in the comparison, it should silence the compiler warning. I suppose explicit casting (
int64_t(std::numeric_limits<int8_t>::max())) could work too, but I found this more readable.