iterator_category
Section: 24.3.2.3 [iterator.traits] Status: C++23 Submitter: Jiang An Opened: 2022-10-22 Last modified: 2023-11-22
Priority: Not Prioritized
View all other issues in [iterator.traits].
View all issues with C++23 status.
Discussion:
Since C++11, a forward iterator may have an rvalue reference as its reference
type.
I think this is an intentional change made by N3066. However, several components
added (or changed) in C++20/23 recognize an iterator as a Cpp17ForwardIterator (by using
forward_iterator_tag
or a stronger iterator category tag type as the iterator_category
type) only if the reference
type would be an lvalue reference type, which seems a regression.
[2022-11-01; Reflector poll]
Set status to Tentatively Ready after eight votes in favour during reflector poll.
[2022-11-12 Approved at November 2022 meeting in Kona. Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4917.
Modify 24.3.2.3 [iterator.traits] as indicated:
-2- The definitions in this subclause make use of the following exposition-only concepts:
[…] template<class I> concept cpp17-forward-iterator = cpp17-input-iterator<I> && constructible_from<I> && is_lvalue_reference_v<iter_reference_t<I>> && same_as<remove_cvref_t<iter_reference_t<I>>, typename indirectly_readable_traits<I>::value_type> && requires(I i) { { i++ } -> convertible_to<const I&>; { *i++ } -> same_as<iter_reference_t<I>>; }; […]
Modify 25.7.9.3 [range.transform.iterator] as indicated:
-2- The member typedef-name
iterator_category
is defined if and only if Base modelsforward_range
. In that case,iterator::iterator_category
is defined as follows: LetC
denote the typeiterator_traits<iterator_t<Base>>::iterator_category
.
(2.1) — If
is_
islvalue_reference_v<invoke_result_t<maybe-const<Const, F>&, range_reference_t<Base>>>true
, then
(2.1.1) — if
C
modelsderived_from<contiguous_iterator_tag>
,iterator_category denotes random_access_iterator_tag
;(2.1.2) — otherwise,
iterator_category
denotesC
.(2.2) — Otherwise,
iterator_category
denotesinput_iterator_tag
.
Modify 25.7.15.3 [range.join.with.iterator] as indicated:
-2- The member typedef-name
iterator_category
is defined if and only ifref-is-glvalue
istrue
, andBase
andInnerBase
each modelforward_range
. In that case,iterator::iterator_category
is defined as follows:
(2.1) — […]
(2.2) — If
is_lvalue_reference_v<common_reference_t<iter_reference_t<InnerIter>, iter_reference_t<PatternIter>>>is
false
,iterator_category
denotesinput_iterator_tag
.(2.3) — […]
Modify 25.7.26.3 [range.zip.transform.iterator] as indicated:
-1- The member typedef-name
iterator::iterator_category
is defined if and only ifBase
modelsforward_range
. In that case,iterator::iterator_category
is defined as follows:
(1.1) — If
invoke_result_t<maybe-const<Const, F>&, range_reference_t<maybe-const<Const, Views>>...>is not a
n lvaluereference,iterator_category
denotesinput_iterator_tag
.(1.2) — […]
Modify 25.7.28.3 [range.adjacent.transform.iterator] as indicated:
-1- The member typedef-name
iterator::iterator_category
is defined as follows:
(1.1) — If
invoke_result_t<maybe-const<Const, F>&, REPEAT(range_reference_t<Base>, N)...>
is not an lvaluereference,iterator_category
denotesinput_iterator_tag
.(1.2) — […]