Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

standard c++11 way to remove all pointers of a type

Is there a way to do this with some c++11 or at most a boost library?

#include <iostream>
#include <typeinfo>
using namespace std;

template <typename T> class remove_all_pointers{
public:
    typedef T type;
};

template <typename T> class remove_all_pointers<T*>{
public:
    typedef typename remove_all_pointers<T>::type type;
};

int main(){
    //correctly prints 'i' on gcc
    cout<<typeid(remove_all_pointers<int****>::type).name()<<endl;
}
like image 301
Lorenzo Pistone Avatar asked Mar 24 '12 12:03

Lorenzo Pistone


2 Answers

That doesn't quite work for all pointer types. You need to account for different cv-qualifiers as well:

template <typename T> class remove_all_pointers<T* const>{
public:
    typedef typename remove_all_pointers<T>::type type;
};

template <typename T> class remove_all_pointers<T* volatile>{
public:
    typedef typename remove_all_pointers<T>::type type;
};

template <typename T> class remove_all_pointers<T* const volatile >{
public:
    typedef typename remove_all_pointers<T>::type type;
};
like image 107
MSN Avatar answered Nov 17 '22 10:11

MSN


Since C++17 you can create a readable, simple and cv-qualifier aware meta function.

Use it like:

int main()
{
    remove_all_pointers_t<int* const* volatile* const volatile*> v = 42;
    return 0;
}

C++20

#include <type_traits>

template<typename T>
struct remove_all_pointers : std::conditional_t<
    std::is_pointer_v<T>,
    remove_all_pointers<
        std::remove_pointer_t<T>
    >,
    std::type_identity<T>
>
{};

template<typename T>
using remove_all_pointers_t = typename remove_all_pointers<T>::type;

C++17

In C++17 std::type_identity isn't available yet and std::identity isn't available anymore, hence you need to create your own 'identity' meta function:

#include <type_traits>

// your custom 'identity' meta function
template <typename T>
struct identity
{
    using type = T;
};

template<typename T>
struct remove_all_pointers : std::conditional_t<
    std::is_pointer_v<T>,
    remove_all_pointers<
        std::remove_pointer_t<T>
    >,
    identity<T>
>
{};

template<typename T>
using remove_all_pointers_t = typename remove_all_pointers<T>::type;
like image 45
klaus triendl Avatar answered Nov 17 '22 10:11

klaus triendl