Title
elements_view needs its own sentinel type
Status
c++20
Section
[range.elements]
Submitter
Tim Song

Created on 2020-02-07.00:00:00 last changed 37 months ago

Messages

Date: 2020-06-11.16:18:56

Proposed resolution:

The proposed wording is contained in P1994R0.

Date: 2020-06-11.00:00:00

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

Date: 2020-02-10.19:13:13

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

Date: 2020-02-07.00:00:00

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.

History
Date User Action Args
2021-02-25 10:48:01adminsetstatus: wp -> c++20
2020-06-11 16:18:56adminsetmessages: + msg11327
2020-06-11 16:18:56adminsetstatus: new -> wp
2020-02-10 19:13:13adminsetmessages: + msg11021
2020-02-08 00:40:52adminsetmessages: + msg10985
2020-02-07 00:00:00admincreate