Remove link with links to const

For the parametric class C, I always want to get a "primitive" type, regardless of pointers, constant or reference modifiers.

template<typename __T> class C { public: typedef std::some_magic_remove_all<__T>::type T; } int main() { C<some_type>::type a; } 

For example, for some_type equal to:

  • int&
  • int**
  • int*&
  • int const &&
  • int const * const
  • etc.

I want a always be of type int . How can i achieve this?

+10
source share
3 answers
 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; -)

+11
source

If you want to use the standard library more, you can do:

 #include <type_traits> template<class T, class U= typename std::remove_cv< typename std::remove_pointer< typename std::remove_reference< typename std::remove_extent< T >::type >::type >::type >::type > struct remove_all : remove_all<U> {}; template<class T> struct remove_all<T, T> { typedef T type; }; 

which removes things until it no longer changes the type. With a newer standard, this can be reduced to

 template<class T, class U= std::remove_cvref_t< std::remove_pointer_t< std::remove_extent_t< T >>>> struct remove_all : remove_all<U> {}; template<class T> struct remove_all<T, T> { typedef T type; }; template<class T> using remove_all_t = typename remove_all<T>::type; 
+11
source

You can also use the remove_cvref_t function, it was available with C ++ 20

 #include <iostream> #include <type_traits> int main() { std::cout << std::boolalpha << std::is_same_v<std::remove_cvref_t<int>, int> << '\n' << std::is_same_v<std::remove_cvref_t<int&>, int> << '\n' << std::is_same_v<std::remove_cvref_t<int&&>, int> << '\n' << std::is_same_v<std::remove_cvref_t<const int&>, int> << '\n' << std::is_same_v<std::remove_cvref_t<const int[2]>, int[2]> << '\n' << std::is_same_v<std::remove_cvref_t<const int(&)[2]>, int[2]> << '\n' << std::is_same_v<std::remove_cvref_t<int(int)>, int(int)> << '\n'; } 
0
source

All Articles