7

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 可能是对的。

4

2 回答 2

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()!我不确定这是否真的是故意的。

于 2012-10-05T22:52:16.080 回答
1

既不正确也不不正确,因为两者都在使用扩展。

警告:此答案基于 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)

于 2012-10-05T23:00:55.317 回答