Last time, we wrote a remove_
type trait, but I noted that even though we found a solution, we weren’t finished yet.
We can bring back the one-liner by using a different trick to delay the recursion: Don’t ask for the type
until we know we really are recursing.
The sketch is
template<typename T> struct dummy { using type = T; }; template<typename T> struct remove_all_pointers { if (std::is_pointer_v<T>) { using type_holder = remove_all_pointers< std::remove_pointer_t<T> >; } else { using type_holder = dummy<T>; } using type = typename type_holder::type; };
We first define a type_holder
to be a type which has a type
member type that holds our answer. If T
is a pointer, then the type holder is the recursive call. Otherwise, the type holder is a dummy type whose sole purpose is to have a type
member type that produces T
again.
We can now pack up that if
into a std::
.
template<typename T> struct remove_all_pointers { using type_holder = std::conditional_t< std::is_pointer_v<T>, remove_all_pointers< std::remove_pointer_t<T> >, dummy<T>>; using type = typename type_holder::type; };
It turns out that we don’t need to define a dummy
: The C++ standard library comes with one built in! It’s called std::
, available starting in C++20. (We looked at std::
a little while ago.)
template<typename T> struct remove_all_pointers { using type_holder = std::conditional_t< std::is_pointer_v<T>, remove_all_pointers< std::remove_pointer_t<T> >, std::type_identity<T>>; using type = typename type_holder::type; };
Now we can inline the type_holder
.
template<typename T> struct remove_all_pointers { using type = typename std::conditional_t< std::is_pointer_v<T>, remove_all_pointers< std::remove_pointer_t<T> >, std::type_identity<T>>::type; };
Or even better, just derive from the type_holder
!
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>> { };
So basically moving the
::type
outside thestd::conditional_t
fixes it, because this way you don’t construct the template unless it’s necessary. (But the last optimisation is nice.)The Aha moment after comparing the initial attempt and the final approach: A manual design of short circuitry.