assert 可用于常量表达式吗?
Is assert usable in constant expressions?
来自 <cassert>
的 assert
宏提供了一种确保满足条件的简洁方法。如果参数的计算结果为 true
,则它不会产生任何进一步的影响。但是,在那种情况下,它的调用也可以在常量表达式中使用吗?
这已由 LWG 2234 处理,在引入对 constexpr
函数的宽松限制后重新引起注意。
Proposed resolution:
This wording is relative to N3936.
Introduce the following new definition to the existing list in 17.3
[definitions]:
constant subexpression [defns.const.subexpr]
an expression whose evaluation as subexpression of a conditional-expression CE (5.16 [expr.cond]) would not prevent CE from being a core constant expression (5.20 [expr.const]).
Insert a new paragraph following 19.3 [assertions] p1 as indicated:
-?- An expression assert(
E)
is a constant subexpression ( [defns.const.subexpr]), if either
NDEBUG
is defined at the point where assert(E) appears, or
E contextually converted to bool
(4 [conv]), is a constant subexpression that evaluates to the value true
.
常量子表达式
该决议引入了 常量子表达式 的概念 - 本质上是一种表达式,它本身(不一定)是常量表达式,但可以在其中使用。考虑例如
constexpr void f() {
int i = 0;
++i;
}
++i
不是常量表达式,因为它修改的对象的生命周期开始于该表达式之外 (§5.20/(2.15))。然而,表达式 f()
完全是一个常量表达式,因为前一点不适用 - i
的生命周期从 f
开始。因此 ++i
是常量子表达式,因为 ++i
不会阻止 f()
成为常量表达式。
和assert
?
决议的第二部分保证 assert(
E)
是常量子表达式,如果定义了 NDEBUG
或参数本身是常量子表达式,计算结果为 true
。这意味着对 assert
的调用也可以是标准常量表达式。
以下是合式的:
constexpr int check(bool b) {
assert(b);
return 7;
}
constexpr int k = check(true);
b
是常量子表达式,在调用 check(true)
时计算结果为 true
,因此 assert(b)
是常量子表达式,因此不会阻止 check(true)
从成为一个。
当然,与模板中 static_assert
相同的陷阱是可能的。鉴于 NDEBUG
未定义,此定义格式错误,§7.1.5/5 不需要诊断:
constexpr void fail() {
assert(false);
}
来自 <cassert>
的 assert
宏提供了一种确保满足条件的简洁方法。如果参数的计算结果为 true
,则它不会产生任何进一步的影响。但是,在那种情况下,它的调用也可以在常量表达式中使用吗?
这已由 LWG 2234 处理,在引入对 constexpr
函数的宽松限制后重新引起注意。
Proposed resolution:
This wording is relative to N3936.
Introduce the following new definition to the existing list in 17.3 [definitions]:
constant subexpression [defns.const.subexpr]
an expression whose evaluation as subexpression of a conditional-expression CE (5.16 [expr.cond]) would not prevent CE from being a core constant expression (5.20 [expr.const]).
Insert a new paragraph following 19.3 [assertions] p1 as indicated:
-?- An expression
assert(
E)
is a constant subexpression ( [defns.const.subexpr]), if either
NDEBUG
is defined at the point where assert(E) appears, orE contextually converted to
bool
(4 [conv]), is a constant subexpression that evaluates to the valuetrue
.
常量子表达式
该决议引入了 常量子表达式 的概念 - 本质上是一种表达式,它本身(不一定)是常量表达式,但可以在其中使用。考虑例如
constexpr void f() {
int i = 0;
++i;
}
++i
不是常量表达式,因为它修改的对象的生命周期开始于该表达式之外 (§5.20/(2.15))。然而,表达式 f()
完全是一个常量表达式,因为前一点不适用 - i
的生命周期从 f
开始。因此 ++i
是常量子表达式,因为 ++i
不会阻止 f()
成为常量表达式。
和assert
?
决议的第二部分保证 assert(
E)
是常量子表达式,如果定义了 NDEBUG
或参数本身是常量子表达式,计算结果为 true
。这意味着对 assert
的调用也可以是标准常量表达式。
以下是合式的:
constexpr int check(bool b) {
assert(b);
return 7;
}
constexpr int k = check(true);
b
是常量子表达式,在调用 check(true)
时计算结果为 true
,因此 assert(b)
是常量子表达式,因此不会阻止 check(true)
从成为一个。
当然,与模板中 static_assert
相同的陷阱是可能的。鉴于 NDEBUG
未定义,此定义格式错误,§7.1.5/5 不需要诊断:
constexpr void fail() {
assert(false);
}