2763. common_type_t<void, void> is undefined

Section: 21.3.8.7 [meta.trans.other] Status: Resolved Submitter: Tim Song Opened: 2016-08-10 Last modified: 2016-11-21

Priority: 2

View all other issues in [meta.trans.other].

View all issues with Resolved status.

Discussion:

There are no xvalues of type cv void (see [basic.lval]/6), so the current wording appears to mean that there is no common_type_t<void, void>. Is that intended?

[2016-08-11, Daniel comments]

This is strongly related to LWG 2465. It should be considered to resolve 2465 by this revised wording.

[2016-11-12, Issaquah]

Resolved by P0435R1

Proposed resolution:

This wording is relative to N4606.

  1. Edit 21.3.8.7 [meta.trans.other]/3 as indicated:

    [Drafting note: The proposed wording below simply goes back to using declval, which already does the right thing. To describe this in words would be something like "if D1 is void, a prvalue of type void that is not a (possibly parenthesized) throw-expression, otherwise an xvalue of type D1", which seems unnecessarily convoluted at best. — end drafting note]

    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:

    1. (3.1) — If sizeof...(T) is zero, there shall be no member type.

    2. (3.2) — If sizeof...(T) is one, let T0 denote the sole type in the pack T. The member typedef type shall denote the same type as decay_t<T0>.

    3. (3.3) — If sizeof...(T) is greater than two, let T1, T2, and R, respectively, denote the first, second, and (pack of) remaining types comprising T. [Note: sizeof...(R) may be zero. — end note] Let C denote the type, if any, of an unevaluated conditional expression (7.6.16 [expr.cond]) whose first operand is an arbitrary value of type bool, whose second operand is an xvalue of type T1declval<T1>(), and whose third operand is an xvalue of type T2declval<T2>(). If there is such a type C, the member typedef type shall denote the same type, if any, as common_type_t<C, R...>. Otherwise, there shall be no member type.

  2. The following wording is a merge of the above with the current proposed resolution of 2465, to provide editorial guidance if both proposed resolutions are accepted:

    -3- 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:

    1. (3.1) — If sizeof...(T) is zero, there shall be no member type.

    2. (3.2) — If sizeof...(T) is one, let T0 denote the sole type in the pack T. The member typedef type shall denote the same type as decay_t<T0>.

    3. (3.3) — If sizeof...(T) is two, let T1 and T2, respectively, denote the first and second types comprising T, and let D1 and D2, respectively, denote decay_t<T1> and decay_t<T2>.

      1. (3.3.1) — If is_same_v<T1, D1> and is_same_v<T2, D2>, let C denote the type of an unevaluated conditional expression (7.6.16 [expr.cond]) whose first operand is an arbitrary value of type bool, whose second operand is declval<D1>(), and whose third operand is declval<D2>(). [Note: This will not apply if there is a specialization common_type<D1, D2>. — end note]

      2. (3.3.2) — Otherwise, let C denote the type common_type_t<D1, D2>.

      In either case, if there is such a type C, the member typedef type shall denote C. Otherwise, there shall be no member type.

    4. (3.4) — If sizeof...(T) is greater than onetwo, let T1, T2, and R, respectively, denote the first, second, and (pack of) remaining types comprising T. [Note: sizeof...(R) may be zero. — end note] Let C denote the type, if any, of an unevaluated conditional expression (7.6.16 [expr.cond]) whose first operand is an arbitrary value of type bool, whose second operand is an xvalue of type T1, and whose third operand is an xvalue of type T2. Let C denote common_type_t<T1, T2>. If there is such a type C, the member typedef type shall denote the same type, if any, as common_type_t<C, R...>. Otherwise, there shall be no member type.

    -?- Note B: A program may specialize the common_type trait for two cv-unqualified non-reference types if at least one of them is a user-defined type. [Note: Such specializations are needed when only explicit conversions are desired among 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 a cv-unqualified non-reference type that need not otherwise meet the specification set forth in Note A, above.

    -4- [Example: Given these definitions: […]