c++ - 模板类的统一复制和移动构造函数
问题描述
假设我有一个 DataProcessor 模板类,它包含一个智能指针,指向具有 operator * 和 operator -> 的已处理数据:
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。因此,如何实现这样的场景是一个普遍的问题。
解决方案
您的选择基本上是这些:
按值取参数:
DataProcessor(DataPointer p) : pData(std::move(p)) {}
如果
DataPointer
是 move-only,那么用户必须通过 调用它std::move
,这将p
是 move-construct ,然后用于 move-constructpData
。如果它是可复制的,那么p
将根据用户传递值的方式来构造复制/移动。从那里,它将移动构造pData
。请注意,此版本添加了额外的移动操作。
通过右值引用获取参数,始终:
DataProcessor(DataPointer &&p) : pData(std::move(p)) {}
在这种情况下,如果
DataPointer
不是仅移动,并且用户想要传递一个左值,则用户必须显式将该值复制到用于初始化的临时值中p
。看起来像这样:DataProcessor<shared_ptr<T>> dp(shared_ptr{sp});
您要从中复制
sp
的现有对象在哪里。shared_ptr
当给定一个要移动的对象时,这只会移动一次,但在复制时会进行复制+移动。DataPointer
编写两个函数,如果不可复制,则使用 SFINAE 删除复制版本。这个版本的优点是不需要做额外的动作:
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) {}
推荐阅读
- hadoop - 气流:如何重新运行依赖的 DAG
- google-chrome - 如何(重新)将浏览器窗口插入 Chromium 的标签栏?
- c# - 成功注册/登录后不显示 LOGOUT 按钮,ASP.NET Core 标识
- typescript - 从通用类型中提取类型或接口名称作为 Typescript 中的字符串
- rendering - 如何修复模糊的 VS2019
- usb - 在 ubuntu 18.04 的某些条件下,用户配置从 70-snap.core.rules 文件中删除
- r - 根据一个变量的值在堆叠条形图中排列堆叠
- sass - 尝试使用新的 @use 语法在 create-react-app 中使用 sass 模块但收到错误
- javascript - setInterval 不是每秒刷新数据
- javascript - 通过 Fetch API 验证登录