我尝试编写一个函数,它使用C ++ 0x constexpr返回一个只有输入集最高位的整数。
constexpr inline uint64_t
get_highest_bit(uint64_t p)
{
return
(p|=(p>>1)),
(p|=(p>>2)),
(p|=(p>>4)),
(p|=(p>>8)),
(p|=(p>>16)),
(p|=(p>>32)),
(p-(p>>1));
}
这使用gcc 4.6.1提供编译时失败。
error: expression ‘(p <unknown operator> ((p >> 1) | p))’ is not a constant-expression
请注意,它没有constexpr关键字。
我的问题是:
为什么这不起作用? 我可以看到operator | =不是constexpr,但对于内置类型是否重要?
有没有一种简单的方法可以将此功能写为constexpr?我希望它在运行时合理有效,我关心可读性。
答案 0 :(得分:8)
(未在GCC上测试,因为我没有4.6,但我已经验证算法是正确的。)
要使用constexpr
,您必须没有作业。因此,您经常需要使用递归来编写功能表单:
#include <cstdint>
#include <climits>
constexpr inline uint64_t highestBit(uint64_t p, int n = 1) {
return n < sizeof(p)*CHAR_BIT ? highestBit(p | p >> n, n * 2) : p - (p >> 1);
}
int main() {
static_assert(highestBit(7) == 4);
static_assert(highestBit(5) == 4);
static_assert(highestBit(0x381283) == 0x200000);
return 0;
}
您可以检查C ++0x§[expr.const] / 2,以查看constexpr
函数中不能使用的表达式。特别是,倒数第二项是“作业或复合作业”。
答案 1 :(得分:3)
constexpr inline uint64_t highestBit(uint64_t p)
{
return (p & (p-1))? highestBit(p & (p-1)): p;
}
每个级别的递归都会清除设置的最右边的位,当最后一位被清除时,只剩下最高位,所以它会被返回。