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.
哪个编译器是正确的?
两个编译器都是正确的,即使代码是 ill-formed,因为您显示的程序不需要诊断。确实 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.
(强调我的)
由于不需要诊断,允许GCC不诊断。
另一方面,如果您尝试将 f
计算为常数,例如
constexpr float a = f();
那么就违反了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:
- 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;
事实上,both GCC and Clang diagnose this 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.
哪个编译器是正确的?
两个编译器都是正确的,即使代码是 ill-formed,因为您显示的程序不需要诊断。确实 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.
(强调我的)
由于不需要诊断,允许GCC不诊断。
另一方面,如果您尝试将 f
计算为常数,例如
constexpr float a = f();
那么就违反了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:
- 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;
事实上,both GCC and Clang diagnose this error,根据不断评估的要求。