Issue 3798: Rvalue reference and iterator_category (original) (raw)
This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++23 status.
3798. Rvalue reference and 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_categorytype) 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
concept cpp17-forward-iterator =
cpp17-input-iterator && constructible_from &&
is_lvalue_reference_v<iter_reference_t> &&
same_as<remove_cvref_t<iter_reference_t>,
typename indirectly_readable_traits::value_type> &&
requires(I i) {
{ i++ } -> convertible_to<const I&>;
{ *i++ } -> same_as<iter_reference_t>;
};
[…] 2. Modify 25.7.9.3 [range.transform.iterator] as indicated:
-2- The member typedef-nameiterator_categoryis defined if and only if _Base_modelsforward_range. In that case,_iterator_::iterator_categoryis defined as follows: LetCdenote the typeiterator_traits<iterator_t<_Base_>>::iterator_category.
(2.1) — If
is_~~lvalue_~~reference_v<invoke_result_t<_maybe-const_<Const, F>&, range_reference_t<_Base_>>>istrue, then
- (2.1.1) — if
Cmodelsderived_from<contiguous_iterator_tag>,iterator_category denotes random_access_iterator_tag;- (2.1.2) — otherwise,
iterator_categorydenotesC.(2.2) — Otherwise,
iterator_categorydenotesinput_iterator_tag.Modify 25.7.15.3 [range.join.with.iterator] as indicated:
-2- The member typedef-nameiterator_categoryis defined if and only if_ref-is-glvalue_istrue, and_Base_and_InnerBase_each modelforward_range. In that case,_iterator_::iterator_categoryis 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_categorydenotesinput_iterator_tag.
3. (2.3) — […] 4. Modify 25.7.26.3 [range.zip.transform.iterator] as indicated:
-1- The member typedef-name_iterator_::iterator_categoryis defined if and only if_Base_modelsforward_range. In that case,_iterator_::iterator_categoryis defined as follows:
(1.1) — If
invoke_result_t<_maybe-const_<Const, F>&, range_reference_t<_maybe-const_<Const, Views>>...>
is not an lvaluereference,iterator_categorydenotesinput_iterator_tag.(1.2) — […]
Modify 25.7.28.3 [range.adjacent.transform.iterator] as indicated:
-1- The member typedef-name_iterator_::iterator_categoryis defined as follows:(1.1) — If
invoke_result_t<_maybe-const_<Const, F>&, _REPEAT_(range_reference_t<_Base_>, N)...>is not an lvaluereference,iterator_categorydenotesinput_iterator_tag.(1.2) — […]