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

### 3386. `elements_view` needs its own `sentinel` type

Section: 24.7.18 [range.elements] Status: C++20 Submitter: Tim Song Opened: 2020-02-07 Last modified: 2021-02-25

Priority: 1

View all issues with C++20 status.

Discussion:

`elements_view` is effectively a specialized version of `transform_view`. The latter has a custom `sentinel` type, and so should `elements_view`.

In particular, it should not use the underlying range's sentinel directly, for that sentinel could encode a generic predicate that is equally meaningful for the adapted range. Consider a range `[i, s)` whose `value_type` is `pair<array<int, 2>, long>`, where `s` is a generic sentinel that checks if the second element (for this range in particular, the `long`) is zero:

>     struct S {
>       friend bool operator==(input_iterator auto const& i, S) /* additional constraints */
>       { return get<1>(*i) == 0; }
>     };

If we adapt `[i, s)` with `views::keys`, then the resulting adapted range would have surprising behavior when used with `S{}`: even though it's nominally a range of `array<int, 2>`, when its iterator is used with the sentinel `S{}` it doesn't actually check the second element of the array, but the `long` that's not even part of the `value_type`:

>     void algo(input_range auto&& r) /* constraints */{
>       // We want to stop at the first element of the range r whose second element is zero.
>       for (auto&& x : subrange{ranges::begin(r), S{}})
>       {
>         std::cout << get<0>(x);
>       }
>     }

>     using P = pair<array<int, 2>, long>;
>     vector<P> vec =  {
>         { {0, 1}, 1L },
>         { {1, 0}, 1L },
>         { {2, 2}, 0L }
>     };

>     subrange r{vec.begin(), S{}};              // range with two elements: {0, 1}, {1, 0}

>     algo(r | views::keys);                     // checks the long, prints '01'
>     algo(r | views::transform(&P::first));     // checks the second element of the array, prints '0'

This is an API break since it changes the return type of `end()`, so it should be fixed before we ship C++20.

[2020-02 Prioritized as P1 Monday morning in Prague]

[2020-06-11 Voted into the WP in Prague. Status changed: New → WP.]

Proposed resolution:

The proposed wording is contained in P1994R0.