3

I would like something that has semantics similar to std::remove_pointer but works for pointer classes in addition to true pointers. Naturally I could enumerate the known possibilities:

// Important: remove_pointer_ex<T>::type should evaluate to T
// if T::operator* is not defined (like std::remove_pointer)
template<typename T> struct remove_pointer_ex { typedef T type; };

template<typename T> struct remove_pointer_ex<T*> { typedef T type; };
template<typename T> struct remove_pointer_ex<std::shared_ptr<T>> { typedef T type; };
template<typename T> struct remove_pointer_ex<std::unique_ptr<T>> { typedef T type; };
// and then again for all the different cv combinations

But I'd really like an approach that will work with any class that supports operator*.

It seems like this should be doable using SFINAE and/or type traits. The answers to this question describe how to test whether a particular type has a particular member, and I suppose I could use one of those suggestions in combination with enable_if, but frankly if there's no less-ugly way to solve the problem, I'd rather just try a completely different approach.

Community
  • 1
  • 1
dlf
  • 9,045
  • 4
  • 32
  • 58

1 Answers1

5

Use a type trait that defaults to T but prefers std::remove_reference<decltype(*T)> when it is valid (Live at Coliru):

template <typename T>
class remove_pointer_ {
    template <typename U=T>
    static auto test(int) -> std::remove_reference<decltype(*std::declval<U>())>;
    static auto test(...) -> std::remove_cv<T>;

public:
    using type = typename decltype(test(0))::type;
};

template <typename T>
using remove_pointer = typename remove_pointer_<T>::type;
Casey
  • 41,449
  • 7
  • 95
  • 125
  • 4
    This doesn't work for pointers to arrays or functions. But this is easily worked around with a wrapper type: http://coliru.stacked-crooked.com/a/81e7754e3a5e4529 – Brian Bi Jun 19 '14 at 19:56
  • That looks like it will do it. I had to make a couple adjustments before Microsoft's partial C++11 support would accept it (they don't like the usings or having a default template argument on a function), and it doesn't drop cv qualifiers like `std::remove_pointer` does, but that isn't difficult to add. – dlf Jun 19 '14 at 19:59
  • 1
    @Brian Thanks - incorporated into the answer, with arbitrary style changes since [I prefer the bikeshed to be blue](http://en.wiktionary.org/wiki/bikeshedding). – Casey Jun 19 '14 at 20:20