Title
Rvalue reference and iterator_category
Status
c++23
Section
[iterator.traits]
Submitter
Jiang An

Created on 2022-10-22.00:00:00 last changed 10 months ago

Messages

Date: 2022-11-17.00:42:33

Proposed resolution:

This wording is relative to N4917.

  1. Modify [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>>;
      };
    […]
    
  2. Modify [range.transform.iterator] as indicated:

    -2- The member typedef-name iterator_category is defined if and only if Base models forward_range. In that case, iterator::iterator_category is defined as follows: Let C denote the type iterator_traits<iterator_t<Base>>::iterator_category.

    1. (2.1) — If is_lvalue_reference_v<invoke_result_t<maybe-const<Const, F>&, range_reference_t<Base>>> is true, then

      1. (2.1.1) — if C models derived_from<contiguous_iterator_tag>, iterator_category denotes random_access_iterator_tag;

      2. (2.1.2) — otherwise, iterator_category denotes C.

    2. (2.2) — Otherwise, iterator_category denotes input_iterator_tag.

  3. Modify [range.join.with.iterator] as indicated:

    -2- The member typedef-name iterator_category is defined if and only if ref-is-glvalue is true, and Base and InnerBase each model forward_range. In that case, iterator::iterator_category is defined as follows:

    1. (2.1) — […]

    2. (2.2) — If

      is_lvalue_reference_v<common_reference_t<iter_reference_t<InnerIter>,
                            iter_reference_t<PatternIter>>>
      

      is false, iterator_category denotes input_iterator_tag.

    3. (2.3) — […]

  4. Modify [range.zip.transform.iterator] as indicated:

    -1- The member typedef-name iterator::iterator_category is defined if and only if Base models forward_range. In that case, iterator::iterator_category is defined as follows:

    1. (1.1) — If

      invoke_result_t<maybe-const<Const, F>&, range_reference_t<maybe-const<Const, Views>>...>
      

      is not an lvalue reference, iterator_category denotes input_iterator_tag.

    2. (1.2) — […]

  5. Modify [range.adjacent.transform.iterator] as indicated:

    -1- The member typedef-name iterator::iterator_category is defined as follows:

    1. (1.1) — If invoke_result_t<maybe-const<Const, F>&, REPEAT(range_reference_t<Base>, N)...> is not an lvalue reference, iterator_category denotes input_iterator_tag.

    2. (1.2) — […]

Date: 2022-11-12.00:00:00

[ 2022-11-12 Approved at November 2022 meeting in Kona. Status changed: Voting → WP. ]

Date: 2022-11-15.00:00:00

[ 2022-11-01; Reflector poll ]

Set status to Tentatively Ready after eight votes in favour during reflector poll.

Date: 2022-10-22.00:00:00

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.

History
Date User Action Args
2023-11-22 15:47:43adminsetstatus: wp -> c++23
2022-11-17 00:42:33adminsetmessages: + msg13085
2022-11-17 00:42:33adminsetstatus: voting -> wp
2022-11-08 03:46:49adminsetstatus: ready -> voting
2022-11-01 17:49:19adminsetmessages: + msg12911
2022-11-01 17:49:19adminsetstatus: new -> ready
2022-10-23 12:50:58adminsetmessages: + msg12887
2022-10-22 00:00:00admincreate