2408. SFINAE-friendly common_type/iterator_traits is missing in C++14

Section: 21.3.8.7 [meta.trans.other], 24.3.2.3 [iterator.traits] Status: C++17 Submitter: Daniel Krügler Opened: 2014-06-19 Last modified: 2017-07-30

Priority: Not Prioritized

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

View all issues with C++17 status.

Discussion:

During the Rapperswil meeting the proposal N4041 had been discussed and there seemed to be strong consensus to apply the SFINAE-friendly definitions that currently exist within the fundamentals-ts to the C++ Standard working draft. This issue requests this change to happen.

Proposed resolution:

This wording is relative to N3936.

  1. Change 21.3.8.7 [meta.trans.other] p3 as indicated:

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

    • If sizeof...(T) is one, let T0 denote the sole type comprising T. The member typedef type shall denote the same type as decay_t<T0>.

    • If sizeof...(T) is greater than one, 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] Finally, 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. 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.

    The nested typedef common_type::type shall be defined as follows:

    template <class ...T> struct common_type;
    
    template <class T>
    struct common_type<T> {
      typedef decay_t<T> type;
    };
    
    template <class T, class U>
    struct common_type<T, U> {
      typedef decay_t<decltype(true ? declval<T>() : declval<U>())> type;
    };
    
    template <class T, class U, class... V>
    struct common_type<T, U, V...> {
      typedef common_type_t<common_type_t<T, U>, V...> type;
    };
    
  2. Change 24.3.2.3 [iterator.traits] p2 as indicated:

    -2- The template iterator_traits<Iterator> is defined asshall have the following as publicly accessible members, and have no other members, if and only if Iterator has valid (13.10.3 [temp.deduct]) member types difference_type, value_type, pointer, reference, and iterator_category; otherwise, the template shall have no members:

    namespace std {
      template<class Iterator> struct iterator_traits {
        typedef typename Iterator::difference_type difference_type;
        typedef typename Iterator::value_type value_type;
        typedef typename Iterator::pointer pointer;
        typedef typename Iterator::reference reference;
        typedef typename Iterator::iterator_category iterator_category;
      };
    }