繁体   English   中英

Constexpr 函数返回联合成员:g++ 与 clang++:无诊断与错误

[英]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]) 的规则,将评估以下之一:

  • 左值到右值的转换,应用于引用联合或其子对象的非活动成员的左值;

事实上, GCC 和 Clang 都根据不断评估的要求诊断出这个错误

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM