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

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

Section: 21.3.8.7 [meta.trans.other], 25.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 25.3.2.3 [iterator.traits] p2 as indicated:

   > -2- The template `iterator_traits<Iterator>` is defined as shall 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;
   > >       };
   > >     }