unique_ptr
is required to support move-constructible deleters; 20.7.1.2.1 [unique.ptr.single.ctor]:
9 - [...] if [the deleter type]
D
is non-reference typeA
, then the [two-argument constructor] signatures are:unique_ptr(pointer p, const A& d); unique_ptr(pointer p, A&& d);
[...]
12 - Requires: [...]
- [if
d
is a non-const rvalue then]D
shall satisfy the requirements ofMoveConstructible
(Table 20), and the move constructor ofD
shall not throw an exception. Thisunique_ptr
will hold a value move constructed fromd
. [...]
If we explicitly add a move constructor and delete the copy constructor from LockDeleter
then we get a more informative error message; 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
Note the mention of std::_Unique_ptr_base<_Ty,_Dx,false>::_Unique_ptr_base(int *,_Dx)
; this indicates that the deleter parameter is incorrectly being copied into the internal base class, when it should be being moved.
The only workaround I can see is to make lock_
mutable, allowing a copy constructor to operate as a move constructor.