[英]Constexpr function returning member of union: g++ vs. clang++: no diagnostics vs. error
考虑这段代码:
typedef union { float v; unsigned u; } T;
constexpr T x = { .u = 0 };
constexpr float f(void)
{
return x.v;
}
此代码有效吗?
调用:
$ g++ t506a.cpp -c -std=c++20 -pedantic -Wall -Wextra
<nothing>
$ clang++ t506a.cpp -c -std=c++20 -pedantic -Wall -Wextra
t506a.cpp:3:17: error: constexpr function never produces a constant expression
[-Winvalid-constexpr]
constexpr float f(void)
^
t506a.cpp:5:9: note: read of member 'v' of union with active member 'u' is not allowed in a
constant expression
return x.v;
^
1 error generated.
哪个编译器是正确的?
即使代码格式不正确,两个编译器都是正确的,因为在您显示的程序中不需要诊断。 确实f
永远不能作为核心常量表达式进行评估,但在这种情况下dcl.constexpr#6适用:
对于既不是默认值也不是模板的 constexpr 函数或 constexpr 构造函数,如果不存在参数值,则函数或构造函数的调用可以是核心常量表达式的求值子表达式,或者,对于构造函数,求值子表达式为一些常量初始化对象([basic.start.static])的初始化完整表达式,程序格式错误,不需要诊断。
(强调我的)
由于不需要诊断,因此允许 GCC 不对此进行诊断。
另一方面,如果您确实尝试将f
评估为常数,例如
constexpr float a = f();
那么它违反了 expr.const#5.10 :
表达式 E 是一个核心常量表达式,除非 E 的评估遵循抽象机 ([intro.execution]) 的规则,将评估以下之一:
- 左值到右值的转换,应用于引用联合或其子对象的非活动成员的左值;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.