static_assert 表达式不是 __builtin_clz 的整数常量表达式
static_assert expression is not an integral constant expression with __builtin_clz
我有以下代码:
typedef unsigned char uchar;
constexpr int leaing_ones(uchar const u8) noexcept {
return __builtin_clz(static_cast<uchar>(~static_cast<unsigned>(u8))) +
sizeof(uchar) * 8 - sizeof(int) * 8;
}
int main() {
static_assert(leaing_ones(0b0000'0000) == 0);
static_assert(leaing_ones(0b1000'0000) == 1);
static_assert(leaing_ones(0b1100'0000) == 2);
static_assert(leaing_ones(0b1110'0000) == 3);
static_assert(leaing_ones(0b1111'0000) == 4);
static_assert(leaing_ones(0b1111'1000) == 5);
static_assert(leaing_ones(0b1111'1000) == 5);
static_assert(leaing_ones(0b1111'1100) == 6);
static_assert(leaing_ones(0b1111'1110) == 7);
static_assert(leaing_ones(0b1111'1111) == 8);
}
我 tested 这些带有 clang 12 和 GCC 11.1。唯一的问题是 clang 特别不喜欢最后一个断言:
<source>:16:17: error: static_assert expression is not an integral constant expression
static_assert(leaing_ones(0b1111'1111) == 8);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
据我所知,我没有造成任何类型的溢出,并且 GCC 可以很好地处理所有这些问题。这是一个 clang 错误,还是我忽略了什么?
将 0
传递给 __builtin_clz
是未定义的行为。
来自GCC manual:
Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.
(大胆的矿)
__builtin_clz
is undefined for an argument with value zero,并且由于您反转了所有位,因此 0b1111'1111
成为全零的模式。您的函数需要特殊情况 0
才能使用适当的值。
我有以下代码:
typedef unsigned char uchar;
constexpr int leaing_ones(uchar const u8) noexcept {
return __builtin_clz(static_cast<uchar>(~static_cast<unsigned>(u8))) +
sizeof(uchar) * 8 - sizeof(int) * 8;
}
int main() {
static_assert(leaing_ones(0b0000'0000) == 0);
static_assert(leaing_ones(0b1000'0000) == 1);
static_assert(leaing_ones(0b1100'0000) == 2);
static_assert(leaing_ones(0b1110'0000) == 3);
static_assert(leaing_ones(0b1111'0000) == 4);
static_assert(leaing_ones(0b1111'1000) == 5);
static_assert(leaing_ones(0b1111'1000) == 5);
static_assert(leaing_ones(0b1111'1100) == 6);
static_assert(leaing_ones(0b1111'1110) == 7);
static_assert(leaing_ones(0b1111'1111) == 8);
}
我 tested 这些带有 clang 12 和 GCC 11.1。唯一的问题是 clang 特别不喜欢最后一个断言:
<source>:16:17: error: static_assert expression is not an integral constant expression
static_assert(leaing_ones(0b1111'1111) == 8);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
据我所知,我没有造成任何类型的溢出,并且 GCC 可以很好地处理所有这些问题。这是一个 clang 错误,还是我忽略了什么?
将 0
传递给 __builtin_clz
是未定义的行为。
来自GCC manual:
Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.
(大胆的矿)
__builtin_clz
is undefined for an argument with value zero,并且由于您反转了所有位,因此 0b1111'1111
成为全零的模式。您的函数需要特殊情况 0
才能使用适当的值。