12

-macro assertfrom<cassert>提供了一种确保满足条件的简洁方法。如果参数的计算结果为true,则不会产生任何进一步的影响。但是,在这种情况下,它的调用是否也可以在常量表达式中使用?

4

1 回答 1

9

LWG 2234处理了这个问题,constexpr在引入了对功能的放松限制后,该问题重新引起了人们的注意。

提议的决议

该措辞与 N3936 相关。

  1. 在 17.3 [定义] 中的现有列表中引入以下新定义:

    常量子表达式[defns.const.subexpr]

    作为 条件表达式 CE (5.16 [expr.cond]) 的子表达式求值的表达式不会阻止CE成为核心常量表达式 (5.20 [expr.const])。

  2. 在 19.3 [断言] p1 之后插入一个新段落,如下所示:

    -?- 表达式assert(E)是一个常量子表达式 ([defns.const.subexpr]),如果有的话

    • NDEBUG在 assert(E) 出现的地方定义,或

    • E上下文转换为bool(4 [conv]),是一个常量子表达式,其计算结果为 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是一个常量子表达式并true在调用中计算为check(true),因此assert(b)是一个常量子表达式,因此不会阻止check(true)它是一个。

当然,与static_assert模板相同的陷阱是可能的。鉴于NDEBUG未定义,此定义格式错误,§7.1.5/5 不需要诊断:

constexpr void fail() {
    assert(false);
}
于 2015-05-25T11:34:10.690 回答