Search code examples
c++unique-ptrvoid-pointerstype-traits

How to use std::remove_pointer with void*?


I am using std::unique_ptr in this way:

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

It seems to work when Pointer = void*, but when trying to use reset on such a my_unique_ptr, I am getting this error:

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

Shouldn't std::remove_pointer<void*>* automatically mean void*?


Solution

  • Your my_unique_ptr<void*> does not contain void*. It contains a std::remove_pointer<void*>*.

    Shouldn't std::remove_pointer<void*>* automatically mean void*?

    The std::remove_pointer type is not magic. It's a type like any other. Here's a possible implementation:

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

    As you can see, as you defined it, the std::unique_ptr contains a pointer to that struct, just like the compiler error mentionned.

    What you probably meant to do is to use the member ::type of the struct, aka the result of the remove_pointer metafunction:

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

    And with C++14, there's a alias to simplify:

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