Table 6 — Other transformations

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.