禁用假“警告:左移计数> =类型的宽度” [英] disable spurious "warning: left shift count >= width of type"
问题描述
当用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实例化时, p>
现在警告是完全错误的,因为代码检查N足够大,不需要检查/掩码,所以当N为64时,移位永远不会发生。但是gcc警告。所以我试图禁用警告,但我不能弄清楚需要的#pragma魔术来关闭它...
标签分派到救援:
const bitval& check(){
constexpr bool enough_bits =(N using enough_bits_t = std :: integr_constant< bool,enough_bits> ;;
return check(enough_bits_t {});
}
const bitval& check(std :: false_type / * enough bits * /){
return * this;
}
const bitval&检查(std :: true_type / *足够的位* /){
if(val> =(1UL<< N)){
std :: clog< val<< out of range for<< N< bits in \\\
;
val& =(1UL<< N)-1;
}
return * this;
}
决定(有足够的位)是编译时常量,因此我计算它作为一个。
然后我构建一个类型( std :: true_type
或 std :: false_type
)基于该决定,并分派到两个不同的重载之一。
c> N 太大,不能移位,远不会被实例化,因此没有警告。如果在决策中有一个逻辑错误,代码被实例化,我得到一个编译器警告,而不是沉默(如果你设法禁用警告,并且你有一个逻辑错误,你会得到沉默的UB)。
I'm getting a spurious "warning: left shift count >= width of type" when compiling some template code with 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
};
The problem being that when it is instantiated with N == 64, it gives the warning.
Now the warning is completely spurious, as the code checks for N being large enough that no check/mask is needed, so when N is 64, the shifts will never happen. But gcc warns anyways. So I'm trying to disable the warning, but I can't figure out the needed #pragma magic to shut it up...
Tag dispatching to the rescue:
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;
}
The decision (are there enough bits) is a compile-time constant, so I calculate it as one.
I then build a type (std::true_type
or std::false_type
) based off that decision, and dispatch to one of two different overloads.
So the code where N
is too big to be shifted that far is never instantiated, and hence no warning. If there is a logic error in the decision, and the code is instantiated, I get a compiler warning instead of silence (had you managed to disable the warning, and you had a logic error, you'd get silent UB).
这篇关于禁用假“警告:左移计数> =类型的宽度”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!