2460. LWG issue 2408 and value categories

Section: 23.15.7.6 [meta.trans.other], 27.4.1 [iterator.traits] Status: C++17 Submitter: Richard Smith Opened: 2014-11-19 Last modified: 2017-07-30

Priority: 2

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

View all issues with C++17 status.

Discussion:

LWG issue 2408 changes the meat of the specification of common_type to compute:

[…] the type, if any, of an unevaluated conditional expression (5.16) 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.

This has an effect on the specification that I think was unintended. It used to be the case that common_type<T&, U&&> would consider the type of a conditional between an lvalue of type T and an xvalue of type U. It's now either invalid (because there is no such thing as an xvalue of reference type) or considers the type of a conditional between an xvalue of type T and an xvalue of type U, depending on how you choose to read it.

Put another way, this has the effect of changing the usual definition from:

typedef decay_t<decltype(true ? declval<T>() : declval<U>())> type;

to:

typedef decay_t<decltype(true ? declval<remove_reference_t<T>>() : declval<remove_reference_t<U>>())> type;

It also makes common_type underspecified in the case where one of the operands is of type void; in that case, the resulting type depends on whether the expression is a throw-expression, which is not specified (but used to be).

Also on the subject of this wording: the changes to 27.4.1 [iterator.traits] say that iterator_traits<T> "shall have no members" in some cases. That's wrong. It's a class type; it always has at least a copy constructor, a copy assignment operator, and a destructor. Plus this removes the usual library liberty to add additional members with names that don't collide with normal usage (for instance, if a later version of the standard adds members, they can't be present here as a conforming extension). Perhaps this should instead require that the class doesn't have members with any of those five names? That's what 2408 does for common_type's type member.

[2016-08 Chicago]

This issue has two parts, one dealing with common_type, the other with iterator_traits. The first of these is resolved by 2465. See below for the proposed resolution for the other one.

Wed PM: Move to Tentatively Ready

Proposed resolution:

Change 27.4.1 [iterator.traits] p.2:

[…] as publicly accessible members and no other members:

[…]

Otherwise, iterator_traits<Iterator> shall have no members by any of the above names.