Proposed resolution:
This wording is relative to N4849.
Modify [iterator.traits] as indicated:
-4- Explicit or partial specializations of iterator_traits may have a member type iterator_concept that is used to indicate conformance to the iterator concepts ([iterator.concepts]). [Example: To indicate conformance to the input_iterator concept but a lack of conformance to the Cpp17InputIterator requirements ([input.iterators]), an iterator_traits specialization might have iterator_concept denote input_iterator_tag and iterator_category denote output_iterator_tag. — end example]
Modify [common.iter.types] as indicated:
-1- The nested typedef-names of the specialization of iterator_traits for common_iterator<I, S> are defined as follows.
(1.1) — iterator_concept denotes forward_iterator_tag if I models forward_iterator; otherwise it denotes input_iterator_tag.
(1.2) — iterator_category denotes forward_iterator_tag if iterator_traits<I>::iterator_category models derived_from<forward_iterator_tag>; otherwise it denotes
input_iterator_tagiterator_traits<I>::iterator_category.(1.3) — If the expression a.operator->() is well-formed, where a is an lvalue of type const common_iterator<I, S>, then pointer denotes the type of that expression. Otherwise, pointer denotes void.
Modify [range.filter.iterator] as indicated:
-3- iterator::iterator_category is defined as follows:
(3.1) — Let C denote the type iterator_traits<iterator_t<V>>::iterator_category.
(3.2) — If C models derived_from<bidirectional_iterator_tag>, then iterator_category denotes bidirectional_iterator_tag.
(3.3) — Otherwise, if C models derived_from<forward_iterator_tag>, then iterator_category denotes forward_iterator_tag.(3.4) — Otherwise, iterator_category denotes C.
Modify [range.join.iterator] as indicated:
-2- iterator::iterator_category is defined as follows:
(2.1) — Let OUTERC denote iterator_traits<iterator_t<Base>>::iterator_category, and let INNERC denote iterator_traits<iterator_t<range_reference_t<Base>>>::iterator_category.
(2.?) — If OUTERC does not model derived_from<input_iterator_tag>, iterator_category denotes OUTERC.
(2.?) — Otherwise, if INNERC does not model derived_from<input_iterator_tag>, iterator_category denotes INNERC.
(2.2) — Otherwise, i
If ref-is-glvalue is true and OUTERC and INNERC each model derived_from<bidirectional_iterator_tag>, iterator_category denotes bidirectional_iterator_tag.(2.3) — Otherwise, if ref-is-glvalue is true and OUTERC and INNERC each model derived_from<forward_iterator_tag>, iterator_category denotes forward_iterator_tag.
(2.4) — Otherwise, if OUTERC and INNERC each model derived_from<input_iterator_tag>, iterator_category denotes input_iterator_tag.
(2.5) — Otherwise, iterator_category denotes output_iterator_tag.
Modify [range.split.outer] as indicated:
[Drafting note: The previous wording change has been adjusted to follow the pattern used in [range.split.inner] p1.]
namespace std::ranges { template<class V, class Pattern> template<bool Const> struct split_view<V, Pattern>::outer_iterator { private: […] public: using iterator_concept = conditional_t<forward_range<Base>, forward_iterator_tag, input_iterator_tag>; using iterator_category = see belowinput_iterator_tag; […] }; […] }-?- The typedef-name iterator_category denotes:
(?.?) — input_iterator_tag if iterator_traits<iterator_t<Base>>::iterator_category models derived_from<input_iterator_tag>;
(?.?) — otherwise, iterator_traits<iterator_t<Base>>::iterator_category.
-1- Many of the following specifications refer to the notional member current of outer-iterator. current is equivalent to current_ if V models forward_range, and parent_->current_ otherwise.