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.
Common
and common_type
have too little in commonSection: 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 namedtype
, but if it does, that member shall be a typedef-name for an accessible and unambiguous cv-unqualified non-reference typeC
to which each of the typesT1
andT2
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
(30.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.
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>>>;