在 constexpr 表达式中检查具有公共初始序列的联合的非活动成员
Inspect inactive member of a union with common initial sequence in constexpr expression
C++ 标准第 12.3.1 点说:
If a standard-layout union contains several standard-layout structs that share a common initial sequence, and if a non-static data member of an object of this standard-layout union type is active and is one of the standard-layout structs, it is permitted to inspect the common initial sequence of any of the standard-layout struct members;
但是以下代码无法在任何主要编译器 (https://godbolt.org/z/3jM1co) 上编译:
struct type {
union {
int a;
int b;
};
constexpr type(int n) : a(n) {}
};
constexpr int fun(int n) {
type t(n);
return t.b;
}
constexpr int res = fun(5);
为什么代码无法编译(我相信这里所有的编译器都没有错)?此代码应满足访问技术上不活跃的联合成员的条件(标准布局,公共初始序列)。当删除 constexpr
关键字时,这段代码编译没有问题。
您引用的文本是正确的,但在 constexpr 上下文中访问联合体的非活动成员还有其他限制。特别是,您违反了此 rule:
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;
请注意,您可以在 constexpr 上下文中更改联合的活动成员,因此您可以这样做:
constexpr int fun(int n)
{
type t(n);
t.b = t.a; // t.b is now the active member
return t.b; // ok, reading from active member is fine
}
我相信只有 c++20 才允许这样做:demo.
相关的rule是这样的:
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 invocation of an implicitly-defined copy/move constructor or copy/move assignment operator for a union whose active member (if any) is mutable, unless the lifetime of the union object began within the evaluation of E;
(重点是我的)。由于 t
的生命周期从 fun
的计算开始,这是允许的。
C++ 标准第 12.3.1 点说:
If a standard-layout union contains several standard-layout structs that share a common initial sequence, and if a non-static data member of an object of this standard-layout union type is active and is one of the standard-layout structs, it is permitted to inspect the common initial sequence of any of the standard-layout struct members;
但是以下代码无法在任何主要编译器 (https://godbolt.org/z/3jM1co) 上编译:
struct type {
union {
int a;
int b;
};
constexpr type(int n) : a(n) {}
};
constexpr int fun(int n) {
type t(n);
return t.b;
}
constexpr int res = fun(5);
为什么代码无法编译(我相信这里所有的编译器都没有错)?此代码应满足访问技术上不活跃的联合成员的条件(标准布局,公共初始序列)。当删除 constexpr
关键字时,这段代码编译没有问题。
您引用的文本是正确的,但在 constexpr 上下文中访问联合体的非活动成员还有其他限制。特别是,您违反了此 rule:
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;
请注意,您可以在 constexpr 上下文中更改联合的活动成员,因此您可以这样做:
constexpr int fun(int n)
{
type t(n);
t.b = t.a; // t.b is now the active member
return t.b; // ok, reading from active member is fine
}
我相信只有 c++20 才允许这样做:demo.
相关的rule是这样的:
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 invocation of an implicitly-defined copy/move constructor or copy/move assignment operator for a union whose active member (if any) is mutable, unless the lifetime of the union object began within the evaluation of E;
(重点是我的)。由于 t
的生命周期从 fun
的计算开始,这是允许的。