Template | Comments |
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.