constexpr和未定义的行为

时间:2019-09-12 15:15:44

标签: c++ language-lawyer undefined-behavior constexpr

此代码在GCC 8中编译,但不在GCC 7和clang中编译。

constexpr int a = 1;
constexpr int b = --const_cast<int&>(a);

这显然是UB。

我的问题:标准人士对评估包含UB的constexpr有何看法-此代码应完全编译吗?

2 个答案:

答案 0 :(得分:5)

GCC 8错误

constexpr编译时表达式中的所有未定义行为使该表达式在编译时不求值(基本上不是consteval,要使用基本上具有该含义的新关键字)。

初始化constexpr实际上需要一个consteval表达式。

如果您所做的是UB(我相信是),我不会解决,但是如果它是UB,则不应编译。

我将看看是否可以找到标准引号来支持这些断言。但是这里不需要棘手的处理。一个简单的原则:在编译时评估编译时表达式时,编译器必须审核它为UB运行的代码,并且如果它们再次运行到UB中(再次在编译时),则该表达式不再是编译时表达式。

答案 1 :(得分:3)

此代码格式不正确,GCC 8和9不正确,没有给出诊断信息。

[expr.const](C ++ 17第2段,current C++20 draft paragraph 4):

  

表达式e核心常量表达式,除非根据抽象机的规则对e的求值将对以下表达式之一求值:      

      
  • ...

  •   
  • 将具有本国际标准[intro]至[cpp]条款中规定的不确定行为的操作;

  •   
  • ...

  •   
  • 对对象的修改,除非将其应用于文字类型的非易失性左值,该值是指其寿命在e的求值内开始的非易失性对象;

  •   
  • ...

  •   

“从[cpp到[cpp]的介绍]”也被称为核心语言规范。

[expr.const](C ++ 17第5段,current C++20 draft paragraph 10):

  

常量表达式是glvalue核心常量表达式,它引用的是一个常量表达式(如下定义)的允许结果的实体,或者是其值满足以下条件的prvalue核心常量表达式:以下限制条件:

“以下约束”仅适用于类类型,数组类型或指针类型的值。

[dcl.constexpr](C ++ 17第9段,current C++20 draft paragraph 10):

  

在任何constexpr变量声明中,初始化的完整表达应为常量表达式。

表达式--const_cast<int&>(a);不是核心常量表达式,因此也不是常量表达式,这不仅是因为其评估具有不确定的行为,而且还因为它修改了一个寿命不在评估之内的对象。 “必须”语句(除非与“不需要诊断”结合使用)意味着,如果程序违反了该要求,则实现必须打印一条诊断消息(例如错误或警告)。