Как использовать std::remove_pointer с void *?

#c #unique-ptr #void-pointers #typetraits

#c #уникальный-ptr #void-указатели #typetraits

Вопрос:

Я использую std::unique_ptr таким образом:

 template <typename Pointer, auto deleter>
using my_unique_ptr = std::unique_ptr<std::remove_pointer<Pointer>, std::integral_constant<decltype(deleter), deleter>>;
 

Кажется, это работает, когда Pointer = void* , но при попытке использовать reset для такого my_unique_ptr , я получаю эту ошибку:

 invalid conversion from 'SampleType' {aka 'void*'} to 'std::unique_ptr<std::remove_pointer<void*>, std::integral_constant<...> >::pointer' {aka 'std::remove_pointer<void*>*'}
 

Не std::remove_pointer<void*>* должно автоматически означать void* ?

Ответ №1:

Ваш my_unique_ptr<void*> не содержит void* . Он содержит std::remove_pointer<void*>* .

Не std::remove_pointer<void*>* должно автоматически означать void* ?

std::remove_pointer Тип не является волшебным. Это такой же тип, как и любой другой. Вот возможная реализация:

 template<typename T>
struct remove_pointer {
    using type = T;
};

template<typename T>
struct remove_pointer<T*> {
    using type = T;
};
 

Как вы можете видеть, как вы его определили, std::unique_ptr содержит указатель на эту структуру, как и упомянутая ошибка компилятора.

То, что вы, вероятно, хотели сделать, это использовать член ::type структуры, он же результат remove_pointer метафункции:

 template <typename Pointer, auto deleter>
using my_unique_ptr = std::unique_ptr<typename std::remove_pointer<Pointer>::type, std::integral_constant<decltype(deleter), deleter>>;
 

А в C 14 есть псевдоним для упрощения:

 template <typename Pointer, auto deleter>
using my_unique_ptr = std::unique_ptr<std::remove_pointer_t<Pointer>, std::integral_constant<decltype(deleter), deleter>>;