假设我有一个DataProcessor模板类,该类持有一个智能指针,该指针指向具有运算符*和运算符->的已处理数据:
template <class DataPointer>
class DataProcessor
{
public:
//it is not clear how to implement the constructor
//DataProcessor(DataPointer p) : pData(p) {};
void Process() { /* do something with *pData */ };
private:
DataPointer pData;
}
如何实现构造函数以使DataProcessor与std :: unique_ptr(构造函数应由&&接受并移动)和std :: shared_ptr(构造函数应由&接受并复制)一起工作?可以使用某种统一的构造函数吗?
实际上,我有一个类,其中包含一个智能Win32句柄UniqueHandle和SharedHandle,它们具有类似std :: unique_ptr和std :: shared_ptr的相似语义。因此,这是一个有关如何实现这种情况的普遍问题。
答案 0 :(得分:2)
您的选择本质上是这些:
按值获取参数
DataProcessor(DataPointer p) : pData(std::move(p)) {}
如果DataPointer
是仅移动的,则用户将不得不通过std::move
对其进行调用,这将移动构建p
,然后将其用于移动构建{{ 1}}。如果它是可复制的,则pData
将根据用户传递值的方式进行复制/移动。从那里,它将移动构造p
。
请注意,此版本增加了一个额外的移动操作。
始终通过右值引用获取参数
pData
在这种情况下,如果DataProcessor(DataPointer &&p) : pData(std::move(p)) {}
不是仅移动的,并且用户希望传递左值,则用户必须将值显式复制到用于初始化DataPointer
的临时目录中。看起来像这样:
p
DataProcessor<shared_ptr<T>> dp(shared_ptr{sp});
是您要复制的现有sp
所在的位置。给定要移动的对象时,此操作只会执行一次移动,但复制时会执行复制+移动操作。
编写两个函数,如果shared_ptr
是不可复制的,则使用SFINAE删除复制版本。此版本的优点是无需执行其他操作:
DataPointer