简体   繁体   English

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

[英]Constexpr function returning member of union: g++ vs. clang++: no diagnostics vs. error

Consider this code:考虑这段代码:

typedef union { float v; unsigned u; } T;
constexpr T x = { .u = 0 };
constexpr float f(void)
{
        return x.v;
}

Is this code valid?此代码有效吗?

Invocations:调用:

$ 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.

Which compiler is correct?哪个编译器是正确的?

Both compilers are correct, even though the code is ill-formed, because no diagnostic is required in the program you've shown.即使代码格式不正确,两个编译器都是正确的,因为在您显示的程序中不需要诊断。 It's true that f can never be evaluated as a core constant expression, but in that case dcl.constexpr#6 applies:确实f永远不能作为核心常量表达式进行评估,但在这种情况下dcl.constexpr#6适用:

For a constexpr function or constexpr constructor that is neither defaulted nor a template, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression , or, for a constructor, an evaluated subexpression of the initialization full-expression of some constant-initialized object ([basic.start.static]), the program is ill-formed, no diagnostic required .对于既不是默认值也不是模板的 constexpr 函数或 constexpr 构造函数,如果不存在参数值,则函数或构造函数的调用可以是核心常量表达式的求值子表达式,或者,对于构造函数,求值子表达式为一些常量初始化对象([basic.start.static])的初始化完整表达式,程序格式错误,不需要诊断

(emphasis mine) (强调我的)

Since no diagnostic is required, GCC is allowed to not diagnose this.由于不需要诊断,因此允许 GCC 不对此进行诊断。

On the other hand, if you do attempt to evaluate f as a constant, eg另一方面,如果您确实尝试将f评估为常数,例如

constexpr float a = f();

then it violates expr.const#5.10 :那么它违反了 expr.const#5.10

An expression E is a core constant expression unless the evaluation of E, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following:表达式 E 是一个核心常量表达式,除非 E 的评估遵循抽象机 ([intro.execution]) 的规则,将评估以下之一:

  • an lvalue-to-rvalue conversion that is applied to a glvalue that refers to a non-active member of a union or a subobject thereof;左值到右值的转换,应用于引用联合或其子对象的非活动成员的左值;

and indeed, both GCC and Clang diagnose this error , as required during constant evaluation.事实上, GCC 和 Clang 都根据不断评估的要求诊断出这个错误

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

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