在成员容器

时间:2016-05-28 21:22:07

标签: c++ c++11

假设我们有两种类型,T1T2

除了以下事实外,

T1并不重要:

  • 它不是可复制的构造
  • 它有一个移动构造函数
  • 我们有一个很好的功能,签名为T1 copy(T1 const& orig),可以创建副本。

T2可以简化为以下类:

// T2.h
class T2 {
public:
    T2() { /* initializes the vector with something */ }
    T2(T2 const& other);
private:
    std::vector<T1> v;
}

// T2.cpp

T2::T2(T2 const& other) : ... {}

如果您只能写入省略号部分或全局范围,您将如何实现此方法?

一个简单的真实世界用例 - 假设“你不能在花括号之间写任何东西”部分是一个现实世界的限制:

  • T1std::unique_ptr<anything>
  • copystd::make_unique
  • anything有一个复制构造函数

我还有两个额外的实施要求:

  • 性能。它不应该(相当)慢于复制构造函数体中for循环的朴素实现。
  • 可读性。问题背后的重点是做一些比琐碎的for循环更清晰/干净的东西(例如想象T2有两个或更多成员向量)。

可选,但很高兴有功能:

  • 易于推广到其他容器的东西
  • 适用于迭代器的东西
  • 通用的东西

澄清:我知道这个问题可以通过std::vector<T1> copy_vec(std::vector<T1> const& orig)全局函数轻松解决。将该函数放入T2.cpp内的匿名命名空间也会使其成为本地命名空间,但我会反对它的可读性,我认为它根本不会比for循环更好。如果复制构造函数不在实现文件中但在标题中内联,那么这显然是一个糟糕的解决方案。

所以重新解释我的问题是:

  • 是否已经实施了类似的内容,我可以加入哪些内容?
  • 如果没有,那么为什么?我不是说我考虑过每一个角落的情况,但我认为这可能是以一种很好的通用方式实现的,并且由于unique_ptr,这是一个很常见的案例。

1 个答案:

答案 0 :(得分:1)

天真循环没有错:

v.reserve(other.v.size());
for (auto& elem : other.v) {
    v.push_back(copy(elem));
}

这是可读和最佳的。

虽然我认为现代的,聪明的解决方案是使用range-v3

T2(T2 const& other)
: v(other.v | view::transform(copy))
{ } 

我不确定这比循环更好,以证明额外的复杂性,但YMMV。