While trying to answer one question here, I found this question:
How to recursively dereference pointer (C++03)?
Adapted code from the answer is following:
You can do it with a trait to compute the ultimate return type, here dubbed remove_all_pointers
:
#include <type_traits>
template <typename T> struct remove_all_pointers
{ typedef typename std::remove_reference<T>::type type; };
template <typename T> struct remove_all_pointers<T *>
{ typedef typename std::remove_reference<T>::type type; };
template <typename T>
T & dereference(T & p)
{ return p; }
template <typename U>
typename remove_all_pointers<U>::type & dereference(U * p)
{ return dereference(*p); }
int main(int argc, char * argv[])
{
return dereference(argv);
}
You may need to add CV-variants; I'm still thinking about that.
This is possible with the use of a custom can_dereference
trait:
template <typename T>
struct can_dereference_helper {
template <typename U, typename = decltype(*std::declval<U>())>
static std::true_type test(U);
template <typename...U>
static std::false_type test(U...);
using type = decltype(test(std::declval<T>()));
};
template <typename T>
struct can_dereference :
can_dereference_helper<typename std::decay<T>::type>::type {};
and some mutually-recursive functions with a bit'o tag dispatching:
template <typename T>
auto recursive_dereference(T&& t, std::false_type) ->
decltype(std::forward<T>(t)) {
return std::forward<T>(t);
}
template <typename T>
auto recursive_dereference(T&& t) ->
decltype(recursive_dereference(std::forward<T>(t), can_dereference<T>{}));
template <typename T>
auto recursive_dereference(T&& t, std::true_type) ->
decltype(recursive_dereference(*std::forward<T>(t))) {
return recursive_dereference(*std::forward<T>(t));
}
template <typename T>
auto recursive_dereference(T&& t) ->
decltype(recursive_dereference(std::forward<T>(t), can_dereference<T>{})) {
return recursive_dereference(std::forward<T>(t), can_dereference<T>{});
}
See it work live at Coliru. This may seem like overkill compared to Kerrek's answer, but I went for a generic approach that will dereference anything that supports operator*
. I'll let you decide which tool fits your problem best.