This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.

### 3153. `Common` and `common_type` have too little in common

Section: 18.4.6 [concept.common] Status: C++20 Submitter: Casey Carter Opened: 2018-08-10 Last modified: 2021-02-25

Priority: 0

View all other issues in [concept.common].

View all issues with C++20 status.

Discussion:

The `Common` concept when applied to types `T` and `U` requires that `T` and `U` are each `ConvertibleTo` ( [concept.convertibleto]) their common type `common_type_t<T, U>`. `ConvertibleTo` requires both implicit and explicit conversions with equivalent results. The requirement for implicit conversion is notably not a requirement for specializing `common_type` as detailed in 21.3.8.7 [meta.trans.other]:

> -5- 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.

which only requires explicit conversion to be valid. While it's not inconsistent that the `Common` concept's requirements are a refinement of the requirements for `common_type`, there's no good reason for this additional requirement. The stated design intent is to enable writing monomorphic predicates that can compare `T`s with `U`s (and vice versa) by accepting two arguments of type `common_type_t<T, U>`, but this role has been superseded by the addition of `CommonReference` and `common_reference_t` to the ranges design. The existence of pairs of types that are only explicitly convertible to their common type suggests that using `Common` in this way would never be a fully generic solution in any case.

The only existing use of the `Common` concept in either the working draft or the Ranges proposal is as a soundness check on the comparison and difference operators of `counted_iterator`, none of which actually convert any argument to the common type in their normal operation. It would seem that we could strike the additional requirement without impacting the Ranges design, which would allow for future uses of the `Common` concept with types like `chrono::duration` (29.5 [time.duration]) which sometimes provide only explicit conversion to a common type.

Notably, removing the requirement for implicit conversion will also make the `Common` concept consistent with the description in 18.4.6 [concept.common] p1: "If `T` and `U` can both be explicitly converted to some third type, `C`, then `T` and `U` share a common type, `C`."

[2018-08 Batavia Monday issue prioritization]

P0; Status to 'Tentatively Ready' after adding two semicolons to the P/R.

[2018-11, Adopted in San Diego]

Proposed resolution:

This wording is relative to N4762.

1. Modify the definition of `Common` in 18.4.6 [concept.common] as follows:

   >     template<class T, class U>
   >       concept Common =
   >         Same<common_type_t<T, U>, common_type_t<U, T>> &&
   >         ConvertibleTo<T, common_type_t<T, U>> &&
   >         ConvertibleTo<U, common_type_t<T, U>> &&
   >         requires {
   >           static_cast<common_type_t<T, U>>(declval<T>());
   >           static_cast<common_type_t<T, U>>(declval<U>());
   >         } &&
   >         CommonReference<
   >           add_lvalue_reference_t<const T>,
   >           add_lvalue_reference_t<const U>> &&
   >         CommonReference<
   >           add_lvalue_reference_t<common_type_t<T, U>>,
   >           common_reference_t<
   >             add_lvalue_reference_t<const T>,
   >             add_lvalue_reference_t<const U>>>;