constexpr与operator | =

时间:2011-07-23 15:20:21

标签: c++11 constexpr

我尝试编写一个函数,它使用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?我希望它在运行时合理有效,我关心可读性。

2 个答案:

答案 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;
}

每个级别的递归都会清除设置的最右边的位,当最后一位被清除时,只剩下最高位,所以它会被返回。