C++ 为什么在std::optional的一些实现中有一个虚拟的联合成员?
libstdc++(GNU)和libc++(LLVM)都使用一个并集实现C++ 为什么在std::optional的一些实现中有一个虚拟的联合成员?,c++,c++17,optional,unions,C++,C++17,Optional,Unions,libstdc++(GNU)和libc++(LLVM)都使用一个并集实现std::optional值存储,并且它们都包含一个伪成员 GNU实施: using _Stored_type = remove_const_t<_Tp>; struct _Empty_byte { }; union { _Empty_byte _M_empty; _Stored_type _M_payload; }; union { char __null_state_; va
std::optional
值存储,并且它们都包含一个伪成员
GNU实施:
using _Stored_type = remove_const_t<_Tp>;
struct _Empty_byte { };
union {
_Empty_byte _M_empty;
_Stored_type _M_payload;
};
union
{
char __null_state_;
value_type __val_;
};
我的问题是:为什么我们需要这些
\u M_empty
/\u null\u state\u
成员?单成员联合有什么问题吗?单成员联合在尝试默认可构造且与constexpr兼容时会产生各种各样的问题
考虑以下代码:
struct nontrivial {
constexpr nontrivial(int o) : u{o} {}
int u;
};
union storage {
nontrivial nt;
};
struct optional {
storage s;
};
constexpr auto run() -> int {
optional o;
return o.s.nt.u;
}
int main() {
constexpr int t = run();
}
这是格式错误的,因为optional
有一个已删除的构造函数
然后,一个简单的修复方法是添加一个构造函数,该构造函数不初始化任何联合成员:
union storage {
constexpr storage() {} // standard says no
nontrivial nt;
};
但这行不通。Constexpr联合必须至少有一个活动成员。它不可能是一个空的联盟。为了解决此限制,添加了一个虚拟成员。这使得std::可选在constexpr上下文中可用
(谢谢@Barry!)来自(我的):
函数体为not=delete的constexpr构造函数的定义还应满足以下要求:
- 如果类是具有可变成员([class.union])的并集,则应仅初始化其中一个强>
- 如果类是一个类似于并集的类,但不是并集,则对于其具有变体成员的每个匿名并集成员,应仅初始化其中一个
- 对于非委托构造函数,为初始化非静态数据成员和基类子对象而选择的每个构造函数都应该是constexpr构造函数
- 对于委托构造函数,目标构造函数应为constexpr构造函数
对于那些寻找标准报价的人:@TEDLYNGOM,哪个版本?在7.4.0上试用-出现错误。@r3musn0x 9.1.1。我不认为7.4.0实现了。@TedLyngmo,在我看来,LWG 2900只与optional的库实现相关,所以我看不到真正的联系。。。无论如何,看-一个错误!:)@r3musn0x您可能是对的。这里有一个g++和clang++之间的错误报告,还有一个似乎与此相关的错误报告:当涉及到模板时,它似乎击中了我的示例,但在错误报告中,它们设法在没有模板的情况下触发了错误。