This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Open status.
std::ranges::size in ranges algorithmsSection: 26.2 [algorithms.requirements] Status: Open Submitter: Ruslan Arutyunyan Opened: 2025-12-12 Last modified: 2026-02-02
Priority: 3
View other active issues in [algorithms.requirements].
View all other issues in [algorithms.requirements].
View all issues with Open status.
Discussion:
26.2 [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.
[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?"
Previous resolution [SUPERSEDED]:
This wording is relative to N5032.
Modify 26.2 [algorithms.requirements] as indicated:
[…]
-14- Overloads of algorithms that takerangearguments (25.4.2 [range.range]) behave as if they are implemented by dispatching to the overload in namespacerangesthat takes separate iterator and sentinel arguments, where for each range argumentr
(14.1) — a corresponding iterator argument is initialized with
ranges::begin(r)and(14.2) — a corresponding sentinel argument is initialized with
one of the following:ranges::end(r), orranges::next(ranges::begin(r), ranges::end(r))if the type ofrmodelsforward_rangeand computingranges::nextmeets the specified complexity requirements.
(14.2.1) — if the type of
rmodelsforward_rangeand computingranges::nextmeets the specified complexity requirements then
(14.2.1.1) —
ranges::next(ranges::begin(r), ranges::size(r))ifrmodelssized_range, otherwise(14.2.1.2) —
ranges::next(ranges::begin(r), ranges::end(r)).(14.2.2) — Otherwise,
std::ranges::end(s).
[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-30; LWG telecon. Status → Open.]
Proposed resolution:
This wording is relative to N5032.
Modify 26.2 [algorithms.requirements] as indicated:
[…]
-14- Overloads of algorithms that takerangearguments (25.4.2 [range.range]) behave as if they are implemented by dispatching to the overload in namespacerangesthat takes separate iterator and sentinel arguments, where for each range argumentr
(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), orranges::next(ranges::begin(r), ranges::end(r))if the type ofrmodelsforward_rangeand computingranges::nextmeets the specified complexity requirements.ranges::begin(r) + NwhereNis equal toranges::distance(r).