constexpr 和未定义的行为
constexpr and undefined behavior
这段代码在GCC 8中编译,但在GCC 7和clang中不编译。
constexpr int a = 1;
constexpr int b = --const_cast<int&>(a);
这显然是 UB。
我的问题:标准对评估包含 UB 的 constexpr 有什么看法 - 这段代码应该编译吗?
GCC 8 是错误的
constexpr
编译时表达式中的所有未定义行为都会使表达式在编译时不计算(基本上不是consteval
,使用基本上具有该含义的新关键字(。
初始化constexpr
实际上需要一个consteval
表达式。
我不会解决你所做的是否是UB(我相信是(,但如果它是UB,那么它不应该编译。
我会看看我是否能找到标准的引文来支持这些断言;但这里不需要棘手的语言律师。 只是一个简单的原则:在编译时计算编译时表达式时,编译器必须审核它为 UB 运行的代码,如果它们遇到 UB(同样,在编译时(,表达式不再是编译时表达式。
此代码格式不正确,GCC 8 和 9 不正确,无法给出诊断。
[expr.const](C++17第2款,目前的C++20第4款草案(:
表达式
e
是核心常量表达式,除非按照抽象机器的规则计算e
将计算以下表达式之一:
- 具有
。
本国际标准条款[介绍]至[CPP]中规定的未定义行为的操作;
- 修改对象,
。
除非将其应用于文字类型的非易失性左值,该值是指其生命周期始于
e
评估的非易失性对象;。
"从句 [介绍] 到 [cpp]"也称为核心语言规范。
[expr.const](C++17第5款,目前的C++20第10款草案(:
常量表达式是 glvalue 核心常量表达式,它引用作为常量表达式(定义如下(的允许结果的实体,或者是其值满足以下约束的 prvalue 核心常量表达式:
"以下约束"仅适用于类类型、数组类型或指针类型的值。
[dcl.constexpr](C++17第9段,目前的C++20草案第10段(:
在任何
constexpr
变量声明中,初始化的完整表达式应为常量表达式。
表达式--const_cast<int&>(a);
不是核心常量表达式,因此不是常量表达式,这既是因为它的计算将具有未定义的行为,还因为它修改了生存期不在计算中开始的对象。 "shall"语句(除非与"不需要诊断"结合使用(意味着当程序违反诊断消息时,实现必须打印诊断消息(例如错误或警告(。
- 编译C++时未定义的引用
- vscode g++链路故障:体系结构x86_64的未定义符号
- 如何修复此错误:未定义对"距离(浮点数,浮点数,浮点数,浮点数,浮点数)"的引用
- 编译器如何知道C++constexpr计算不会触发未定义的行为
- constexpr 和未定义的行为
- 未优化的 constexpr 的未定义引用用作默认参数
- 对外部模板 constexpr 构造函数的未定义引用
- 架构x86_64的未定义符号链接constexpr std :: array
- 对静态 constexpr 成员的未定义引用仅由值使用
- 静态 constexpr 模板成员在专用时提供未定义的引用
- 关于静态模板化 constexpr 的 Clang 警告(未定义内联函数)
- C++ 默认构造函数 constexpr 或正确未定义
- 成员函数指针值上的Constexpr-未定义的行为
- 对静态 constexpr 字符串的未定义引用(除非它是一个指针)
- 链接器错误(未定义的引用)与“静态 constexpr const char*”和完美转发
- 访问静态 constexpr 浮点型成员时的未定义引用
- 对静态constexpr char[]的未定义引用
- 为什么编译器抱怨对constexpr函数的未定义引用,即使它是在另一个源文件中定义的
- Clang抱怨在未求值的上下文中没有定义constexpr函数
- G++ 4.9 上静态 constexpr 的未定义引用,没有优化