在成员容器中复制具有仅可移动但可克隆类型的构造函数
Copy constructors with move-only, but cloneable types in member containers
假设我们有两种类型,T1
和T2
。
除了以下事实之外,T1
并不重要:
- 它是不可复制的
- 它有一个move构造函数
- 我们有一个优秀的函数,签名
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) : ... {}
如果只能写入省略号部分或全局范围,您将如何实现此方法?
一个简单的现实世界用例——假设"你不能在大括号之间写任何东西"部分是现实世界的限制:
T1
就是std::unique_ptr<anything>
copy
就是std::make_unique
anything
有一个复制构造函数
我还有两个额外的实现要求:
- 性能。它不应该比复制构造函数主体中有
for
循环的天真实现慢(相当) - 可读性。这个问题背后的全部要点是做一些比循环的琐碎更清晰/干净的事情(例如,想象T2有两个或多个成员向量)
可选,但很高兴拥有以下功能:
- 很容易推广到其他容器的东西
- 只使用迭代器的东西
- 一般的东西
澄清:我知道这个问题用std::vector<T1> copy_vec(std::vector<T1> const& orig)
全局函数是平凡可解的。将该函数放入T2.cpp
中的匿名命名空间也会使其成为本地函数,但我反对它的可读性,我认为它根本不会比for循环更好。如果复制构造函数不在实现文件中,而是内联在头中,那么这显然是一个糟糕的解决方案。
因此,我的问题的措辞是:
- 是否已经实现了类似的东西,我可以将其包括在内
- 如果没有,为什么?我并不是说我考虑了每一个角落的情况,但我认为这是一种可能以良好的通用方式实现的东西,多亏了
unique_ptr
,这是一个足够常见的情况
天真循环没有错:
v.reserve(other.v.size());
for (auto& elem : other.v) {
v.push_back(copy(elem));
}
这是可读性很强的,也是最佳的。
虽然我想现代,聪明的解决方案是使用范围-v3:
T2(T2 const& other)
: v(other.v | view::transform(copy))
{ }
我不确定这是否比循环更好来证明额外的复杂性,但YMMV。
相关文章:
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 构造函数正在调用一个使用当前类类型的函数
- 如何修复函数样式强制转换或类型构造的预期"("?
- 具有默认模板类型的默认构造函数的类型推导
- C++LinkedList问题.数据类型之间存在冲突?没有匹配的构造函数
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- 在 c++ 中的模板实例化中使用带有构造函数的类作为类型参数
- 不命名构造函数和析构函数上的类型错误
- 具有自定义构造函数 (C++) 的类型的动态数组分配
- C++方法是否可以根据传递给构造函数的参数具有不同的返回类型?
- 创建类类型的动态分配数组,其中类不得具有默认构造函数
- 初始化自定义类型构造函数的数组
- OpenGL着色器错误C1068:类型构造函数中的数据过多
- Lambda 闭包类型构造函数
- 仅当基础类型具有模板类型构造函数时,才实现这些构造函数
- 模板类的构造函数在使用 new 关键字时调用类型构造函数
- 如何强制函数参数为相同类型,并且不允许使用类型构造函数与给定类型匹配
- 模板类型构造函数参数
- 它们是c++中的类型构造函数
- 解析C++类型构造函数