简体   繁体   English

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

[英]A uniform copy and move constructor of a template class

Let assume I have a DataProcessor template class that holds a smart pointer to the processed data that has operator * and operator ->: 假设我有一个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;
}

How to implement the constructor to make DataProcessor work with both std::unique_ptr (the constructor should accept it by && and move it) and std::shared_ptr (the constructor should accept it by & and copy it)? 如何实现构造函数以使DataProcessor与std :: unique_ptr(构造函数应由&&接受并将其移动)和std :: shared_ptr(构造函数应由&接受并复制)一起使用? Is it possible to have some kind of a uniform constructor? 是否可以使用某种统一的构造函数?

Actually I have a class that holds a smart Win32 handle UniqueHandle and SharedHandle that have the similar semantics like std::unique_ptr and std::shared_ptr. 实际上,我有一个类,拥有一个智能Win32句柄UniqueHandle和SharedHandle,它们具有类似std :: unique_ptr和std :: shared_ptr的类似语义。 So it is a general question on how to implement a scenario like this. 因此,这是一个关于如何实现这种情况的普遍问题。

Your choices are essentially these: 您的选择基本上是这些:

  1. Take the parameter by value: 按值取参数:

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

    If DataPointer is move-only, then the user will have to call it through std::move , which will move-construct p , which is then used to move-construct pData . 如果DataPointer仅是移动的,则用户将必须通过std::move调用它,它将移动结构p ,然后将其用于移动结构pData If it is copyable, then p will be copy/move constructed based on how the user passes the value. 如果它是可复制的,则将根据用户如何传递值来复制/移动p From there, it will move construct pData . 从那里,它将移动构造pData

    Note that this version adds an additional move operation. 请注意,此版本添加了附加的移动操作。

  2. Take the parameter by rvalue reference, always: 始终通过右值引用获取参数:

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

    In this case, if DataPointer is not move-only, and the user wants to pass an lvalue, the user must explicitly copy the value into a temporary used to initialize p . 在这种情况下,如果DataPointer不是仅移动的,并且用户希望传递左值,则用户必须将值显式复制到用于初始化p的临时目录中。 That would look something like this: 看起来像这样:

     DataProcessor<shared_ptr<T>> dp(shared_ptr{sp}); 

    Where sp is an existing shared_ptr that you want to copy from. 其中sp是要从中复制的现有shared_ptr This does only one move when given an object to move from, but does a copy+move when copying. 给定要移动的对象时,此操作仅执行一次移动,但复制时执行复制+移动操作。

  3. Write two functions, employing SFINAE to remove the copying version if DataPointer is non-copyable. 编写两个函数,如果DataPointer是不可复制的,则使用SFINAE删除复制版本。 This version has the advantage of doing no additional moves: 此版本的优点是无需执行其他任何操作:

DataProcessor(DataPointer &&p) : pData(std::move(p)) {}
template<typename T = DataPointer>
DataProcessor(std::enable_if_t<std::is_copy_constructible_v<T>, const T&> p)
        : pData(p) {}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM