我一直在寻找另一个问题(this one)的解决方案。似乎应该可以为可以解锁互斥锁的unique_ptr
实例创建自定义删除器。
例如,
#include <mutex>
#include <memory>
struct LockDeleter
{
std::unique_lock<std::mutex> lock_;
LockDeleter(std::mutex& m) : lock_(m) {}
void operator()(void*) { lock_.unlock(); }
};
int main()
{
std::mutex moo;
{
std::unique_ptr<int, LockDeleter> ptr(new int(42), LockDeleter(moo));
}
}
在VS2013 express下编译,我得到了
错误1错误C2280:&#39; std :: unique_lock :: unique_lock(const std :: unique_lock&amp;)&#39; :尝试引用已删除的函数
和
此诊断发生在编译器生成的函数&#39; LockDeleter :: LockDeleter(const LockDeleter&amp;)&#39;
现在,我似乎无法强制移动锁删除器实例,而不是使用std::move
复制...甚至向{{添加显式移动构造函数1}}没有帮助,删除的拷贝构造函数仍然被调用。
那么,我是在做傻事,还是LockDeleter
删除者总是可以复制?
答案 0 :(得分:1)
unique_ptr
需要支持可移动构造的删除者; 20.7.1.2.1 [unique.ptr.single.ctor] :
9 - [...]如果[删除者类型]
D
是非引用类型A
,那么[双参数构造函数]签名是:unique_ptr(pointer p, const A& d); unique_ptr(pointer p, A&& d);
[...]
12 - 需要: [...]
- [if
d
是非const rvalue,然后D
应满足MoveConstructible
的要求(表20),D
的移动构造函数不得抛出一个例外。此unique_ptr
将保留从d
构建的值移动。 [...]
如果我们显式添加一个移动构造函数并从LockDeleter
删除复制构造函数,那么我们会得到一条信息更丰富的错误消息; http://rextester.com/XFYUG91939:
Error(s):
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\memory(1243) : error C2280: 'LockDeleter::LockDeleter(const LockDeleter &)' : attempting to reference a deleted function
source_file.cpp(10) : see declaration of 'LockDeleter::LockDeleter'
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\memory(1241) : while compiling class template member function 'std::_Unique_ptr_base<_Ty,_Dx,false>::_Unique_ptr_base(int *,_Dx)'
with
[
_Ty=int
, _Dx=LockDeleter
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\memory(1380) : see reference to function template instantiation 'std::_Unique_ptr_base<_Ty,_Dx,false>::_Unique_ptr_base(int *,_Dx)' being compiled
with
[
_Ty=int
, _Dx=LockDeleter
]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\memory(1331) : see reference to class template instantiation 'std::_Unique_ptr_base<_Ty,_Dx,false>' being compiled
with
[
_Ty=int
, _Dx=LockDeleter
]
source_file.cpp(20) : see reference to class template instantiation 'std::unique_ptr<int,LockDeleter>' being compiled
请注意提及std::_Unique_ptr_base<_Ty,_Dx,false>::_Unique_ptr_base(int *,_Dx)
;这表示当删除参数被移动时,它被错误地复制到内部基类中。
我能看到的唯一解决方法是使lock_
变为可变,允许复制构造函数作为移动构造函数运行。