std::is_trivially_copyable
(至少就gcc 4.6而言)。但两者都提供了__has_trivial_copy
指令,这些指令做得非常好。
除了它被删除的复制构造函数。
struct A { A(A const&) =delete; };
__has_trivial_copy(A)
在clang中返回1,在gcc中返回0。
我正在挖掘标准,但是找不到一个条款,说明当复制构造函数被删除时,该类是否仍然被认为是可以复制的。
谁是对的?
我倾向于相信gcc是对的,因为struct A
根本不可复制,更不用说可以复制了。此外,还有一个广泛的共识,即删除的拷贝构造函数可以被视为私有声明但未定义的构造函数,在这种情况下gcc仍然是正确的。
另一方面,第9/6节中的标准描述了没有任何非平凡操作的简单可复制性。我想如果你按照书面标准阅读标准,铿锵可能是对的。
答案 0 :(得分:5)
libc ++,clang的本地库,支持std::is_trivially_copyable<T>
,实际上,假装你的例子,该类型可以轻易复制,尽管它显然不是可轻易复制的。我认为,12.8 [class.copy]第12段将删除的构造函数定义为非平凡的:
如果不是用户提供的话,X类的复制/移动构造函数是微不足道的......
删除的声明显然是用户提供的。当我在这里说“清楚”时,我的意思是我不能立即通过宣布删除函数的标准来支持它,因为用户提供了......
进一步调查显示,8.4.2 [dcl.fct.def.default]第4段(感谢Jesse Good提供参考)使得用户提供的删除功能无法提供:
...特殊成员函数是用户提供的,如果它是用户声明的,并且在其第一个声明中未明确默认或删除。 ...
因此,如果没有其他理由可以进行非平凡的可复制,那么具有已删除的复制构造函数的类确实可以轻易地复制(但这些都不适用于问题中的A
类型。这有点奇怪:无法使用其复制构造函数复制类型类型,但可以使用std::memcpy()
复制 !我不确定这是否真的是故意的。
答案 1 :(得分:1)
两者都不正确或不正确,因为两者都使用扩展名。
警告:这个答案基于C ++ 11草案N3242中的单词,但不在最终的标准中。所以它并不是特别好。留下来进行比较和讨论。
您想要问的是:std::is_trivially_copyable<A>::value
(以及std::is_trivially_copy_constructible<A>::value
)必须是false
。
12.8第13段:
类
X
的复制/移动构造函数是微不足道的,如果既不是用户提供也不是删除,如果.... {/ p>
只是为了完成,
9第6段:
平易可复制的类是一个类:
- 没有非平凡的副本构造函数(12.8),
- 没有非平凡的移动构造函数(12.8),
- 没有非平凡的复制赋值运算符(13.5.3,12.8),
- 没有非平凡的移动赋值运算符(13.5.3,12.8)和
- 有一个简单的析构函数(12.4)。
3.9第9段:
标量类型,简单的可复制类类型(第9节),此类类型的数组以及这些类型的cv限定版本(3.9.3)统称为普通可复制类型。
20.9.4.3表49:
模板:
template <class T> struct is_trivially_copyable;
条件:
T
是一个简单的可复制类型(3.9)