C++ 17的当前标准(我已经观察到类似于C++ 11的措辞)对于简单的可复制类型具有非常混乱的措辞.我首先使用以下代码(GCC 5.3.0)偶然发现了这个问题:
class TrivialClass {};
std::is_trivially_copyable<int volatile>::value; // 0
std::is_trivially_copyable<TrivialClass volatile>::value; // 1 ??
Run Code Online (Sandbox Code Playgroud)
让混乱更加糟糕,我试着检查std::is_trivial一下这件事情有什么说法,只是让人更加困惑.
class TrivialClass {};
std::is_trivial<int volatile>::value; // 1 ??
std::is_trivial<TrivialClass volatile>::value; // 1
Run Code Online (Sandbox Code Playgroud)
很困惑,我检查了最新的C++ 17草案,看看是不是有问题,我发现了一些有些含糊不清的措辞可能是罪魁祸首:
http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4567.pdf#page.73
cv-非限定标量类型,平凡可复制类类型(第9节),此类类型的数组以及这些类型的非易失性const限定版本(3.9.3)统称为平凡可复制类型.
以下是关于平凡可复制类的信息:
http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4567.pdf#page.226
一个简单的可复制类是一个类:
- (6.1)没有非平凡的复制构造函数(12.8),
- (6.2)没有非平凡的移动构造函数(12.8),
- (6.3)没有非平凡的副本分配操作员(13.5.3,12.8),
- (6.4)没有非平凡的移动指派算子(13.5.3,12.8),和
- (6.5)有一个简单的析构函数(12.4).
http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4567.pdf#section.12.8
构造函数:
如果不是用户提供的,则类X的复制/移动构造函数是微不足道的,其参数类型列表等效于隐式声明的参数类型列表,如果
- (12.1)类X没有虚函数(10.3),没有虚基类(10.1),和
- (12.2)类X 没有volatile限定类型的非静态数据成员,和
- (12.3)选择复制/移动每个直接基类子对象的构造函数是微不足道的,并且
- (12.4)对于类型(或其数组)的X的每个非静态数据成员,选择复制/移动该成员的构造函数是微不足道的;
否则复制/移动构造函数是非平凡的.
分配:
如果类X不是用户提供的,则类X的复制/移动赋值运算符是微不足道的,其参数类型列表等效于隐式声明的参数类型列表,如果
- (25.1)类X没有虚函数(10.3),没有虚基类(10.1),和
- (25.2)类X 没有volatile限定类型的非静态数据成员,和
- (25.3)选择复制/移动每个直接基类子对象的赋值运算符是微不足道的,并且
- (25.4)对于类型(或其数组)的X的每个非静态数据成员,选择复制/移动该成员的赋值运算符是微不足道的;
否则复制/移动赋值运算符是非常重要的.
注意:更新了此部分以及更多信息.我现在相信这是GCC中的一个错误.然而,仅凭这一点并不能回答我的所有问题.
我可以看到,也许是因为TrivialClass没有非静态成员,因为它会传递上述规则,所以我添加了一个int,它仍然可以简单地复制.
class TrivialClass { …Run Code Online (Sandbox Code Playgroud)