C++11 式が C++11 の定数式 (つまり ) であるかどうかに基づいて、コンパイル時のブール値を生成することは可能constexpr
ですか? SO に関するいくつかの質問はこれに関連していますが、どこにも明確な答えはありません。
5 に答える
私はかつてそれを書きました(編集:制限と説明については以下を参照してください)。https://stackoverflow.com/a/10287598/34509から:
template<typename T>
constexpr typename remove_reference<T>::type makeprval(T && t) {
return t;
}
#define isprvalconstexpr(e) noexcept(makeprval(e))
ただし、定数式にはさまざまな種類があります。上記の回答は、prvalue定数式を検出します。
説明
noexcept(e)
式はiff false
containse
を与える
- 呼び出しが定数式でない限り、スローしない例外仕様を持たない関数への潜在的に評価される呼び出し、
- 潜在的に評価される
throw
式、 dynamic_cast
またはの潜在的に評価されるスロー可能な形式typeid
。
関数テンプレートmakeprval
は宣言されていないことに注意してください。そのnoexcept
ため、最初の箇条書きが適用されないようにするには、呼び出しが定数式である必要があり、これを悪用しています。throw
他の箇条書きも適用しないようにする必要がありますが、ありがたいことに、 aとthrowable or の両方がdynamic_cast
定数typeid
式でも許可されていないため、これで問題ありません。
制限事項
残念ながら、あなたにとって重要な場合とそうでない場合がある微妙な制限があります。「潜在的に評価される」という概念は、適用される定数式の制限よりもはるかに保守的です。したがって、上記noexcept
は偽陰性を与える可能性があります。一部の式は prvalue 定数式ではありませんが、そうではないと報告されます。例:
constexpr int a = (0 ? throw "fooled!" : 42);
constexpr bool atest = isprvalconstexpr((0 ? throw "fooled!" : 42));
の初期化が成功しatest
たとしても、上記では false です。a
これは、定数式であるためには、「邪悪な」非定数部分式が正式に評価される可能性があるとしても、「決して評価されない」ことで十分だからです。