Почему unique_ptr не может определить тип делетера?
Скажем, я хочу использовать пользовательский делетер с уникальным_ptr:
void custom_deleter(int* obj)
{
delete obj;
}
Зачем мне это писать:
std::unique_ptr<int, void(*)(int*)> x(new int, custom_deleter);
вместо этого:
std::unique_ptr<int> x(new int, custom_deleter); //does not compile
?
Нельзя ли вывести тип делетера?
Ответы
Ответ 1
Для unique_ptr
делетер является частью типа:
template <
class T,
class Deleter = std::default_delete<T>
> class unique_ptr;
Таким образом, когда вы строите объект, вам нужно указать его тип. Строка, которую вы пишете:
std::unique_ptr<int> x(new int, custom_deleter);
эквивалентно:
std::unique_ptr<int, std::default_delete<int> > x(new int, custom_deleter);
И вы не можете построить std::default_delete<int>
из custom_deleter
.
Единственный способ сделать вывод типа делетира - использовать вычитание шаблона на этой части:
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);
}
Ответ 2
Он не может вывести тип делетера, потому что unique_ptr
по умолчанию не имеет состояния, посвященного делетеру: дефолт по умолчанию не имеет состояния.
В вашем случае для делетера требуется значение состояния указателя, поэтому оно не может "соответствовать" в состоянии std::unique_ptr
(которое является только указателем на T
).
Это делает unique_ptr
легкую, почти бесплатную замену для владеющего указателя.
Дедуктин может быть выполнен, но он должен будет изменить тип результирующего unique_ptr
.
Для сравнения, shared_ptr
всегда имеет емкость состояний для делетера, двух разных счетчиков атомов и указателя на значение. Это более тяжелый вес, а не бесплатная замена для указателя.