-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) 出现的地方定义,或E上下文转换为
bool
(4 [conv]),是一个常量子表达式,其计算结果为 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
是一个常量子表达式并true
在调用中计算为check(true)
,因此assert(b)
是一个常量子表达式,因此不会阻止check(true)
它是一个。
当然,与static_assert
模板相同的陷阱是可能的。鉴于NDEBUG
未定义,此定义格式错误,§7.1.5/5 不需要诊断:
constexpr void fail() {
assert(false);
}