This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of WP status.

### 3564. `transform_view::iterator<true>::value_type` and `iterator_category` should use `const F&`

Section: 26.7.9.3 [range.transform.iterator] Status: WP Submitter: Tim Song Opened: 2021-06-06 Last modified: 2022-07-25

Priority: 2

View all other issues in [range.transform.iterator].

View all issues with WP status.

Discussion:

Iterators obtained from a `const transform_view` invoke the transformation function as `const`, but the `value_type` and `iterator_category` determination uses plain `F&`, i.e., non-`const`.

[2021-06-14; Reflector poll]

Set priority to 2 after reflector poll, send to SG9 for design clarification. Should `r` and `as_const(r)` guarantee same elements?

[2022-07-08; Reflector poll]

SG9 has decided to proceed with this PR in its 2021-09-13 telecon and not block the issue for a paper on the more general const/non-const problem.

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

[2022-07-15; LWG telecon: move to Ready]

[2022-07-25 Approved at July 2022 virtual plenary. Status changed: Ready → WP.]

Proposed resolution:

This wording is relative to N4885.

1. Modify 26.7.9.3 [range.transform.iterator] as indicated:

   > >     namespace std::ranges {
   > >       template<input_range V, copy_constructible F>
   > >         requires view<V> && is_object_v<F> &&
   > >                  regular_invocable<F&, range_reference_t<V>> &&
   > >                  can-reference<invoke_result_t<F&, range_reference_t<V>>>
   > >       template<bool Const>
   > >       class transform_view<V, F>::iterator {
   > >       private:
   > >         […]
   > >       public:
   > >         using iterator_concept = see below;
   > >         using iterator_category = see below; // not always present
   > >         using value_type =
   > >           remove_cvref_t<invoke_result_t<maybe-const<Const, F>&,
   > >           range_reference_t<Base>>>;
   > >         using difference_type = range_difference_t<Base>;
   > >         […]
   > >       };
   > >     }

   > -1- […]

   > -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) — […]

   >    2. (2.1.2) — […]

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