以下代码打印是否std::atomic<bool>可简单复制:

#include <atomic>
#include <iostream>
#include <type_traits>

int main(){
    std::cout << std::is_trivially_copyable_v<std::atomic<bool>> << "\n";
}

它在 gcc 和 clang 上给出以下结果:

1

但在 MSVC 上的结果是:

0

还使用演示了所有 3 个编译器的行为static_assert

我认为标准以任何一种方式定义了平凡的可复制性。

哪个编译器是正确的(或者是特定于实现的)?

2

  • 3
    状态“std::atomic 既不可复制也不可移动。”现在也许对于atomic bool gcc 和 clang 已经实现了一种复制它的方法,但我建议遵循标准


    – 

  • 1


    – 



3 个回答
3

另请参阅:

删除的构造函数并非不重要。

的决议之前,要实现简单复制,所有复制/移动构造函数/赋值运算符都必须是简单的。是这样的std::atomic<bool>(都被删除了)

使用新的措辞,也必须不删除(在 C++20 中,“合格”,因为满足其约束)。

GCC 和 Clang 没有实现这一点。请参阅:

2

  • 这是否意味着 MSVC 就在这里,而 gcc/glang 不兼容?


    – 


  • 7
    @wohlstad 是的,MSVC 目前是正确的,GCC 和 clang 在 2016 年 2 月之前都是合规的


    – 

问题在于 trivially_copyable 的操作方式。您实际上无法复制 clang 上的原子:

这同样适用于自定义不可复制类型。因此,唯一的问题是是否允许 trivially_copyable 对于不可复制类型返回 true。也许有人会说,由于该类型无法复制,因此它没有重要的复制操作。虽然我自己的直觉是 is 应该给出“false” – 否则你必须在某些情况下检查 is_copyable 以及 trivally_copyable 。对标准有更多了解的人可能能够回答这个问题 – 我只能说,基于 Cpp-reference (),我没有看到任何本案例的要求。

1

  • 谢谢回答。尽管我可以从您所写的内容中看到原因,但我对可复制性和琐碎可复制性之间的依赖关系并不乐观。请参阅 Nifil 答案下的评论。


    – 


评论跟进:

声明“std::atomic 既不可复制也不可移动。”我建议遵循标准。

另外查看我们发现复制运算符已被删除。

关于 std::is_trivially_copyable_v 的返回值,我认为 @Juliean 的答案提供了一个很好的解释

6

  • 1
    先验的不可复制(即没有可行的复制构造函数)并不意味着std::trivially_copyable必须是false。 “简单可复制”是指通过复制字节进行复制,即绕过复制构造函数。


    – 


  • 谢谢回答。但我认为,如上所述,琐碎的可复制性是一个与“正常”可复制性/可移动性分开的概念。


    – 

  • @wohlstad 我从这里获取了定义 /… 一个简单可复制的类是一个至少有一个合格的复制构造函数、移动构造函数、复制赋值运算符或移动赋值运算符的类,每个合格的复制构造函数是平凡的 每个合格的移动构造函数都是平凡的 每个合格的复制赋值运算符都是平凡的 每个合格的移动赋值运算符都是平凡的,并且具有未删除的平凡析构函数。


    – 

  • 2
    恕我直言,你应该在答案中引用这句话。请注意,我并不是说你错了。我只是说你的答案做了一个无声的假设,如果一个类型不能通过复制构造函数复制,那么它就不能被简单地复制,我不认为这是显而易见的,它应该是答案的一部分。


    – 


  • 1
    顺便说一句,据我理解,当一个类有一个移动构造函数但没有其他移动或复制时就足够了,并且如果该移动构造函数很简单,那么其他项目符号也将被覆盖。 (仍然不是说你错了,只是想澄清我自己的困惑)


    –