This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of LEWG status.
drop_view and drop_while_view should be const-iterable for input-only rangeSection: 25.7.12.2 [range.drop.view], 25.7.13.2 [range.drop.while.view] Status: LEWG Submitter: Hewill Kang Opened: 2026-03-25 Last modified: 2026-06-16
Priority: Not Prioritized
View other active issues in [range.drop.view].
View all other issues in [range.drop.view].
View all issues with LEWG status.
Discussion:
After P3725R3,
filter_view can be const-iterable as long as the underlying range is input-only range,
implying that LEWG do believe that providing const-iterable properties for views
does have some value.
drop_view and drop_while_view are also const-iterable in
the same situation, because they do not internally need to cache the begin call on the first
iteration.
[2026-05-29 LWG reflector poll; status: New → LEWG]
This wording is relative to N5032.
Modify 25.7.12.2 [range.drop.view] as indicated:
namespace std::ranges { template<view V> class drop_view : public view_interface<drop_view<V>> { public: […] constexpr auto begin() requires (!(simple-view<V> && ((random_access_range<const V> && sized_range<const V>) || (input_range<const V> && !forward_range<const V>)))); constexpr auto begin() const requires (random_access_range<const V> && sized_range<const V>) || (input_range<const V> && !forward_range<const V>); […] }; […] }constexpr auto begin() requires (!(simple-view<V> && ((random_access_range<const V> && sized_range<const V>) || (input_range<const V> && !forward_range<const V>)))); constexpr auto begin() const requires (random_access_range<const V> && sized_range<const V>) || (input_range<const V> && !forward_range<const V>);-3- Returns:
-4- Remarks: In order to provide the amortized constant-time complexity required by theranges::next(ranges::begin(base_), count_, ranges::end(base_)).rangeconcept whendrop_viewmodelsforward_range, the first overload caches the result within thedrop_viewfor use on subsequent calls.
Modify 25.7.13.2 [range.drop.while.view] as indicated:
[…]namespace std::ranges { template<view V, class Pred> requires input_range<V> && is_object_v<Pred> && indirect_unary_predicate<const Pred, iterator_t<V>> class drop_while_view : public view_interface<drop_while_view<V, Pred>> { public: […] constexpr auto begin() requires (!(simple-view<V> && input_range<const V> && !forward_range<const V>)); constexpr auto begin() const requires (input_range<const V> && !forward_range<const V> && indirect_unary_predicate<const Pred, iterator_t<const V>>); constexpr auto end() requires (!simple-view<V>) { return ranges::end(base_); } constexpr auto end() const requires range<const V> { return ranges::end(base_); } […] }; […] }constexpr auto begin() requires (!(simple-view<V> && input_range<const V> && !forward_range<const V>)); constexpr auto begin() const requires (input_range<const V> && !forward_range<const V> && indirect_unary_predicate<const Pred, iterator_t<const V>>);-3-Preconditions:
-4-Returns:pred_.has_value()istrue.ranges::find_if_not(base_, cref(*pred_)). -5-Remarks: In order to provide the amortized constant-time complexity required by therangeconcept whendrop_while_viewmodelsforward_range, the first overloadcallcaches the result within thedrop_while_viewfor use on subsequent calls.
[2026-06-16; Hewill provides new wording]
Proposed resolution:
This wording is relative to N5032.
Modify 25.2 [ranges.syn], header <ranges> synopsis, as indicated:
// mostly freestanding #include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] #include <iterator> // see [iterator.synopsis] namespace std::ranges { […] template<class T> concept sized-random-access-range = see below; // exposition only template<class T> concept single-pass-range = see below; // exposition only […] }
Modify25.4.6 [range.refinements] as indicated:
-8- The exposition-only concept
sized-random-access-rangespecifies the requirements of arangetype that is sized and allows random access to its elements.template<class T> concept sized-random-access-range = // exposition only random_access_range<T> && sized_range<T>;[Note 1: This concept constrains some parallel algorithm overloads; see [algorithms]. — end note]
-?- The exposition-only concept
single-pass-rangespecifies the requirements of arangetype that can only be traversed once and does not guarantee multi-pass safety.[Drafting note: Theinput_rangeis not required insingle-pass-rangebecause views likedrop_viewcan also apply onoutput_range.]template<class T> concept single-pass-range = // exposition only range<T> && !forward_range<T>;
Modify 25.7.8.2 [range.filter.view] as indicated:
[Drafting note:
This just reuse single-pass-range concept in `filter_view to reduce.]
namespace std::ranges {
template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
requires view<V> && is_object_v<Pred>
class filter_view : public view_interface<filter_view<V, Pred>> {
[…]
constexpr iterator<true> begin() const
requires single-pass-range(input_range<const V> && !forward_range<const V> &&
indirect_unary_predicate<const Pred, iterator_t<const V>>);
[…]
constexpr sentinel<true> end() const
requires single-pass-range(input_range<const V> && !forward_range<const V> &&
indirect_unary_predicate<const Pred, iterator_t<const V>>) {
return sentinel<true>{*this};
}
[…]
};
[…]
}
[…]constexpr iterator<true> begin() const requires single-pass-range(input_range<const V> && !forward_range<const V> && indirect_unary_predicate<const Pred, iterator_t<const V>>);-6-Preconditions:
pred_.has_value()istrue.
Modify 25.7.12.2 [range.drop.view] as indicated:
[Drafting note: This reuse exposition onlysized-random-access-range, which is defined in the same place assingle-pass-range, to reduce typing.]
namespace std::ranges { template<view V> class drop_view : public view_interface<drop_view<V>> { public: […] constexpr auto begin() requires (!(simple-view<V> && (sized-random-access-range[…]random_access_range<const V> && sized_range<const V> || single-pass-range<const V>))); constexpr auto begin() const requires sized-random-access-rangerandom_access_range<const V> && sized_range<const V> || single-pass-range<const V>; […] }; […] }constexpr auto begin() requires (!(simple-view<V> && (sized-random-access-rangerandom_access_range<const V> && sized_range<const V> || single-pass-range<const V>))); constexpr auto begin() const requires sized-random-access-rangerandom_access_range<const V> && sized_range<const V> || single-pass-range<const V>;-3-Returns:
ranges::next(ranges::begin(base_), count_, ranges::end(base_)).-4-Remarks: In order to provide the amortized constant-time complexity required by the
rangeconcept whendrop_viewmodelsforward_range, the first overload caches the result within thedrop_viewfor use on subsequent calls.
Modify 25.7.13.2 [range.drop.while.view] as indicated:
namespace std::ranges { template<view V, class Pred> requires input_range<V> && is_object_v<Pred> && indirect_unary_predicate<const Pred, iterator_t<V>> class drop_while_view : public view_interface<drop_while_view<V, Pred>> { public: […] constexpr auto begin() requires (!(simple-view<V> && single-pass-range<const V>)); constexpr auto begin() const requires single-pass-range<const V> && indirect_unary_predicate<const Pred, iterator_t<const V>>; constexpr auto end() requires (!simple-view<V>) { return ranges::end(base_); } constexpr auto end() const requires range<const V> { return ranges::end(base_); } […] }; […] }[…]constexpr auto begin() requires (!(simple-view<V> && single-pass-range<const V>)); constexpr auto begin() const requires single-pass-range<const V> && indirect_unary_predicate<const Pred, iterator_t<const V>>;-3-Preconditions:
pred_.has_value()istrue.-4-Returns:
ranges::find_if_not(base_, cref(*pred_)).-5-Remarks: In order to provide the amortized constant-time complexity required by the
rangeconcept whendrop_while_viewmodelsforward_range, the first overloadcallcaches the result within thedrop_while_viewfor use on subsequent calls.