20 General utilities library [utilities]

20.9 Metaprogramming and type traits [meta]

20.9.7 Transformations between types [meta.trans]

This sub-clause contains templates that may be used to transform one type to another following some predefined rule.

Each of the templates in this subclause shall be a TransformationTrait ([meta.rqmts]).

20.9.7.1 Const-volatile modifications [meta.trans.cv]

Table 52 — Const-volatile modifications
TemplateComments
template <class T>
struct remove_const;
The member typedef type shall name the same type as T except that any top-level const-qualifier has been removed. [ Example: remove_const<const volatile int>::type evaluates to volatile int, whereas remove_const<const int*>::type evaluates to const int*.  — end example ]
template <class T>
struct remove_volatile;
The member typedef type shall name the same type as T except that any top-level volatile-qualifier has been removed. [ Example: remove_volatile<const volatile int>::type evaluates to const int, whereas remove_volatile<volatile int*>::type evaluates to volatile int*.  — end example ]
template <class T>
struct remove_cv;
The member typedef type shall be the same as T except that any top-level cv-qualifier has been removed. [ Example: remove_cv<const volatile int>::type evaluates to int, whereas remove_cv<const volatile int*>::type evaluates to const volatile int*.  — end example ]
template <class T>
struct add_const;
If T is a reference, function, or top-level const-qualified type, then type shall name the same type as T, otherwise T const.
template <class T>
struct add_volatile;
If T is a reference, function, or top-level volatile-qualified type, then type shall name the same type as T, otherwise T volatile.
template <class T>
struct add_cv;
The member typedef type shall name the same type as add_const<typename add_volatile<T>::type>::type.

20.9.7.2 Reference modifications [meta.trans.ref]

Table 53 — Reference modifications
TemplateComments
template <class T>
struct remove_reference;
If T has type “reference to T1” then the member typedef type shall name T1; otherwise, type shall name T.
template <class T>
struct add_lvalue_reference;
If T names an object or function type then the member typedef type shall name T&; otherwise, if T names a type “rvalue reference to T1” then the member typedef type shall name T1&; otherwise, type shall name T.
template <class T>
struct add_rvalue_reference;
If T names an object or function type then the member typedef type shall name T&&; otherwise, type shall name T. [ Note: This rule reflects the semantics of reference collapsing ([dcl.ref]). For example, when a type T names a type T1&, the type add_rvalue_reference<T>::type is not an rvalue reference.  — end note ]

20.9.7.3 Sign modifications [meta.trans.sign]

Table 54 — Sign modifications
TemplateComments
template <class T>
struct make_signed;
If T names a (possibly cv-qualified) signed integer type ([basic.fundamental]) then the member typedef type shall name the type T; otherwise, if T names a (possibly cv-qualified) unsigned integer type then type shall name the corresponding signed integer type, with the same cv-qualifiers as T; otherwise, type shall name the signed integer type with smallest rank ([conv.rank]) for which sizeof(T) == sizeof(type), with the same cv-qualifiers as T.
Requires: T shall be a (possibly cv-qualified) integral type or enumeration but not a bool type.
template <class T>
struct make_unsigned;
If T names a (possibly cv-qualified) unsigned integer type ([basic.fundamental]) then the member typedef type shall name the type T; otherwise, if T names a (possibly cv-qualified) signed integer type then type shall name the corresponding unsigned integer type, with the same cv-qualifiers as T; otherwise, type shall name the unsigned integer type with smallest rank ([conv.rank]) for which sizeof(T) == sizeof(type), with the same cv-qualifiers as T.
Requires: T shall be a (possibly cv-qualified) integral type or enumeration but not a bool type.

20.9.7.4 Array modifications [meta.trans.arr]

Table 55 — Array modifications
TemplateComments
template <class T>
struct remove_extent;
If T names a type “array of U”, the member typedef type shall be U, otherwise T. [ Note: For multidimensional arrays, only the first array dimension is removed. For a type “array of const U”, the resulting type is const U.  — end note ]
template <class T>
struct remove_all_extents;
If T is “multi-dimensional array of U”, the resulting member typedef type is U, otherwise T.

[Example

// the following assertions hold:
assert((is_same<remove_extent<int>::type, int>::value));
assert((is_same<remove_extent<int[2]>::type, int>::value));
assert((is_same<remove_extent<int[2][3]>::type, int[3]>::value));
assert((is_same<remove_extent<int[][3]>::type, int[3]>::value));

 — end example ]

