我想写一个模板,它返回可以表示给定数字的最小有符号整数类型。这是我的解决方案:
/**
* 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;
};
但是,GCC不接受此代码。我收到错误“由于数据类型的范围有限[-Werror = type-limits]”,因此比较总是如此。为什么会这样? n是带符号的64位整数,对于不同的n值,所有的比较可能都是真或假,或者我忽略了什么?
我会很高兴得到任何帮助。
编辑:我应该提到我正在使用C ++ 11。
答案 0 :(得分:4)
这是gcc的一个问题,模板化代码中的警告可能令人沮丧。您可以更改警告或使用其他方法。
您可能知道,模板化代码会被分析两次:
这里的问题是,在实例化时,检查是微不足道的(是65
适合int
谢谢),并且编译器未能意识到此警告不适用于所有实例化: (对于我们这些努力在上发出警告的无警告编译经验的人来说,这确实令人非常沮丧。
您有三种可能性:
请注意,有时第三种可能性涉及大规模变化和更复杂的解决方案。我建议不要使用复杂的代码 来摆脱无能的警告。
修改强>:
一种可能的解决方法:
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;
};
...通过更改比较中使用的数据类型,它应该使编译器警告静音。我认为显式转换(int64_t(std::numeric_limits<int8_t>::max())
)也可以工作,但我发现它更具可读性。
答案 1 :(得分:2)
错误正在发生,因为您要求GCC使用-Werror=type-limits
向您提供有关此警告的错误。警告-Wtype-limits
会在您进行比较时发出警告,由于给定数据类型的范围,该比较始终为真,例如:
uint8_t x;
if(x >= 0) { ... } // always true, unsigned integers are non-negative
if(x >= 256) { ... } // always false
int32_t x;
if(x < 9223372036854775808LL) { ... } // always true
此警告有时可能有用,但在许多情况下,包括此警告只是无用的迂腐,可以忽略。它通常是一个警告(如果你使用的那样,是-Wextra
的一部分启用),但是-Werror
或-Werror=type-limits
,GCC会将其设为错误。
由于在这种情况下,它实际上并不表示您的代码存在潜在问题,因此只需使用-Wno-type-limits
关闭警告,或者如果您不介意,请将其设为Werror=no-type-limits
错误在编译器输出中看到这些警告。
答案 2 :(得分:1)
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;
你不能在C ++中做到这一点(在C ++ 11中你可以) - numeric_limits<int8_t>::max()
不是编译时常量。你在使用C ++ 11吗?
BTW,Boost已经为您提供了这个:http://www.boost.org/doc/libs/1_49_0/libs/integer/doc/html/boost_integer/integer.html
答案 3 :(得分:1)
我认为问题所在的其他答案是错误的。我不相信这是一个过度热衷的编译器的情况,但我相信这是一个编译器错误。此代码仍会触发警告:
template<int64_t n>
bool a() {
return (n <= static_cast<int64_t>(std::numeric_limits<int8_t>::max()));
}
调用a<500>();
时,但此代码不会:
template<int64_t n>
bool a() {
return (n <= static_cast<int64_t>(127));
}
std :: numeric_limits :: max()的计算结果为127.如果没有其他人这样做,我今天晚些时候会提交bugzilla报告。
答案 4 :(得分:0)
你得到警告,因为对于template <int64_t n>
struct IntTypeThatFits
的一些小n
(小于2 ^ 32)的瞬间,由于操作数的范围,一些比较总是正确的(原文!) em>在编译期间。
在这种情况下,这可能被视为虚假警告,因为您的代码依赖于它,OTOH您明确要求使用-Werror
或类似的命令行开关使其成为错误,您基本上得到您在此处所要求的