8 General utilities library [utilities]

8.4 Metaprogramming and type traits [meta]

8.4.3 Other transformations [meta.trans.other]

Table 6 — Other transformations
TemplateComments
template <class... T>
struct common_type;
The member typedef type shall be defined or omitted as specified below. If it is omitted, there shall be no member type. Each type 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 depends on a user-defined type and sizeof...(T) == 2. [ Note: Such specializations are needed when only explicit conversions are desired among the template arguments.  — end note ]
template <class T, class U,
template <class> class TQual,
template <class> class UQual>
struct basic_common_reference;
The primary template shall have no member typedef type. A program may specialize this trait if at least one template parameter in the specialization depends on a user-defined type. In such a specialization, a member typedef type may be defined or omitted. If it is omitted, there shall be no member type. [ Note: Such specializations may be used to influence the result of common_reference. — end note ]
template <class... T>
struct common_reference;
The member typedef type shall be defined or omitted as specified below. If it is omitted, there shall be no member type. Each type in the parameter pack T shall be complete or (possibly cv) void.

Let CREF(A) be add_lvalue_reference_t<const remove_reference_t<A>>. Let UNCVREF(A) be remove_cv_t<remove_reference_t<A>>. Let XREF(A) denote a unary template T such that T<UNCVREF(A)> denotes the same type as A. Let COPYCV(FROM, TO) be an alias for type TO with the addition of FROM's top-level cv-qualifiers. [ Example: COPYCV(const int, volatile short) is an alias for const volatile short.  — end example ] Let RREF_RES(Z) be remove_reference_t<Z>&& if Z is a reference type or Z otherwise. Let COND_RES(X, Y) be decltype(declval<bool>() ? declval<X(&)()>()() : declval<Y(&)()>()()). Given types A and B, let X be remove_reference_t<A>, let Y be remove_reference_t<B>, and let COMMON_REF(A, B) be:

  • If A and B are both lvalue reference types, COMMON_REF(A, B) is COND_RES(COPYCV(X, Y) &, COPYCV(Y, X) &).

  • Otherwise, let C be RREF_RES(COMMON_REF(X&, Y&)). If A and B are both rvalue reference types, and C is well-formed, and is_convertible<A, C>::value and is_convertible<B, C>::value are true, then COMMON_REF(A, B) is C.

  • Otherwise, let D be COMMON_REF(const X&, Y&). If A is an rvalue reference and B is an lvalue reference and D is well-formed and is_convertible<A, D>::value is true, then COMMON_REF(A, B) is D.

  • Otherwise, if A is an lvalue reference and B is an rvalue reference, then COMMON_REF(A, B) is COMMON_REF(B, A).

  • Otherwise, COMMON_REF(A, B) is decay_t<COND_RES(CREF(A), CREF(B))>.

If any of the types computed above are ill-formed, then COMMON_REF(A, B) is ill-formed.

Note A: For the common_type trait applied to a parameter pack T of types, the member type shall be either defined or not present as follows:

  • If sizeof...(T) is zero, there shall be no member type.

  • Otherwise, if sizeof...(T) is one, let T1 denote the sole type in the pack T. The member typedef type shall denote the same type as decay_t<T1>.

  • Otherwise, if sizeof...(T) is two, let T1 and T2 denote the two types in the pack T, and let D1 and D2 be decay_t<T1> and decay_t<T2> respectively. Then

    • If D1 and T1 denote the same type and D2 and T2 denote the same type, then

      • If std::common_type_t<T1, T2> is well-formed, then the member typedef type denotes std::common_type_t<T1, T2>.

      • If COMMON_REF(T1, T2) is well-formed, then the member typedef type denotes that type.

      • Otherwise, there shall be no member type.

    • Otherwise, if common_type_t<D1, D2> is well-formed, then the member typedef type denotes that type.

    • Otherwise, there shall be no member type.

  • Otherwise, if sizeof...(T) is greater than two, let T1, T2, and Rest, respectively, denote the first, second, and (pack of) remaining types comprising T. Let C be the type common_type_t<T1, T2>. Then:

    • If there is such a type C, the member typedef type shall denote the same type, if any, as common_type_t<C, Rest...>.

    • Otherwise, there shall be no member type.

Note B: Notwithstanding the provisions of ISO/IEC 14882:2014 §[meta.type.synop], and pursuant to ISO/IEC 14882:2014 §[namespace.std], a program may specialize common_type<T1, T2> for types T1 and T2 such that is_same<T1, decay_t<T1>>::value and is_same<T2, decay_t<T2>>::value are each true. [ Note: Such specializations are needed when only explicit conversions are desired between the template arguments.  — end note ] Such a specialization need not have a member named type, but if it does, that member shall be a typedef-name for an accessible and unambiguous cv-unqualified non-reference type C to which each of the types T1 and T2 is explicitly convertible. Moreover, common_type_t<T1, T2> shall denote the same type, if any, as does common_type_t<T2, T1>. No diagnostic is required for a violation of this Note's rules.

For the common_reference trait applied to a parameter pack T of types, the member type shall be either defined or not present as follows:

  • If sizeof...(T) is zero, there shall be no member type.

  • Otherwise, if sizeof...(T) is one, let T1 denote the sole type in the pack T. The member typedef type shall denote the same type as T1.

  • Otherwise, if sizeof...(T) is two, let T1 and T2 denote the two types in the pack T. Then

    • If T1 and T2 are reference types and COMMON_REF(T1, T2) is well-formed and denotes a reference type then the member typedef type denotes that type.

    • Otherwise, if basic_common_reference<UNCVREF(T1), UNCVREF(T2), XREF(T1), XREF(T2)>::type is well-formed, then the member typedef type denotes that type.

    • Otherwise, if COND_RES(T1, T2) is well-formed, then the member typedef type denotes that type.

    • Otherwise, if common_type_t<T1, T2> is well-formed, then the member typedef type denotes that type.

    • Otherwise, there shall be no member type.

  • Otherwise, if sizeof...(T) is greater than two, let T1, T2, and Rest, respectively, denote the first, second, and (pack of) remaining types comprising T. Let C be the type common_reference_t<T1, T2>. Then:

    • If there is such a type C, the member typedef type shall denote the same type, if any, as common_reference_t<C, Rest...>.

    • Otherwise, there shall be no member type.

Notwithstanding the provisions of ISO/IEC 14882:2014 §[meta.type.synop], and pursuant to ISO/IEC 14882:2014 §[namespace.std], a program may specialize basic_common_reference<T, U, TQual, UQual> for types T and U such that is_same<T, decay_t<T>>::value and is_same<U, decay_t<U>>::value are each true. [ Note: Such specializations are needed when only explicit conversions are desired between the template arguments.  — end note ] Such a specialization need not have a member named type, but if it does, that member shall be a typedef-name for an accessible and unambiguous type C to which each of the types TQual<T> and UQual<U> is convertible. Moreover, basic_common_reference<T, U, TQual, UQual>::type shall denote the same type, if any, as does basic_common_reference<U, T, UQual, TQual>::type. A program may not specialize basic_common_reference on the third or fourth parameters, TQual or UQual. No diagnostic is required for a violation of these rules.