禁用杂散"warning: left shift count >= width of type"

disable spurious "warning: left shift count >= width of type"

本文关键字:gt count of width type shift warning left      更新时间:2023-10-16
在使用

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 时,偏移永远不会发生。 但海湾合作委员会还是警告说。 所以我试图禁用警告,但我无法弄清楚关闭它所需的 #pragma 魔法......

标记调度救援:

const bitval& check() {
  constexpr bool enough_bits = (N < sizeof(unsigned long) * CHAR_BIT);
  using enough_bits_t = std::integral_constant<bool, enough_bits>;
  return check( enough_bits_t{} );
}
const bitval& check(std::false_type /*enough bits*/) {
  return *this;
} 
const bitval& check(std::true_type /*enough bits*/) {
  if (val >= (1UL << N)) {
    std::clog << val << " out of range for " << N << " bits in n";
    val &= (1UL << N) - 1;
  }
  return *this;
}

决策(是否有足够的位)是一个编译时常量,所以我将其计算为一个。

然后,我根据该决定构建一个类型(std::true_typestd::false_type),并调度到两个不同的重载之一。

因此,N太大而无法移动那么远的代码永远不会实例化,因此不会发出警告。 如果决策中存在逻辑错误,并且代码被实例化,我会收到编译器警告而不是静音(如果您设法禁用警告,并且您遇到逻辑错误,您将获得静默 UB)。