std::remove_cv,std::remove_const,std::remove_volatile(3)

NAME
std::remove_cv,std::remove_const,std::remove_volatile - std::remove_cv,std::remove_const,std::remove_volatile

Synopsis
   Defined in header <type_traits>
   template< class T > (1) (since C++11)
   struct remove_cv;
   template< class T > (2) (since C++11)
   struct remove_const;
   template< class T > (3) (since C++11)
   struct remove_volatile;
   Provides the member typedef type which is the same as T, except that its topmost
   cv-qualifiers are removed.
   1) removes the topmost const, or the topmost volatile, or both, if present.
   2) removes the topmost const
   3) removes the topmost volatile
   The behavior of a program that adds specializations for any of the templates
   described on this page is undefined.

Member types
   Name Definition
   type the type T without cv-qualifier

Helper types
   template< class T > (since C++14)
   using remove_cv_t = typename remove_cv<T>::type;
   template< class T > (since C++14)
   using remove_const_t = typename remove_const<T>::type;
   template< class T > (since C++14)
   using remove_volatile_t = typename remove_volatile<T>::type;

Possible implementation
   template< class T > struct remove_cv { typedef T type; };
   template< class T > struct remove_cv<const T> { typedef T type; };
   template< class T > struct remove_cv<volatile T> { typedef T type; };
   template< class T > struct remove_cv<const volatile T> { typedef T type; };
   template< class T > struct remove_const { typedef T type; };
   template< class T > struct remove_const<const T> { typedef T type; };
   template< class T > struct remove_volatile { typedef T type; };
   template< class T > struct remove_volatile<volatile T> { typedef T type; };

Example
   Removing const/volatile from const volatile int * does not modify the type, because
   the pointer itself is neither const nor volatile. // Run this code
 #include <iostream>
 #include <type_traits>
 template<typename U, typename V> constexpr bool same = std::is_same_v<U, V>;
 static_assert(
         same< std::remove_cv_t< int >, int >
     and same< std::remove_cv_t< const int >, int >
     and same< std::remove_cv_t< volatile int >, int >
     and same< std::remove_cv_t< const volatile int >, int >
     and same< std::remove_cv_t< const volatile int* >, const volatile int* >
     and same< std::remove_cv_t< const int* volatile >, const int* >
     and same< std::remove_cv_t< int* const volatile >, int* >
 );
 int main() {
     std::cout << std::boolalpha;
     using type1 = std::remove_cv<const int>::type;
     using type2 = std::remove_cv<volatile int>::type;
     using type3 = std::remove_cv<const volatile int>::type;
     using type4 = std::remove_cv<const volatile int*>::type;
     using type5 = std::remove_cv<int* const volatile>::type;
     std::cout << std::is_same<type1, int>::value << "\n";
     std::cout << std::is_same<type2, int>::value << "\n";
     std::cout << std::is_same<type3, int>::value << "\n";
     std::cout << std::is_same<type4, int*>::value << " "
               << std::is_same<type4, const volatile int*>::value << "\n";
     std::cout << std::is_same<type5, int*>::value << "\n";
 }

Output:
 true
 true
 true
 false true
 true

See also
   is_const checks if a type is const-qualified
   (C++11) (class template)
   is_volatile checks if a type is volatile-qualified
   (C++11) (class template)
   add_cv
   add_const
   add_volatile adds const or/and volatile specifiers to the given type
   (C++11) (class template)
   (C++11)
   (C++11)
   remove_cvref combines std::remove_cv and std::remove_reference
   (C++20) (class template)