【发布时间】:2015-02-02 15:37:32
【问题描述】:
在使用 gcc 编译某些模板代码时,我收到了一个虚假的“警告:左移计数 >= 类型宽度”:
template <int N> class bitval {
unsigned long val;
#pragma GCC diagnostic ignored "-Wall"
const bitval &check() {
if (N < sizeof(unsigned long) * CHAR_BIT && val >= (1UL << N)) {
std::clog << val << " out of range for " << N << " bits in " << std::endl;
val &= (1UL << N) - 1; }
return *this; }
#pragma GCC diagnostic pop
};
问题是当它用 N == 64 实例化时,它会给出警告。
现在警告完全是虚假的,因为代码检查 N 是否足够大以至于不需要检查/掩码,因此当 N 为 64 时,将永远不会发生移位。但是 gcc 还是会发出警告。所以我正在尝试禁用警告,但我无法弄清楚关闭它所需的#pragma 魔法......
【问题讨论】:
-
显然这不是虚假的,编译器比你更了解实例化。 G++ 很好,让您知道代码中有未定义的行为。如果
N大于63,我建议使用enable_if禁用此模板 -
所以您只是假设
unsigned long是64 位类型?好的。 -
不,我不认为 OP 假设(参见
sizeof(unsigned long) * CHAR_BIT但我猜编译器没有意识到这意味着(1UL << N)后面的if是“安全”。 -
@Mgetz:但没有未定义的行为。仅当第一次检查
N成功时才评估班次,在这种情况下,班次在范围内且定义明确 - 如问题所述。 -
@Mgetz:不,正如问题所说,这只是一个虚假的警告。可能对代码的分析不够深入,无法确定无法触发未定义的行为。