此代码在GCC 8中编译,但不在GCC 7和clang中编译。
constexpr int a = 1;
constexpr int b = --const_cast<int&>(a);
这显然是UB。
我的问题:标准人士对评估包含UB的constexpr有何看法-此代码应完全编译吗?
答案 0 :(得分:5)
constexpr
编译时表达式中的所有未定义行为使该表达式在编译时不求值(基本上不是consteval
,要使用基本上具有该含义的新关键字)。
初始化constexpr
实际上需要一个consteval
表达式。
如果您所做的是UB(我相信是),我不会解决,但是如果它是UB,则不应编译。
我将看看是否可以找到标准引号来支持这些断言。但是这里不需要棘手的language-lawyer处理。一个简单的原则:在编译时评估编译时表达式时,编译器必须审核它为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);
不是核心常量表达式,因此也不是常量表达式,这不仅是因为其评估具有不确定的行为,而且还因为它修改了一个寿命不在评估之内的对象。 “必须”语句(除非与“不需要诊断”结合使用)意味着,如果程序违反了该要求,则实现必须打印一条诊断消息(例如错误或警告)。