[range.subrange] # 25 Ranges library [[ranges]](./#ranges) ## 25.5 Range utilities [[range.utility]](range.utility#range.subrange) ### 25.5.4 Sub-ranges [range.subrange] #### [25.5.4.1](#general) General [[range.subrange.general]](range.subrange.general) [1](#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[.](#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[.](#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*](range.utility.helpers#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*](range.utility.helpers#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](#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](#ctor-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2020) *Preconditions*: [i, s) is a valid range[.](#ctor-1.sentence-1) [2](#ctor-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2024) *Effects*: Initializes *begin_* with std​::​move(i) and *end_* withs[.](#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](#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[.](#ctor-3.sentence-1) [4](#ctor-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2044) *Effects*: Initializes *begin_* with std​::​move(i) and *end_* withs[.](#ctor-4.sentence-1) If *StoreSize* is true, initializes *size_* withn[.](#ctor-4.sentence-2) [5](#ctor-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2050) [*Note [1](#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]")[.](#ctor-5.sentence-1) — *end note*] [🔗](#lib:subrange,constructor__) `template<[different-from](range.utility.helpers#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](#ctor-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2069) *Effects*: Equivalent to: - [(6.1)](#ctor-6.1) If *StoreSize* is true,subrange(r, static_cast(ranges​::​size(r)))[.](#ctor-6.1.sentence-1) - [(6.2)](#ctor-6.2) Otherwise, subrange(ranges​::​begin(r), ranges​::​end(r))[.](#ctor-6.2.sentence-1) [🔗](#lib:operator_PairLike,subrange) `template<[different-from](range.utility.helpers#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](#ctor-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2087) *Effects*: Equivalent to: return PairLike(*begin_*, *end_*); #### [25.5.4.3](#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](#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](#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](#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](#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](#access-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L2145) *Effects*: - [(5.1)](#access-5.1) If *StoreSize* is true, equivalent to: return *size_*; - [(5.2)](#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](#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](#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](#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](#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](#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();