__has_trivial_copy在clang和gcc中的行为不同.谁'是吗

__has_trivial_copy behaves differently in clang and gcc. Who's right?

本文关键字:是吗 copy trivial has clang gcc      更新时间:2023-10-16

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节中的标准从没有任何非琐碎操作的角度描述了琐碎的可复制性。我想如果你按照书面标准阅读,clang可能是对的。

clang的原生库

libc++支持std::is_trivially_copyable<T>,并且在您的示例中假装该类型是可复制的,尽管它显然不是可复制的。我认为,12.8[class.copy]第12段将删除的构造函数定义为非平凡的:

如果不是用户提供的,那么类X的复制/移动构造函数是微不足道的。。。

删除的声明显然是用户提供的。当我在这里说"清楚"时,我的意思是我不能立即用标准来支持它,即声明一个函数为已删除的函数视为用户提供的函数。。。

进一步的调查显示,8.4.2[dcl.fct.def.default]第4段(感谢Jesse Good提供的参考)使一个被删除的功能非用户提供:

。。。一个特殊的成员函数是用户提供的,如果它是用户声明的,并且在第一次声明时没有显式默认或删除。。。

因此,如果没有其他理由使复制构造函数被删除,则具有复制构造函数的类确实是可复制的(但这些都不适用于问题中的类型A)。这有点奇怪:类型类型不能使用其复制构造函数复制,但它可以使用std::memcpy()复制!我不确定这是否真的是故意的。

两者都不正确或不正确,因为两者都使用扩展。

警告:此答案基于C++11草案N3242中的单词,但不在最终标准中。所以它不是特别好。留待比较和讨论。

你似乎想问:std::is_trivially_copyable<A>::value(以及std::is_trivially_copy_constructible<A>::value)必须是false

12.8第13段:

如果X类的复制/移动构造函数既不是用户提供的也不是删除的,并且如果…

为了完整起见,

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)