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

### 3446. `indirectly_readable_traits` ambiguity for types with both `value_type` and `element_type`

Section: 23.3.2.2 [readable.traits] Status: WP Submitter: Casey Carter Opened: 2020-05-15 Last modified: 2020-11-09

Priority: 2

View all other issues in [readable.traits].

View all issues with WP status.

Discussion:

Per 23.3.2.2 [readable.traits], `indirectly_readable_traits<T>::value_type` is the same type as `remove_cv_t<T::value_type>` if it denotes an object type, or `remove_cv_t<T::element_type>` if it denotes an object type. If both `T::value_type` and `T::element_type` denote types, `indirectly_readable_traits<T>::value_type` is ill-formed. This was perhaps not the best design, given that there are iterators in the wild (Boost's unordered containers) that define both nested types. `indirectly_readable_traits` should tolerate iterators that define both nested types consistently.

[2020-07-17; Priority set to 2 in telecon]

Previous resolution [SUPERSEDED]:

> This wording is relative to N4861.

> 1. Modify 23.3.2.2 [readable.traits] as indicated:

>    >     […]
>    >     template<class> struct cond-value-type { }; // exposition only

>    >     template<class T>
>    >       requires is_object_v<T>
>    >     struct cond-value-type<T> {
>    >       using value_type = remove_cv_t<T>;
>    >     };

>    >     template<class> struct indirectly_readable_traits { };

>    >     […]

>    >     template<class T>
>    >       requires requires { typename T::value_type; }
>    >     struct indirectly_readable_traits<T>
>    >       : cond-value-type<typename T::value_type> { };

>    >     template<class T>
>    >       requires requires { typename T::element_type; }
>    >     struct indirectly_readable_traits<T>
>    >       : cond-value-type<typename T::element_type> { };

>    >     template<class T>
>    >       requires requires {
>    >         typename T::element_type;
>    >         typename T::value_type;
>    >         requires same_as<
>    >           remove_cv_t<typename T::element_type>,
>    >           remove_cv_t<typename T::value_type>>;
>    >       }
>    >     struct indirectly_readable_traits<T>
>    >       : cond-value-type<typename T::value_type> { };

>    >     […]

[2020-07-23; Casey improves wording per reflector discussion]

[2020-08-21; moved to Tentatively Ready after five votes in favour in reflector poll]

[2020-11-09 Approved In November virtual meeting. Status changed: Tentatively Ready → WP.]

Proposed resolution:

This wording is relative to N4861.

1. Modify 23.3.2.2 [readable.traits] as indicated:

   >     […]
   >     template<class> struct cond-value-type { }; // exposition only

   >     template<class T>
   >       requires is_object_v<T>
   >     struct cond-value-type<T> {
   >       using value_type = remove_cv_t<T>;
   >     };

   >     template<class T>
   >     concept has-member-value-type = requires { typename T::value_type; }; // exposition only

   >     template<class T>
   >     concept has-member-element-type = requires { typename T::element_type; }; // exposition only

   >     template<class> struct indirectly_readable_traits { };

   >     […]

   >     template<classhas-member-value-type T>
   >       requires requires { typename T::value_type; }
   >     struct indirectly_readable_traits<T>
   >       : cond-value-type<typename T::value_type> { };

   >     template<classhas-member-element-type T>
   >       requires requires { typename T::element_type; }
   >     struct indirectly_readable_traits<T>
   >       : cond-value-type<typename T::element_type> { };

   >     template<classhas-member-value-type T>
   >       requires has-member-element-type<T> &&
   >                same_as<remove_cv_t<typename T::element_type>, remove_cv_t<typename T::value_type>>
   >     struct indirectly_readable_traits<T>
   >       : cond-value-type<typename T::value_type> { };

   >     […]