[英]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: 您的选择基本上是这些:
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. 请注意,此版本添加了附加的移动操作。
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. 给定要移动的对象时,此操作仅执行一次移动,但复制时执行复制+移动操作。
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.