Created on 2025-12-12.00:00:00 last changed 1 week ago
Proposed resolution:
This wording is relative to N5032.
Modify [algorithms.requirements] as indicated:
[…]
-14- Overloads of algorithms that take `range` arguments ([range.range]) behave as if they are implemented by dispatching to the overload in namespace `ranges` that takes separate iterator and sentinel arguments, where for each range argument `r`
(14.1) — a corresponding iterator argument is initialized with `ranges::begin(r)` and
(14.2) — a corresponding sentinel argument is initialized with `ranges::end(r)`, or
`ranges::next(ranges::begin(r), ranges::end(r))` if the type of `r` models `forward_range` and computing `ranges::next` meets the specified complexity requirements.`ranges::begin(r) + N` where `N` is equal to `ranges::distance(r)`.
[ 2026-01-30; LWG telecon. Status → Open. ]
[ 2026-01-30; Jonathan provides new wording ]
We can just say that the value is either the end iterator, or begin+N, without saying when or how the implementation obtains begin+N. It might use `ranges::next(ranges::begin(r), std::ranges::end(r))` or `ranges::next(ranges::begin(r), ranges::distance(r))` or something else, only the value matters not how it's obtained. Paragraph 11 in the same subclause defines what begin+N means if the iterator is not a random access iterator.
[ 2026-01-16; Reflector poll. ]
Set priority to 3 after reflector poll.
"Should be 'the type of `r` models `sized_range`"
"It's a lot of words, could be shorter. Would prefer not to establish priority, but let implementation decide if/when to use `ranges::next`."
"Would `counted_iterator(ranges::begin(r), ranges::distance(r))` and `default_sentinel` be better?"
This wording is relative to N5032.
Modify [algorithms.requirements] as indicated:
[…]
-14- Overloads of algorithms that take `range` arguments ([range.range]) behave as if they are implemented by dispatching to the overload in namespace `ranges` that takes separate iterator and sentinel arguments, where for each range argument `r`
(14.1) — a corresponding iterator argument is initialized with `ranges::begin(r)` and
(14.2) — a corresponding sentinel argument is initialized with
`ranges::end(r)`, or `ranges::next(ranges::begin(r), ranges::end(r))` if the type of `r` models `forward_range` and computing `ranges::next` meets the specified complexity requirements.one of the following:
(14.2.1) — if the type of `r` models `forward_range` and computing `ranges::next` meets the specified complexity requirements then
(14.2.1.1) — `ranges::next(ranges::begin(r), ranges::size(r))` if `r` models `sized_range`, otherwise
(14.2.1.2) — `ranges::next(ranges::begin(r), ranges::end(r))`.
(14.2.2) — Otherwise, `std::ranges::end(s)`.
[algorithms.requirements] paragraph 14 says that the algorithms in `ranges` namespace are implemented as if they are dispatched to the corresponding overload with iterator and sentinel. However, there are two problems with the current wording:
We only allow to call either `std::ranges::end(r)` or `std::ranges::next(std::ranges::begin(r)`, `std::ranges::end())` to calculate a corresponding sentinel. However, this is a pessimization for some ranges because we can have sized ranges without sized_sentinel_for. Consider the following example:
const char str[] = "something";
ranges::subrange<const char*,
null_sentinel_t,
subrange_kind::sized> sr(ranges::begin(str),
null_sentinel,
ranges::size(str) - 1);
my::ranges::next(sr.begin(), sr.end()); // this line serially calculates iterator that is equal to sr.end()
Despite the fact that we know the size of the range and that the range is the random access one, `std::ranges::next` calculates the iterator serially, because it only has constant time complexity optimization for `sized_sentinel_for`. We could clearly achieve better complexity with a different API or with the different overload of the same API.
It is unclear when an algorithm calls `std::ranges::end(r)` and when it calls `std::ranges::next(std::ranges::begin(r), std::ranges::end())` to calculate the corresponding sentinel because there is no established priority between them. Maybe, it's smaller problem but still it's worth clarifying in my opinion.
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2026-01-30 23:38:56 | admin | set | status: ready -> open |
| 2026-01-30 18:22:04 | admin | set | status: new -> ready |
| 2026-01-30 18:02:58 | admin | set | messages: + msg15909 |
| 2026-01-30 18:02:58 | admin | set | messages: + msg15908 |
| 2026-01-16 22:15:24 | admin | set | messages: + msg15876 |
| 2025-12-20 11:22:52 | admin | set | messages: + msg15828 |
| 2025-12-12 00:00:00 | admin | create | |