[Example

// the following assertions hold:
assert((is_same<remove_all_extents<int>::type, int>::value));
assert((is_same<remove_all_extents<int[2]>::type, int>::value));
assert((is_same<remove_all_extents<int[2][3]>::type, int>::value));
assert((is_same<remove_all_extents<int[][3]>::type, int>::value));

 — end example ]

20.9.7.5 Pointer modifications [meta.trans.ptr]

Table 56 — Pointer modifications
TemplateComments
template <class T>
struct remove_pointer;
If T has type “(possibly cv-qualified) pointer to T1” then the member typedef type shall name T1; otherwise, it shall name T.
template <class T>
struct add_pointer;
The member typedef type shall name the same type as remove_reference<T>::type*.

20.9.7.6 Other transformations [meta.trans.other]

Table 57 — Other transformations
TemplateConditionComments
template <std::size_t Len,
std::size_t Align
= default-alignment>
struct aligned_storage;
Len shall not be zero. Align shall be equal to alignof(T) for some type T or to default-alignment. The value of default-alignment shall be the most stringent alignment requirement for any C++ object type whose size is no greater than Len ([basic.types]). The member typedef type shall be a POD type suitable for use as uninitialized storage for any object whose size is at most Len and whose alignment is a divisor of Align.
template <std::size_t Len,
class... Types>
struct aligned_union;
At least one type is provided. The member typedef type shall be a POD type suitable for use as uninitialized storage for any object whose type is listed in Types; its size shall be at least Len. The static member alignment_value shall be an integral constant of type std::size_t whose value is the strictest alignment of all types listed in Types.
template <class T> struct decay; Let U be remove_reference<T>::type. If is_array<U>::value is true, the member typedef type shall equal remove_extent<U>::type*. If is_function<U>::value is true, the member typedef type shall equal add_pointer<U>::type. Otherwise the member typedef type equals remove_cv<U>::type. [ Note: This behavior is similar to the lvalue-to-rvalue ([conv.lval]), array-to-pointer ([conv.array]), and function-to-pointer ([conv.func]) conversions applied when an lvalue expression is used as an rvalue, but also strips cv-qualifiers from class types in order to more closely model by-value argument passing.  — end note ]
template <bool B, class T = void> struct enable_if; If B is true, the member typedef type shall equal T; otherwise, there shall be no member typedef type.
template <bool B, class T, class F> struct conditional; If B is true, the member typedef type shall equal T. If B is false, the member typedef type shall equal F.
template <class... T> struct common_type; The member typedef type shall be defined as set out below. All types in the parameter pack T shall be complete or (possibly cv) void. A program may specialize this trait if at least one template parameter in the specialization is a user-defined type. [ Note: Such specializations are needed when only explicit conversions are desired among the template arguments.  — end note ]
template <class T>
struct underlying_type;
T shall be an enumeration type ([dcl.enum]) The member typedef type shall name the underlying type of T.
template <class Fn,
class... ArgTypes> struct result_of<Fn(ArgTypes...)>;
Fn shall be a callable type ([func.def]), reference to function, or reference to callable type. The expression decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...)) shall be well formed. The member typedef type shall name the type decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...))

Note: A typical implementation would define aligned_storage as:

template <std::size_t Len, std::size_t Alignment>
struct aligned_storage {
  typedef struct {
    alignas(Alignment) unsigned char __data[Len];
  } type;
};

 — end note ]

It is implementation-defined whether any extended alignment is supported ([basic.align]).

The nested typedef common_type::type shall be defined as follows:

template <class ...T> struct common_type;

template <class T>
struct common_type<T> {
  typedef T type;
};

template <class T, class U>
struct common_type<T, U> {
  typedef decltype(true ? declval<T>() : declval<U>()) type;
};

template <class T, class U, class... V>
struct common_type<T, U, V...> {
  typedef typename common_type<typename common_type<T, U>::type, V...>::type type;
};

Example: Given these definitions:

typedef bool (&PF1)();
typedef short (*PF2)(long);

struct S {
  operator PF2() const;
  double operator()(char, int&);
  void fn(long) const;
  char data;
};

typedef void (S::*PMF)(long) const;
typedef char S::*PMD;

the following assertions will hold:

static_assert(is_same<result_of<S(int)>::type, short>::value, "Error!");
static_assert(is_same<result_of<S&(unsigned char, int&)>::type, double>::value, "Error!");
static_assert(is_same<result_of<PF1()>::type, bool>::value, "Error!");
static_assert(is_same<result_of<PMF(unique_ptr<S>, int)>::type, void>::value, "Error!");
static_assert(is_same<result_of<PMD(S)>::type, char&&>::value, "Error!");
static_assert(is_same<result_of<PMD(const S*)>::type, const char&>::value, "Error!");

 — end example ]