Self-correction: the failure to meet requirements is only when both value_type and element_type are different - there's a separate specialisation that uses value_type if both are defined and are the same type. LWG issue 3446 added that particular specialisation.

Having both is therefore fine and meets indirectly_readable so long as they have the same type. Only if the types are inconsistent does it not meet indirectly_readable.


On 29 April 2025 07:25:16 BST, Jennifier Burnett via Std-Discussion <std-discussion@lists.isocpp.org> wrote:
Reading [readable.traits] we have the following definitions for how the source of iter_value_t may be generated:

The first provides a specialisation if the type has a typedef value_type, and uses value_type:

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

The second provides a specialisation if the type has a typedef element_type:

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

The third provides a specialisation if BOTH value_type and element_type are provided, and does not contain a definition for value_type:

>template<has-member-value-type T>
>requires has-member-element-type <T>
>struct indirectly_readable_traits<T> { };

The express intent is that a type that defines both value_type and element_type not meet the indirectly_readable concept, and thus shouldn't meet the input_iterator concept either. LWG issue 3541 addressed the earlier ambiguity with types that had both value_type and element_type by explicitly making it fail to meet the requirements.


On 29 April 2025 02:44:42 BST, "F. v.S. via Std-Discussion" <std-discussion@lists.isocpp.org> wrote:
Per current specification of std::iter_value_t, if a class type with proper member type value_type meets some C++17 iterator requirements (Cpp17InputIterator or a stronger one) but has an inconsistent member typedef element_type (e.g. void), it doesn't satisfy the std::input_iterator concept (or a stronger one) because std::iter_value_t isn't valid for that type.

Is such treatment intended? If not, perhaps there should be an LWG issue to specify that I::element_type is not detected when I::value_type is a valid type.

Thanks,
F.v.S.