12

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;
}
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Lorenzo Pistone
  • 5,028
  • 3
  • 34
  • 65
  • What do you want to remove these pointers from? – Gabe Mar 24 '12 at 12:08
  • classes, fundamental types, everything. – Lorenzo Pistone Mar 24 '12 at 12:09
  • 4
    Your `remove_all_pointers` template does remove all pointers. What else do you need? – n. m. could be an AI Mar 24 '12 at 14:05
  • 3
    Is the question here "is there something in the standard library that does the same job as this code I wrote"? – zwol Mar 24 '12 at 17:08
  • 7
    @downvoters I cannot see the problem in looking for a standard feature to achieve something. Even if you can write this yourself in 3 lines, why not see if there's a standard facility for the purpose? And what the OP needs it for is pretty much irrelevant for answering the question. – Christian Rau Mar 24 '12 at 17:36
  • 4
    Plus, it's not like this is some functionality that's so esoteric that one wonders why someone could possibly want it at all. The C++11 standard and Boost already have `remove_pointer`. All he's asking for is `remove_all_pointer`, much like it has `remove_all_extent` for removing all array qualifiers. He wants the base type; why is that so questionable a thing to want? – Nicol Bolas Mar 24 '12 at 17:42

3 Answers3

7

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;
};
MSN
  • 53,214
  • 7
  • 75
  • 105
  • Good point. You could use std:remove_cv and dispatch to a routine that does what the poster has. – emsr Mar 25 '12 at 00:46
5

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;
klaus triendl
  • 1,237
  • 14
  • 25
2

Neither Boost nor C++11 features such a trait template. But your code should work.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982