-macro assert
from<cassert>
は、条件が満たされていることを確認する簡潔な方法を提供します。引数が に評価された場合、true
それ以上の効果はありません。ただし、その場合、その呼び出しを定数式内でも使用できますか?
1 に答える
これはLWG 2234によって対処され、constexpr
関数に対する制約が緩和された後に再び注目されました。
提案された解決策:
この文言は N3936 に関連しています。
17.3 [定義] の既存のリストに次の新しい定義を導入します。
定数部分式[defns.const.subexpr]
条件式 CE (5.16 [expr.cond])の部分式としての評価が、 CEがコア定数式 (5.20 [expr.const] ) になることを妨げない式。
示されているように、19.3 [アサーション] p1 の後に新しい段落を挿入します。
-?- 式
assert(
E)
が定数部分式 ( [defns.const.subexpr]) である場合、
NDEBUG
assert(E) が現れる位置で定義されている、または文脈上 (4 [conv]) に変換されたE
bool
は、値 に評価される定数部分式ですtrue
。
定数部分式
この解決により、定数部分式の概念が導入されました。これは本質的に、それ自体は定数式ではなく (必然的に) 定数式の中で使用できる式です。たとえば、
constexpr void f() {
int i = 0;
++i;
}
++i
ライフタイムがその式の外で始まったオブジェクトを変更するため、定数式ではありません (§5.20/(2.15))。ただし、f()
前の点が適用されないため、この式は全体として定数式です -i
の有効期間は で始まりf
ます。が定数式であることを妨げないので、++i
は定数部分式です。 ++i
f()
そしてassert
?
解決の 2 番目の部分は、 Eが定義されているか、引数自体が定数部分式であり、 に評価される場合、 assert(
E)
が定数部分式であることを保証します。これは、への呼び出しがボグ標準の定数式になる可能性があることを意味します。NDEBUG
true
assert
以下は整形式です。
constexpr int check(bool b) {
assert(b);
return 7;
}
constexpr int k = check(true);
b
true
は定数部分式であり、呼び出しでに評価されますcheck(true)
。したがって、assert(b)
は定数部分式であり、1 になることを妨げませんcheck(true)
。
もちろん、static_assert
テンプレートと同じ落とし穴が考えられます。それが定義されていないことを考えるとNDEBUG
、この定義は形式が正しくなく、§7.1.5/5 による診断は必要ありません。
constexpr void fail() {
assert(false);
}