Reputation: 9612
Got some questions when using the unique_ptr
and tried to read the source but more questions emerge.
The template parameter Deleter
in unique_ptr<class Tp, class Deleter = default_delete<Tp>>
is a class other than a template so I wonder if it uses some tricks like the allocator::rebind
(discussion found here). But no, it must have an exact operator()(pointer)
overload.
So I turned to the STL source (in Ubuntu 14.04 gcc 4.8) and find that a nested _Pointer
class is defined for some type traits, but absolutely nothing to do with rebinding the Deleter
type to something compatible with the pointer type.
// /usr/include/c++/4.8/bits/unique_ptr.h:112
class _Pointer
{
template<typename _Up>
static typename _Up::pointer __test(typename _Up::pointer*);
template<typename _Up>
static _Tp* __test(...);
// _Dp is the Deleter type
typedef typename remove_reference<_Dp>::type _Del;
public:
typedef decltype(__test<_Del>(0)) type;
};
// /usr/include/c++/4.8/bits/unique_ptr.h:130
// adopt the pointer type provided by the _Pointer
typedef typename _Pointer::type pointer;
I've no idea what that class is supposed to do but it seems the Tp
parameter can be overrided. To test it I've fabricated some weird codes like this
struct MyDeleter {
// in the deleter type, define the pointer as pointer to int
typedef int* pointer;
void operator()(pointer p)
{
delete p;
}
};
int main()
{
// this won't compile!
std::unique_ptr<double, MyDeleter> p(new double(0));
// this type is equivalent to std::unique_ptr<int, MyDeleter>
std::unique_ptr<double, MyDeleter> p(new int(0));
return 0;
}
I'm completely confused. Would anybody explain that
unique_ptr
?Upvotes: 3
Views: 177
Reputation: 92271
The rules say that if MyDeleter
has a nested type pointer
, then that type is used. Otherwise std::unique_ptr<double, MyDeleter>
will use double*
formed from the first parameter.
And the pointer you store must match the resulting pointer type of the unique_ptr
, otherwise the final delete would be UB.
So, in the first case of std::unique_ptr<double, MyDeleter> p(new double(0));
you try to store a double*
when the deleter expects an int*
. That will never work, so it's good that the compiler catches it.
Upvotes: 1