断言是否可用于常量表达式?

时间:2015-05-25 11:33:58

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

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

1 个答案:

答案 0 :(得分:9)

这是由LWG 2234处理的,在引入s函数的轻松约束后,它被引起了注意。

  

建议的解决方案

     

这个措辞与N3936有关。

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

         

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

         

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

  2.   
  3. 按照指示在19.3 [断言] p1之后插入一个新段落:

         

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

         
        
    • )定义在断言(E)出现的位置,或

    •   
    • E 从上下文转换为NDEBUG(4 [conv]),是一个常量子表达式,其值为bool

    •   
  4.   

常量子表达式

这个分辨率引入了常量子表达式的概念 - 本质上是一个表达式,它本身不是(必然)一个常量表达式,但可以在一个表达式中使用。考虑例如

true

constexpr void f() { int i = 0; ++i; } 不是常量表达式,因为它修改了生命周期在该表达式之外的对象(§5.20/(2.15))。但是,表达式++i完全是一个常量表达式,因为前一点不适用 - 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未定义,此定义格式不正确,§7.1.5/ 5无需诊断:

NDEBUG