template<class T> struct remove_all { typedef T type; }; template<class T> struct remove_all<T*> : remove_all<T> {}; template<class T> struct remove_all<T&> : remove_all<T> {}; template<class T> struct remove_all<T&&> : remove_all<T> {}; template<class T> struct remove_all<T const> : remove_all<T> {}; template<class T> struct remove_all<T volatile> : remove_all<T> {}; template<class T> struct remove_all<T const volatile> : remove_all<T> {}; //template<class T> struct remove_all<T[]> : remove_all<T> {}; //template<class T, int n> struct remove_all<T[n]> : remove_all<T> {};
I originally also shared extents (arrays), but Johannes noticed that this caused confusion for const char[] , and the question does not mention them. If we also want to separate arrays (see also the ideas mentioned in the comments), the following does not complicate the situation too much:
#include <type_traits> template<class U, class T = typename std::remove_cv<U>::type> struct remove_all { typedef T type; }; template<class U, class T> struct remove_all<U,T*> : remove_all<T> {}; template<class U, class T> struct remove_all<U,T&> : remove_all<T> {}; template<class U, class T> struct remove_all<U,T&&> : remove_all<T> {}; template<class U, class T> struct remove_all<U,T[]> : remove_all<T> {}; template<class U, class T, int n> struct remove_all<U,T[n]> : remove_all<T> {};
or with a helper class, but with one template parameter:
#include <type_traits> template<class T> struct remove_all_impl { typedef T type; }; template<class T> using remove_all = remove_all_impl<typename std::remove_cv<T>::type>; template<class T> struct remove_all_impl<T*> : remove_all<T> {}; template<class T> struct remove_all_impl<T&> : remove_all<T> {}; template<class T> struct remove_all_impl<T&&> : remove_all<T> {}; template<class T> struct remove_all_impl<T[]> : remove_all<T> {}; template<class T, int n> struct remove_all_impl<T[n]> : remove_all<T> {};
This is normal if all options begin to look the same; -)
source share