[英]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.