[range.utility] # 25 Ranges library [[ranges]](./#ranges) ## 25.5 Range utilities [range.utility] ### [25.5.1](#general) General [[range.utility.general]](range.utility.general) [1](#general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1742) The components in [range.utility] are general utilities for representing and manipulating ranges[.](#general-1.sentence-1) ### [25.5.2](#helpers) Helper concepts [[range.utility.helpers]](range.utility.helpers) [1](#helpers-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1748) Many of the types in [range.utility] are specified in terms of the following exposition-only concepts:templateconcept [*simple-view*](#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]") = // *exposition only*[view](range.view#concept:view "25.4.5 Views [range.view]") && [range](range.range#concept:range "25.4.2 Ranges [range.range]") &&[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"), iterator_t> &&[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"), sentinel_t>; templateconcept [*has-arrow*](#concept:has-arrow "25.5.2 Helper concepts [range.utility.helpers]") = // *exposition only*[input_iterator](iterator.concept.input#concept:input_iterator "24.3.4.9 Concept input_­iterator [iterator.concept.input]") && (is_pointer_v || requires(const I i) { i.operator->(); }); templateconcept [*different-from*](#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]") = // *exposition only*![same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"), remove_cvref_t>; templateconcept [*range-with-movable-references*](#concept:range-with-movable-references "25.5.2 Helper concepts [range.utility.helpers]") = // *exposition only*[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") && [move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]")> &&[move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_­constructible [concept.moveconstructible]")>; ### [25.5.3](#view.interface) View interface [[view.interface]](view.interface) #### [25.5.3.1](#view.interface.general) General [[view.interface.general]](view.interface.general) [1](#view.interface.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1776) The class template view_interface is a helper for defining view-like types that offer a container-like interface[.](#view.interface.general-1.sentence-1) It is parameterized with the type that is derived from it[.](#view.interface.general-1.sentence-2) [🔗](#lib:view_interface) namespace std::ranges {templaterequires is_class_v && [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")>class view_interface {private:constexpr D& *derived*() noexcept { // *exposition only*return static_cast(*this); }constexpr const D& *derived*() const noexcept { // *exposition only*return static_cast(*this); }public:constexpr bool empty() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") || [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") {if constexpr ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"))return ranges::size(*derived*()) == 0; elsereturn ranges::begin(*derived*()) == ranges::end(*derived*()); }constexpr bool empty() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") || [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") {if constexpr ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]"))return ranges::size(*derived*()) == 0; elsereturn ranges::begin(*derived*()) == ranges::end(*derived*()); }constexpr auto cbegin() requires [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") {return ranges::cbegin(*derived*()); }constexpr auto cbegin() const requires [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") {return ranges::cbegin(*derived*()); }constexpr auto cend() requires [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") {return ranges::cend(*derived*()); }constexpr auto cend() const requires [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") {return ranges::cend(*derived*()); }constexpr explicit operator bool()requires requires { ranges::empty(*derived*()); } {return !ranges::empty(*derived*()); }constexpr explicit operator bool() constrequires requires { ranges::empty(*derived*()); } {return !ranges::empty(*derived*()); }constexpr auto data() requires [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_­iterator [iterator.concept.contiguous]")> {return to_address(ranges::begin(*derived*())); }constexpr auto data() constrequires [range](range.range#concept:range "25.4.2 Ranges [range.range]") && [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_­iterator [iterator.concept.contiguous]")> {return to_address(ranges::begin(*derived*())); }constexpr auto size() requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") &&[sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t> {return *to-unsigned-like*(ranges::end(*derived*()) - ranges::begin(*derived*())); }constexpr auto size() const requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") &&[sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t> {return *to-unsigned-like*(ranges::end(*derived*()) - ranges::begin(*derived*())); }constexpr decltype(auto) front() requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); constexpr decltype(auto) front() const requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); constexpr decltype(auto) back() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]") && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"); constexpr decltype(auto) back() constrequires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]") && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"); template<[random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") R = D>constexpr decltype(auto) operator[](range_difference_t n) {return ranges::begin(*derived*())[n]; }template<[random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") R = const D>constexpr decltype(auto) operator[](range_difference_t n) const {return ranges::begin(*derived*())[n]; }};} [2](#view.interface.general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1867) The template parameter D for view_interface may be an incomplete type[.](#view.interface.general-2.sentence-1) Before any member of the resulting specialization ofview_interface other than special member functions is referenced, D shall be complete, and model both [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]")> and [view](range.view#concept:view "25.4.5 Views [range.view]")[.](#view.interface.general-2.sentence-2) #### [25.5.3.2](#view.interface.members) Members [[view.interface.members]](view.interface.members) [🔗](#lib:front,view_interface) `constexpr decltype(auto) front() requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); constexpr decltype(auto) front() const requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"); ` [1](#view.interface.members-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1883) *Hardened preconditions*: !empty() is true[.](#view.interface.members-1.sentence-1) [2](#view.interface.members-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1887) *Effects*: Equivalent to: return *ranges​::​begin(*derived*()); [🔗](#lib:back,view_interface) `constexpr decltype(auto) back() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]") && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"); constexpr decltype(auto) back() const requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]") && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"); ` [3](#view.interface.members-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1900) *Hardened preconditions*: !empty() is true[.](#view.interface.members-3.sentence-1) [4](#view.interface.members-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1904) *Effects*: Equivalent to: return *ranges​::​prev(ranges​::​end(*derived*())); ### [25.5.4](#range.subrange) Sub-ranges [[range.subrange]](range.subrange) #### [25.5.4.1](#range.subrange.general) General [[range.subrange.general]](range.subrange.general) [1](#range.subrange.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1913) The subrange class template combines together an iterator and a sentinel into a single object that models the[view](range.view#concept:view "25.4.5 Views [range.view]") concept[.](#range.subrange.general-1.sentence-1) Additionally, it models the[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") concept when the final template parameter issubrange_kind​::​sized[.](#range.subrange.general-1.sentence-2) [🔗](#lib:subrange) namespace std::ranges {templateconcept [*uses-nonqualification-pointer-conversion*](#concept:uses-nonqualification-pointer-conversion "25.5.4.1 General [range.subrange.general]") = // *exposition only* is_pointer_v && is_pointer_v &&![convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")(*)[], remove_pointer_t(*)[]>; templateconcept [*convertible-to-non-slicing*](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]") = // *exposition only*[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]") &&![*uses-nonqualification-pointer-conversion*](#concept:uses-nonqualification-pointer-conversion "25.5.4.1 General [range.subrange.general]"), decay_t>; templateconcept [*pair-like-convertible-from*](#concept:pair-like-convertible-from "25.5.4.1 General [range.subrange.general]") = // *exposition only*![range](range.range#concept:range "25.4.2 Ranges [range.range]") && !is_reference_v && [*pair-like*](tuple.syn#concept:pair-like "22.4.2 Header synopsis [tuple.syn]") &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]") &&[*convertible-to-non-slicing*](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]")> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")>; template<[input_or_output_iterator](iterator.concept.iterator#concept:input_or_output_iterator "24.3.4.6 Concept input_­or_­output_­iterator [iterator.concept.iterator]") I, [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]") S = I, subrange_kind K =[sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]") ? subrange_kind::sized : subrange_kind::unsized>requires (K == subrange_kind::sized || ![sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"))class subrange : public view_interface> {private:static constexpr bool *StoreSize* = // *exposition only* K == subrange_kind::sized && ![sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"); I *begin_* = I(); // *exposition only* S *end_* = S(); // *exposition only**make-unsigned-like-t*> *size_* = 0; // *exposition only*; present only// if *StoreSize* is truepublic: subrange() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr subrange([*convertible-to-non-slicing*](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]") auto i, S s) requires (!*StoreSize*); constexpr subrange([*convertible-to-non-slicing*](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]") auto i, S s, *make-unsigned-like-t*> n)requires (K == subrange_kind::sized); template<[*different-from*](#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]") R>requires [borrowed_range](range.range#concept:borrowed_range "25.4.2 Ranges [range.range]") &&[*convertible-to-non-slicing*](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]"), I> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), S>constexpr subrange(R&& r) requires (!*StoreSize* || [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")); template<[borrowed_range](range.range#concept:borrowed_range "25.4.2 Ranges [range.range]") R>requires [*convertible-to-non-slicing*](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]"), I> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), S>constexpr subrange(R&& r, *make-unsigned-like-t*> n)requires (K == subrange_kind::sized): subrange{ranges::begin(r), ranges::end(r), n} {}template<[*different-from*](#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]") PairLike>requires [*pair-like-convertible-from*](#concept:pair-like-convertible-from "25.5.4.1 General [range.subrange.general]")constexpr operator PairLike() const; constexpr I begin() const requires [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]"); constexpr I begin() requires (![copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")); constexpr S end() const; constexpr bool empty() const; constexpr *make-unsigned-like-t*> size() constrequires (K == subrange_kind::sized); constexpr subrange next(iter_difference_t n = 1) const &requires [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]"); constexpr subrange next(iter_difference_t n = 1) &&; constexpr subrange prev(iter_difference_t n = 1) constrequires [bidirectional_iterator](iterator.concept.bidir#concept:bidirectional_iterator "24.3.4.12 Concept bidirectional_­iterator [iterator.concept.bidir]"); constexpr subrange& advance(iter_difference_t n); }; template<[input_or_output_iterator](iterator.concept.iterator#concept:input_or_output_iterator "24.3.4.6 Concept input_­or_­output_­iterator [iterator.concept.iterator]") I, [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]") S> subrange(I, S) -> subrange; template<[input_or_output_iterator](iterator.concept.iterator#concept:input_or_output_iterator "24.3.4.6 Concept input_­or_­output_­iterator [iterator.concept.iterator]") I, [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]") S> subrange(I, S, *make-unsigned-like-t*>) -> subrange; template<[borrowed_range](range.range#concept:borrowed_range "25.4.2 Ranges [range.range]") R> subrange(R&&) -> subrange, sentinel_t, ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") || [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]"), iterator_t>)? subrange_kind::sized : subrange_kind::unsized>; template<[borrowed_range](range.range#concept:borrowed_range "25.4.2 Ranges [range.range]") R> subrange(R&&, *make-unsigned-like-t*>) -> subrange, sentinel_t, subrange_kind::sized>;} #### [25.5.4.2](#range.subrange.ctor) Constructors and conversions [[range.subrange.ctor]](range.subrange.ctor) [🔗](#lib:subrange,constructor) `constexpr subrange([convertible-to-non-slicing](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]") auto i, S s) requires (!StoreSize); ` [1](#range.subrange.ctor-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2020) *Preconditions*: [i, s) is a valid range[.](#range.subrange.ctor-1.sentence-1) [2](#range.subrange.ctor-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2024) *Effects*: Initializes *begin_* with std​::​move(i) and *end_* withs[.](#range.subrange.ctor-2.sentence-1) [🔗](#lib:subrange,constructor_) `constexpr subrange([convertible-to-non-slicing](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]") auto i, S s, make-unsigned-like-t> n) requires (K == subrange_kind::sized); ` [3](#range.subrange.ctor-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2038) *Preconditions*: [i, s) is a valid range, andn == *to-unsigned-like*(ranges​::​distance(i, s)) is true[.](#range.subrange.ctor-3.sentence-1) [4](#range.subrange.ctor-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2044) *Effects*: Initializes *begin_* with std​::​move(i) and *end_* withs[.](#range.subrange.ctor-4.sentence-1) If *StoreSize* is true, initializes *size_* withn[.](#range.subrange.ctor-4.sentence-2) [5](#range.subrange.ctor-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2050) [*Note [1](#range.subrange.ctor-note-1)*: Accepting the length of the range and storing it to later return fromsize() enables subrange to model [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") even when it stores an iterator and sentinel that do not model[sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_­sentinel_­for [iterator.concept.sizedsentinel]")[.](#range.subrange.ctor-5.sentence-1) — *end note*] [🔗](#lib:subrange,constructor__) `template<[different-from](#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]") R> requires [borrowed_range](range.range#concept:borrowed_range "25.4.2 Ranges [range.range]") && [convertible-to-non-slicing](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]"), I> && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), S> constexpr subrange(R&& r) requires (!StoreSize || [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")); ` [6](#range.subrange.ctor-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2069) *Effects*: Equivalent to: - [(6.1)](#range.subrange.ctor-6.1) If *StoreSize* is true,subrange(r, static_cast(ranges​::​size(r)))[.](#range.subrange.ctor-6.1.sentence-1) - [(6.2)](#range.subrange.ctor-6.2) Otherwise, subrange(ranges​::​begin(r), ranges​::​end(r))[.](#range.subrange.ctor-6.2.sentence-1) [🔗](#lib:operator_PairLike,subrange) `template<[different-from](#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]") PairLike> requires [pair-like-convertible-from](#concept:pair-like-convertible-from "25.5.4.1 General [range.subrange.general]") constexpr operator PairLike() const; ` [7](#range.subrange.ctor-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2087) *Effects*: Equivalent to: return PairLike(*begin_*, *end_*); #### [25.5.4.3](#range.subrange.access) Accessors [[range.subrange.access]](range.subrange.access) [🔗](#lib:begin,subrange) `constexpr I begin() const requires [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]"); ` [1](#range.subrange.access-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2100) *Effects*: Equivalent to: return *begin_*; [🔗](#lib:begin,subrange_) `constexpr I begin() requires (![copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")); ` [2](#range.subrange.access-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2111) *Effects*: Equivalent to: return std​::​move(*begin_*); [🔗](#lib:end,subrange) `constexpr S end() const; ` [3](#range.subrange.access-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2122) *Effects*: Equivalent to: return *end_*; [🔗](#lib:empty,subrange) `constexpr bool empty() const; ` [4](#range.subrange.access-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2133) *Effects*: Equivalent to: return *begin_* == *end_*; [🔗](#lib:size,subrange) `constexpr make-unsigned-like-t> size() const requires (K == subrange_kind::sized); ` [5](#range.subrange.access-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2145) *Effects*: - [(5.1)](#range.subrange.access-5.1) If *StoreSize* is true, equivalent to: return *size_*; - [(5.2)](#range.subrange.access-5.2) Otherwise, equivalent to: return *to-unsigned-like*(*end_* - *begin_*); [🔗](#lib:next,subrange) `constexpr subrange next(iter_difference_t n = 1) const & requires [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]"); ` [6](#range.subrange.access-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2160) *Effects*: Equivalent to:auto tmp = *this; tmp.advance(n);return tmp; [🔗](#lib:next,subrange_) `constexpr subrange next(iter_difference_t n = 1) &&; ` [7](#range.subrange.access-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2176) *Effects*: Equivalent to:advance(n);return std::move(*this); [🔗](#lib:prev,subrange) `constexpr subrange prev(iter_difference_t n = 1) const requires [bidirectional_iterator](iterator.concept.bidir#concept:bidirectional_iterator "24.3.4.12 Concept bidirectional_­iterator [iterator.concept.bidir]"); ` [8](#range.subrange.access-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2192) *Effects*: Equivalent to:auto tmp = *this; tmp.advance(-n);return tmp; [🔗](#lib:advance,subrange) `constexpr subrange& advance(iter_difference_t n); ` [9](#range.subrange.access-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2208) *Effects*: Equivalent to:if constexpr ([bidirectional_iterator](iterator.concept.bidir#concept:bidirectional_iterator "24.3.4.12 Concept bidirectional_­iterator [iterator.concept.bidir]")) {if (n < 0) { ranges::advance(*begin_*, n); if constexpr (*StoreSize*)*size_* += *to-unsigned-like*(-n); return *this; }}auto d = n - ranges::advance(*begin_*, n, *end_*);if constexpr (*StoreSize*)*size_* -= *to-unsigned-like*(d);return *this; [🔗](#lib:get,subrange) `template requires ((N == 0 && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")) || N == 1) constexpr auto get(const subrange& r); template requires (N < 2) constexpr auto get(subrange&& r); ` [10](#range.subrange.access-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2239) *Effects*: Equivalent to:if constexpr (N == 0)return r.begin();elsereturn r.end(); ### [25.5.5](#range.dangling) Dangling iterator handling [[range.dangling]](range.dangling) [1](#range.dangling-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2252) The type dangling is used together with the template aliasesborrowed_iterator_t and borrowed_subrange_t[.](#range.dangling-1.sentence-1) When an algorithm that typically returns an iterator into, or a subrange of, a range argument is called with an rvalue range argument that does not model [borrowed_range](range.range#concept:borrowed_range "25.4.2 Ranges [range.range]") ([[range.range]](range.range "25.4.2 Ranges")), the return value possibly refers to a range whose lifetime has ended[.](#range.dangling-1.sentence-2) In such cases, the type dangling is returned instead of an iterator or subrange[.](#range.dangling-1.sentence-3) [🔗](#lib:dangling) namespace std::ranges {struct dangling {constexpr dangling() noexcept = default; constexpr dangling(auto&&...) noexcept {}};} [2](#range.dangling-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2272) [*Example [1](#range.dangling-example-1)*: vector f();auto result1 = ranges::find(f(), 42); // #1static_assert([same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"));auto vec = f();auto result2 = ranges::find(vec, 42); // #2static_assert([same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")::iterator>);auto result3 = ranges::find(ranges::subrange{vec}, 42); // #3static_assert([same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")::iterator>); The call to ranges​::​find at #1 returns ranges​::​dangling since f() is an rvalue vector; it is possible for the vector to be destroyed before a returned iterator is dereferenced[.](#range.dangling-2.sentence-1) However, the calls at #2 and #3 both return iterators since the lvalue vec and specializations of subrange model [borrowed_range](range.range#concept:borrowed_range "25.4.2 Ranges [range.range]")[.](#range.dangling-2.sentence-2) — *end example*] [3](#range.dangling-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2293) For a type R that models [range](range.range#concept:range "25.4.2 Ranges [range.range]"): - [(3.1)](#range.dangling-3.1) if R models [borrowed_range](range.range#concept:borrowed_range "25.4.2 Ranges [range.range]"), thenborrowed_iterator_t denotes iterator_t, andborrowed_subrange_t denotes subrange>; - [(3.2)](#range.dangling-3.2) otherwise, both borrowed_iterator_t and borrowed_subrange_t denote dangling[.](#range.dangling-3.sentence-1) ### [25.5.6](#range.elementsof) Class template elements_of [[range.elementsof]](range.elementsof) Specializations of elements_of encapsulate a range and act as a tag in overload sets to disambiguate when a range should be treated as a sequence rather than a single value[.](#range.elementsof-sentence-1) [*Example [1](#range.elementsof-example-1)*: template generator f(ranges::[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") auto&& r) {if constexpr (YieldElements)co_yield ranges::elements_of(r); // yield each element of relseco_yield r; // yield r as a single value} — *end example*] namespace std::ranges {template<[range](range.range#concept:range "25.4.2 Ranges [range.range]") R, class Allocator = allocator>struct elements_of {[[no_unique_address]] R range; [[no_unique_address]] Allocator allocator = Allocator(); }; template> elements_of(R&&, Allocator = Allocator()) -> elements_of;} ### [25.5.7](#conv) Range conversions [[range.utility.conv]](range.utility.conv) #### [25.5.7.1](#conv.general) General [[range.utility.conv.general]](range.utility.conv.general) [1](#conv.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2342) The range conversion functions construct an object (usually a container) from a range, by using a constructor taking a range, a from_range_t tagged constructor, or a constructor taking a pair of iterators, or by inserting each element of the range into the default-constructed object[.](#conv.general-1.sentence-1) [2](#conv.general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2350) ranges​::​to is applied recursively, allowing the conversion of a range of ranges[.](#conv.general-2.sentence-1) [*Example [1](#conv.general-example-1)*: string_view str = "the quick brown fox";auto words = views::split(str, ' ') | to>();// words is vector{"the", "quick", "brown", "fox"} — *end example*] [3](#conv.general-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2362) Let *reservable-container* be defined as follows:templateconstexpr bool *reservable-container* = // *exposition only*[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]") &&requires(Container& c, range_size_t n) { c.reserve(n); { c.capacity() } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"); { c.max_size() } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"); }; [4](#conv.general-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2375) Let *container-appendable* be defined as follows:templateconstexpr bool *container-appendable* = // *exposition only*requires(Container& c, Ref&& ref) {requires (requires { c.emplace_back(std::forward(ref)); } ||requires { c.push_back(std::forward(ref)); } ||requires { c.emplace(c.end(), std::forward(ref)); } ||requires { c.insert(c.end(), std::forward(ref)); }); }; [5](#conv.general-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2388) Let *container-append* be defined as follows:templateconstexpr auto *container-append*(Container& c) { // *exposition only*return [&c](Ref&& ref) {if constexpr (requires { c.emplace_back(declval()); }) c.emplace_back(std::forward(ref)); else if constexpr (requires { c.push_back(declval()); }) c.push_back(std::forward(ref)); else if constexpr (requires { c.emplace(c.end(), declval()); }) c.emplace(c.end(), std::forward(ref)); else c.insert(c.end(), std::forward(ref)); };} #### [25.5.7.2](#conv.to) ranges​::​to [[range.utility.conv.to]](range.utility.conv.to) [🔗](#lib:to,ranges) `template requires (![view](range.view#concept:view "25.4.5 Views [range.view]")) constexpr C to(R&& r, Args&&... args); ` [1](#conv.to-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2415) *Mandates*: C is a cv-unqualified class type[.](#conv.to-1.sentence-1) [2](#conv.to-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2419) *Returns*: An object of type C constructed from the elements of r in the following manner: - [(2.1)](#conv.to-2.1) If C does not satisfy [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") or[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]"), range_value_t> is true: * [(2.1.1)](#conv.to-2.1.1) If [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]") is true:C(std::forward(r), std::forward(args)...) * [(2.1.2)](#conv.to-2.1.2) Otherwise, if[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]") is true:C(from_range, std::forward(r), std::forward(args)...) * [(2.1.3)](#conv.to-2.1.3) Otherwise, if + [(2.1.3.1)](#conv.to-2.1.3.1) [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]") is true, + [(2.1.3.2)](#conv.to-2.1.3.2) the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]")iterator_traits>​::​iterator_category is valid and denotes a type that models[derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]"), and + [(2.1.3.3)](#conv.to-2.1.3.3) [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]"), sentinel_t, Args...> is true: C(ranges::begin(r), ranges::end(r), std::forward(args)...) * [(2.1.4)](#conv.to-2.1.4) Otherwise, if + [(2.1.4.1)](#conv.to-2.1.4.1) [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]") is true, and + [(2.1.4.2)](#conv.to-2.1.4.2) *container-appendable*> is true: C c(std::forward(args)...);if constexpr ([approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]") && *reservable-container*) c.reserve(static_cast>(ranges::reserve_hint(r))); ranges::for_each(r, *container-append*(c)); * [(2.1.5)](#conv.to-2.1.5) Otherwise, the program is ill-formed[.](#conv.to-2.1.sentence-1) - [(2.2)](#conv.to-2.2) Otherwise, if [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")> is true:to(ref_view(r) | views::transform([](auto&& elem) {return to>(std::forward(elem));}), std::forward(args)...); - [(2.3)](#conv.to-2.3) Otherwise, the program is ill-formed[.](#conv.to-2.3.sentence-1) [🔗](#lib:to,ranges_) `template class C, [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R, class... Args> constexpr auto to(R&& r, Args&&... args); ` [3](#conv.to-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2497) Let *input-iterator* be an exposition-only type:struct *input-iterator* { // *exposition only*using iterator_category = input_iterator_tag; using value_type = range_value_t; using difference_type = ptrdiff_t; using pointer = add_pointer_t>; using reference = range_reference_t; reference operator*() const; pointer operator->() const; *input-iterator*& operator++(); *input-iterator* operator++(int); bool operator==(const *input-iterator*&) const;}; [*Note [1](#conv.to-note-1)*: *input-iterator* meets the syntactic requirements of *Cpp17InputIterator*[.](#conv.to-3.sentence-1) — *end note*] [4](#conv.to-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2518) Let *DEDUCE_EXPR* be defined as follows: - [(4.1)](#conv.to-4.1) C(declval(), declval()...) if that is a valid expression, - [(4.2)](#conv.to-4.2) otherwise, C(from_range, declval(), declval()...) if that is a valid expression, - [(4.3)](#conv.to-4.3) otherwise,C(declval<*input-iterator*>(), declval<*input-iterator*>(), declval()...) if that is a valid expression, - [(4.4)](#conv.to-4.4) otherwise, the program is ill-formed[.](#conv.to-4.sentence-1) [5](#conv.to-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2536) *Returns*: to(std​::​forward(r), std​::​forward(args)...)[.](#conv.to-5.sentence-1) #### [25.5.7.3](#conv.adaptors) ranges​::​to adaptors [[range.utility.conv.adaptors]](range.utility.conv.adaptors) [🔗](#lib:to,ranges__) `template requires (![view](range.view#concept:view "25.4.5 Views [range.view]")) constexpr auto to(Args&&... args); template class C, class... Args> constexpr auto to(Args&&... args); ` [1](#conv.adaptors-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2552) *Mandates*: For the first overload,C is a cv-unqualified class type[.](#conv.adaptors-1.sentence-1) [2](#conv.adaptors-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2557) *Returns*: A range adaptor closure object ([[range.adaptor.object]](range.adaptor.object "25.7.2 Range adaptor objects")) f that is a perfect forwarding call wrapper ([[func.require]](func.require#term.perfect.forwarding.call.wrapper "22.10.4 Requirements")) with the following properties: - [(2.1)](#conv.adaptors-2.1) It has no target object[.](#conv.adaptors-2.1.sentence-1) - [(2.2)](#conv.adaptors-2.2) Its bound argument entities bound_args consist of objects of types decay_t... direct-non-list-initialized with std​::​forward(args)..., respectively[.](#conv.adaptors-2.2.sentence-1) - [(2.3)](#conv.adaptors-2.3) Its call pattern is to(r, bound_args...), where r is the argument used in a function call expression of f[.](#conv.adaptors-2.3.sentence-1)