__has_trivial_copy在clang和gcc中的行为有所不同。谁是对的?

时间:2012-10-05 22:33:27

标签: c++ c++11

这两个编译器中的任何一个都不支持

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节中的标准描述了没有任何非平凡操作的简单可复制性。我想如果你按照书面标准阅读标准,铿锵可能是对的。

2 个答案:

答案 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)