使用constexpr
和union
我发现,我无法更改union
中constexpr
的有效成员。只有一个例外:union
个空类。
constexpr bool t()
{
struct A {};
struct B {};
union U { A a; B b; } u{};
u.a = A{};
u.b = B{};
return true;
}
static_assert(t());
constexpr bool f()
{
struct A { char c; };
struct B { char c; };
union U { A a; B b; } u{};
u.a = A{};
u.b = B{}; // error originating from here
return true;
}
static_assert(f());
第一个函数可能会产生常量表达式。但第二个不能。硬错误说:
main.cpp:23:15: error: static_assert expression is not an integral constant expression
static_assert(f());
^~~
main.cpp:20:11: note: assignment to member 'b' of union with active member 'a' is not allowed in a constant expression
u.b = B{};
^
main.cpp:20:9: note: in call to '&u.b->operator=(B{})'
u.b = B{};
^
main.cpp:23:15: note: in call to 'f()'
static_assert(f());
^
1 error generated.
1。)是否可以在常量表达式中更改union
的活动成员?
我试图破坏活动成员,但是由于析构函数通常不是constexpr
,所以不允许这样做。我还尝试使用展示位置operator new
(::new (&u.b) B{2};
),但也尝试使用不成功。 reinterpret_cast
也不允许使用常量表达式。也禁止改变共同初始子序列的成员。
2。)有没有办法让变量(在改变主动替代类型的意义上)文字boost::variant
- 类似?如果可能,它的存储效果如何?
3。)在运行时分配给union
非常活跃的可分配类型的成员是不明确的行为?使用展示位置union
构建非常活跃的operator new
成员的非活跃成员是否是未定义的行为,从而避免在运行时初步销毁活动成员?
我可以更改整个文字类型union
,但不能更改其非活动成员:
constexpr
bool
f()
{
struct A { char c; };
struct B { char c; };
union U
{
A a; B b;
constexpr U(A _a) : a(_a) { ; }
constexpr U(B _b) : b(_b) { ; }
};
U a(A{});
a.a = A{}; // check active member is A
U b(B{});
b.b = B{}; // check active member is B
a = b;
a = B{}; // active member is B!
return true;
}
static_assert(f());
因此,对于简单可复制类型的文字类型variant
,转换赋值运算符将为template< typename T > constexpr variant & operator = (T && x) { return *this = variant(std::forward< T >(x)); }
。
答案 0 :(得分:4)
免责声明:&#34;活跃&#34;在P0137R0中定义。
是否可以在常量中更改union的活动成员 表达式?
不直接,因为禁止修改非活跃成员 - [expr.const] /(2.8):
- 左值到右值的转换(4.1)或修改(5.18,5.2.6, 5.3.2),应用于引用联合或其子对象的非活动成员的glvalue;
然而,这个措辞似乎有缺陷,因为它确实可以修改&#34;通过分配另一个union对象的非活动成员,如示例所示。实际上,复制赋值运算符执行基础字节的副本和有关活动成员的内部信息:
联合
X
副本的隐式定义的复制赋值运算符X
的对象表示(3.9)。
是否定义了非活动成员的未定义行为 在运行时简单地复制可分配类型的联合?
对于一个简单的可复制类类型的对象来说,这可能是好的,因为那些具有简单的析构函数和复制构造函数/赋值运算符。虽然未说明,但CWG #1116似乎意味着它的目的是:
我们永远不会说联盟的活跃成员是什么,怎么可能 改变了,等等。标准没有明确是否 以下是有效的:
union U { int a; short b; } u = { 0 }; int x = u.a; // presumably this is OK, but we never say that a is the active member u.b = 0; // not clear whether this is valid