Reputation: 9383
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.
Upvotes: 3
Views: 1065
Reputation: 42554
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;
Upvotes: 5