Reputation: 1921
Let's say I want to use a custom deleter with an unique_ptr:
void custom_deleter(int* obj)
{
delete obj;
}
Why do I have to write this:
std::unique_ptr<int, void(*)(int*)> x(new int, custom_deleter);
instead of this:
std::unique_ptr<int> x(new int, custom_deleter); //does not compile
?
Can't the type of the deleter be inferred?
Upvotes: 11
Views: 544
Reputation: 275600
It cannot infer the type of the deleter, because unique_ptr
by default has no state devoted to a deleter: the default deleter is stateless.
In your case, the deleter needs a pointer's worth of state, so it cannot 'fit' within the std::unique_ptr
's state (which is just a pointer to a T
).
This makes unique_ptr
a lightweight, nearly cost-free replacement for an owning pointer.
Deductin could be done, but it would have to change the type of the resulting unique_ptr
.
In comparison, shared_ptr
always has state capacity for a deleter, two different atomic counters, and a pointer to value. It is heavier weight, and not a cost-free replacement for a pointer.
Upvotes: 3
Reputation: 303217
For unique_ptr
, the deleter is part of the type:
template <
class T,
class Deleter = std::default_delete<T>
> class unique_ptr;
As such, when you're constructing an object, you need to specify its type. The line you're writing:
std::unique_ptr<int> x(new int, custom_deleter);
is equivalent to:
std::unique_ptr<int, std::default_delete<int> > x(new int, custom_deleter);
And you cannot construct a std::default_delete<int>
from custom_deleter
.
The only way to infer the deleter type is to use template deduction on that part too:
template <typename T, typename Deleter>
std::unique_ptr<T, Deleter> make_unique_ptr(T* ptr, Deleter deleter) {
return std::unique_ptr<T, Deleter>(ptr, deleter);
}
Upvotes: 6