【问题标题】:Is assert usable in constant expressions?断言可以在常量表达式中使用吗?
【发布时间】:2015-05-25 11:33:58
【问题描述】:

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

【问题讨论】:

标签: c++ language-lawyer c++14 assert constant-expression


【解决方案1】:

这是由LWG 2234 处理的,在引入了对constexpr 函数的放宽约束后,该问题重新引起了人们的注意。

建议的决议

此措辞与 N3936 相关。

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

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

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

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

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

    • NDEBUG 定义在 assert(E) 出现的位置,或者

    • E 根据上下文转换为 bool (4 [conv]),是一个常量子表达式,其计算结果为 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);
}

【讨论】:

  • 术语有点奇怪:​​常量表达式 CE常量子表达式 CS 不需要是 CE 的子表达式,也不需要是 CE 的子表达式它必须是一个子表达式(一个完整的表达式)。
  • @dyp e 的子表达式可以是 e 本身,不是吗? (例如比较 §1.9/10)或者您实际上是指 CS 根本不是 CE 的一部分?
  • 不确定,是否有subexpression的定义?据我所知,§1.9p10 定义了 full-expression 而不是 subexpression (尽管“另一个表达式”的措辞可能表明子表达式确实是 <= 而不是比<)——这是我想要解决的第二点。第一点是函数中的语句不是函数调用表达式的子表达式。 -- 哦,毛巾日快乐;)
  • @dyp 没有定义,但我认为你提到的情况确实如此。第二点:是的,我想我需要重新措辞。但是 /11 呢?表达式可以是f() 的子表达式,而不会出现在其中。
  • 我不确定是否可以得出结论,函数f 中的表达式是该段落中f() 的子表达式:它谈到了表达式的求值 ,这并不是说这些成为/是f() 的一部分。
猜你喜欢
  • 2016-12-29
  • 2015-03-04
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 2021-05-19
  • 1970-01-01
  • 2013-08-23
  • 2020-02-14
相关资源
最近更新 更多