2

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));
}

これにより、gcc4.6.1を使用したコンパイル時の失敗が発生します。

error: expression ‘(p <unknown operator> ((p >> 1) | p))’ is not a constant-expression

constexprキーワードがなくても機能することに注意してください。

私の質問は次のとおりです。

なぜこれが機能しないのですか?operator | =はconstexprではないことがわかりますが、組み込み型にとっては重要ですか?

この関数をconstexprとして書く簡単な方法はありますか?実行時にかなり効率的になるようにしたいと思います。読みやすさについては少し気にしています。

4

2 に答える 2

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ます。特に、最後から 2 番目の項目は「割り当てまたは複合割り当て」です。

于 2011-07-23T15:55:46.773 に答える
3
constexpr inline uint64_t highestBit(uint64_t p)
{
    return (p & (p-1))? highestBit(p & (p-1)): p;
}

再帰の各レベルは、設定された右端のビットをクリアします。最後のビットがクリアされると、最上位のビットだけが残ったので、それが返されます。

于 2011-07-23T16:02:06.870 に答える