模板类的统一复制和移动构造函数

时间:2019-03-20 17:52:53

标签: c++ c++17

假设我有一个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的相似语义。因此,这是一个有关如何实现这种情况的普遍问题。

1 个答案:

答案 0 :(得分:2)

您的选择本质上是这些:

  1. 按值获取参数

    DataProcessor(DataPointer p) : pData(std::move(p)) {}
    

    如果DataPointer是仅移动的,则用户将不得不通过std::move对其进行调用,这将移动构建p,然后将其用于移动构建{{ 1}}。如果它是可复制的,则pData将根据用户传递值的方式进行复制/移动。从那里,它将移动构造p

    请注意,此版本增加了一个额外的移动操作。

  2. 始终通过右值引用获取参数

    pData

    在这种情况下,如果DataProcessor(DataPointer &&p) : pData(std::move(p)) {} 不是仅移动的,并且用户希望传递左值,则用户必须将值显式复制到用于初始化DataPointer的临时目录中。看起来像这样:

    p

    DataProcessor<shared_ptr<T>> dp(shared_ptr{sp}); 是您要复制的现有sp所在的位置。给定要移动的对象时,此操作只会执行一次移动,但复制时会执行复制+移动操作。

  3. 编写两个函数,如果shared_ptr是不可复制的,则使用SFINAE删除复制版本。此版本的优点是无需执行其他操作:

DataPointer