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 65
fits into an int
thank 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:
template <int64_t n>
struct IntTypeThatFits {
static int64_t const max8 = std::numeric_limits<int8_t>::max();
static int64_t const min8 = std::numeric_limits<int8_t>::min();
static int64_t const max16 = std::numeric_limits<int16_t>::max();
static int64_t const min16 = std::numeric_limits<int16_t>::min();
static int64_t const max32 = std::numeric_limits<int32_t>::max();
static int64_t const min32 = std::numeric_limits<int32_t>::min();
typedef typename IntTypeThatFitsHelper<
(n <= max8 ) && (n >= min8 ),
(n <= max16) && (n >= min16),
(n <= max32) && (n >= min32)
>::Result Result;
};
... 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.
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