This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Tentatively NAD status.
Section: 24.3.1 [iterator.requirements.general], 25.4.3 [range.approximately.sized], 25.4.1 [range.req.general], 25.4.2 [range.range], 25.4.4 [range.sized], 25.7.8.2 [range.filter.view], 25.7.12.2 [range.drop.view], 25.7.13.2 [range.drop.while.view], 25.7.17.2 [range.split.view], 25.7.21.2 [range.reverse.view], 25.7.30.2 [range.slide.view], 25.7.31.2 [range.chunk.by.view] Status: Tentatively NAD Submitter: Andreas Weis Opened: 2025-06-02 Last modified: 2025-10-23
Priority: Not Prioritized
View all other issues in [iterator.requirements.general].
View all issues with Tentatively NAD status.
Discussion:
Currently range views that cache the result of their operation claim an amortized 𝒪(1) worst-case runtime complexity. This is inconsistent with the established practice in algorithm analysis, where the given complexity bound must hold for all possible sequences of operations. Caching is not sufficient to lower the complexity bound here, as the sequence that contains only a single call to the operation will cause a runtime cost linear in the size of the underlying range. Thus all of the caching range operations are in fact 𝒪(n).
Apart from the caching view operations, this also has secondary impacts in other places that rely on the complexity of iterator functions, such as the iterator requirements and functions for computing the size of a range. It is unclear how desirable it is under these circumstances to continue disallowing other kinds of 𝒪(n) behavior for iterator functions. While caching offers clear benefits in the context of lazy evaluation, it cannot prevent losing the 𝒪(1) complexity guarantee. The proposed changes below therefore do not address the issue that other types of views (such as hypothetical non-caching variants of the affected views) that were previously considered invalid will become valid with these changes.[2025-10-23; Reflector poll; Status changed: New → Tentatively NAD.]
Relaxing complexity of ranges::begin/ranges::end is design change,
and not direction we want to pursue.
The "amortized constant" are not quite right words to describe intended requirements. A rework preserving the intent of current wording would be welcomed.
Proposed resolution:
This wording is relative to N5008.
Modify 24.3.1 [iterator.requirements.general] as indicated:
-14- All the categories of iterators require only those functions that are realizable for a given category in
constant time (amortized)linear time. Therefore, requirement tables and concept definitions for the iterators do not specify complexity.
Modify 25.4.3 [range.approximately.sized] as indicated:
-1- The
approximately_sized_rangeconcept refines range with the requirement that an approximation of the number of elements in the range can be determined inamortized constantlinear time usingranges::reserve_hint.
Modify 25.4.1 [range.req.general] as indicated:
-2- The
rangeconcept requires thatranges::beginandranges::endreturn an iterator and a sentinel, respectively. Thesized_rangeconcept refines range with the requirement thatranges::sizebeamortized𝒪(1n). Theviewconcept specifies requirements on arangetype to provide operations with predictable complexity.
Modify 25.4.2 [range.range] as indicated:
-2- Given an expression
tsuch thatdecltype((t))isT&,Tmodelsrangeonly if
(2.1) — […]
(2.2) — both
ranges::begin(t)andranges::end(t)areamortized constantlinear time and non-modifying, and(2.3) — […]
Modify 25.4.4 [range.sized] as indicated:
-1- The
sized_rangeconcept refinesapproximately_sized_rangewith the requirement that the number of elements in the range can be determined inamortized constantlinear time usingranges::size.template<class T> concept sized_range = approximately_sized_range<T> && requires(T& t) { ranges::size(t); };-2- Given an lvalue
tof typeremove_reference_t<T>,Tmodelssized_rangeonly if
(2.1) —
ranges::size(t)isamortized𝒪(1n), does not modifyt, and is equal toranges::distance(ranges::begin(t), ranges::end(t)), and(2.2) — […]
Modify 25.7.8.2 [range.filter.view] as indicated:
constexpr iterator begin();-3- Preconditions: […]
-4- Returns: […] -5- Remarks:In order to provide the amortized constant time complexity required by theThis function caches the result within therangeconcept whenfilter_viewmodelsforward_range, thisfilter_viewfor use on subsequent calls.
Modify 25.7.12.2 [range.drop.view] as indicated:
constexpr auto begin() requires (!(simple-view<V> && random_access_range<const V> && sized_range<const V>)); constexpr auto begin() const requires random_access_range<const V> && sized_range<const V>;-3- Returns: […]
-4- Remarks:In order to provide the amortized constant-time complexity required by theThe first overload caches the result within therangeconcept whendrop_viewmodelsforward_range, thedrop_viewfor use on subsequent calls.
Modify 25.7.13.2 [range.drop.while.view] as indicated:
constexpr auto begin();-3- Preconditions: […]
-4- Returns: […] -5- Remarks:In order to provide the amortized constant-time complexity required by theThe first call caches the result within therangeconcept whendrop_while_viewmodelsforward_range, thedrop_while_viewfor use on subsequent calls.
Modify 25.7.17.2 [range.split.view] as indicated:
constexpr iterator begin();-3- Returns: […]
-4- Remarks:In order to provide the amortized constant time complexity required by theThis function caches the result within therangeconcept, thissplit_viewfor use on subsequent calls.
Modify 25.7.21.2 [range.reverse.view] as indicated:
constexpr reverse_iterator<iterator_t<V>> begin();-2- Returns: […]
-3- Remarks:In order to provide the amortized constant time complexity required by theThis function caches the result within therangeconcept, thisreverse_viewfor use on subsequent calls.
Modify 25.7.30.2 [range.slide.view] as indicated:
constexpr auto begin() requires (!(simple-view<V> && slide-caches-nothing<const V>));[…]-3- Returns: […]
-4- Remarks:In order to provide the amortized constant-time complexity required by theThis function caches the result within therangeconcept, thisslide_viewfor use on subsequent calls whenVmodelsslide-caches-first.constexpr auto end() requires (!(simple-view<V> && slide-caches-nothing<const V>));-6- Returns: […]
-7- Remarks:In order to provide the amortized constant-time complexity required by theThis function caches the result within therangeconcept, thisslide_viewfor use on subsequent calls whenVmodelsslide-caches-first.
Modify 25.7.31.2 [range.chunk.by.view] as indicated:
constexpr iterator begin();-3- Preconditions: […]
-4- Returns: […] -5- Remarks:In order to provide the amortized constant-time complexity required by theThis function caches the result within therangeconcept, thischunk_by_viewfor use on subsequent calls.