为什么不能 std::tuple<int>可以轻松复制吗?
用这个在线编译器构建,代码如下:
#include <iostream>
#include <type_traits>
#include <tuple>
int main() {
std::cout << std::is_trivially_copyable<std::tuple<int>>::value << std::endl;
std::cout << std::is_trivially_copyable<std::pair<int, int>>::value << std::endl;
std::cout << std::is_trivial<std::tuple<int>>::value << std::endl;
std::cout << std::is_trivial<std::pair<int, int>>::value << std::endl;
return 0;
}
输出:
0
0
0
0
我在 Visual Studio 2015 中得到了相同的结果.
I'm getting the same results with Visual Studio 2015.
为什么会这样?POD 类型的 std::tuple
是否有正当理由,更不用说简单的 std::pair
不能轻易复制了?我假设他们的实现提供了一些自定义赋值运算符,但它们与编译器生成的默认版本有什么不同?
Why is that the case? Is there a valid reason an std::tuple
of POD types, let alone a simple std::pair
, couldn't be trivially copyable? I presume their implementations provide some custom assignment operators, but how would they be different from the default versions generated by the compiler?
推荐答案
就琐碎的可复制性而言,绊倒 pair
的是标准不要求 复制/移动赋值运算符是微不足道的.该标准明确声明复制/移动 构造函数 是默认的,但对于分配而言并非如此.实现也可以默认它们,但标准不需要它.
The thing that trips pair
up as far as trivial copyability is concerned is that the standard does not require that the copy/move assignment operators be trivial. The standard explicitly declares that the copy/move constructors are defaulted, but not so for the assignments. An implementation could default them as well, but the standard does not require it.
标准不需要它并没有很好的理由.但事实并非如此.
There's no really good reason why the standard doesn't require it. But it doesn't.
对于 tuple
,事情要复杂得多.许多 tuple
实现基于具有正确大小/对齐的存储缓冲区,并使用放置 new
来构造该缓冲区中的各个成员.这一切都很好,但是这种类型必须实现手动复制/移动构造函数,因为它必须调用每种类型的复制/移动构造函数.即使它知道它们都可以简单地复制并通过 memcpy
复制它们,这仍然是手动操作.这使它失去了微不足道的可复制性.
For tuple
, things are a lot more complicated. Many tuple
implementations are based on having a storage buffer of the right size/alignment, and using placement new
to construct the individual members within that buffer. That's all fine and good, but such a type has to implement a manual copy/move constructor, since it must call the copy/move constructor of each type. Even if it knew that they were all trivially copyable and copied them via memcpy
, that's still a manual operation. And that disqualifies it from trivial copyability.
现在,tuple
的实现如果类型是可轻松复制的,则可以轻松复制.但是没有要求以这种方式实现它们.如果所有类型都可以轻松复制,则要求它们以一种方式实现自己,否则会以不同的方式实现它们,这将使 tuple
实现变得非常复杂.
Now, there are implementations of tuple
which could be trivially copyable if the types are trivially copyable. But there is no requirement to implement them that way. And it would complicate tuple
implementations tremendously to do require them to implement themselves one way if all the types are trivially copyable, and implement them in a different way otherwise.
相关文章