241 lines
16 KiB
Markdown
241 lines
16 KiB
Markdown
[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 {template<class From, class To>concept [*uses-nonqualification-pointer-conversion*](#concept:uses-nonqualification-pointer-conversion "25.5.4.1 General [range.subrange.general]") = // *exposition only* is_pointer_v<From> && is_pointer_v<To> &&<remove_pointer_t<From>(*)[], remove_pointer_t<To>(*)[]>; template<class From, class To>concept [*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]")<From, To> &&<decay_t<From>, decay_t<To>>; template<class T, class U, class V>concept [*pair-like-convertible-from*](#concept:pair-like-convertible-from "25.5.4.1 General [range.subrange.general]") = // *exposition only*<T> && !is_reference_v<T> && [*pair-like*](tuple.syn#concept:pair-like "22.4.2 Header <tuple> synopsis [tuple.syn]")<T> &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]")<T, U, V> &&[*convertible-to-non-slicing*](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]")<U, tuple_element_t<0, T>> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<V, tuple_element_t<1, T>>; 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]")<I> 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]")<S, I> ? subrange_kind::sized : subrange_kind::unsized>requires (K == subrange_kind::sized || <S, I>)class subrange : public view_interface<subrange<I, S, K>> {private:static constexpr bool *StoreSize* = // *exposition only* K == subrange_kind::sized && <S, I>;
|
||
I *begin_* = I(); // *exposition only* S *end_* = S(); // *exposition only**make-unsigned-like-t*<iter_difference_t<I>> *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]")<I> = default; constexpr subrange([*convertible-to-non-slicing*](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]")<I> 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]")<I> auto i, S s, *make-unsigned-like-t*<iter_difference_t<I>> n)requires (K == subrange_kind::sized); template<[*different-from*](range.utility.helpers#concept:different-from "25.5.2 Helper concepts [range.utility.helpers]")<subrange> R>requires [borrowed_range](range.range#concept:borrowed_range "25.4.2 Ranges [range.range]")<R> &&[*convertible-to-non-slicing*](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]")<iterator_t<R>, I> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<sentinel_t<R>, S>constexpr subrange(R&& r) requires (!*StoreSize* || [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R>); 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]")<iterator_t<R>, I> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<sentinel_t<R>, S>constexpr subrange(R&& r, *make-unsigned-like-t*<iter_difference_t<I>> 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]")<subrange> PairLike>requires [*pair-like-convertible-from*](#concept:pair-like-convertible-from "25.5.4.1 General [range.subrange.general]")<PairLike, const I&, const S&>constexpr operator PairLike() const; constexpr I begin() const requires [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")<I>; constexpr I begin() requires (<I>); constexpr S end() const; constexpr bool empty() const; constexpr *make-unsigned-like-t*<iter_difference_t<I>> size() constrequires (K == subrange_kind::sized); constexpr subrange next(iter_difference_t<I> n = 1) const &requires [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_iterator [iterator.concept.forward]")<I>; constexpr subrange next(iter_difference_t<I> n = 1) &&; constexpr subrange prev(iter_difference_t<I> n = 1) constrequires [bidirectional_iterator](iterator.concept.bidir#concept:bidirectional_iterator "24.3.4.12 Concept bidirectional_iterator [iterator.concept.bidir]")<I>; constexpr subrange& advance(iter_difference_t<I> 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]")<I> S> subrange(I, S) -> subrange<I, S>; 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]")<I> S> subrange(I, S, *make-unsigned-like-t*<iter_difference_t<I>>) -> subrange<I, S, subrange_kind::sized>; template<[borrowed_range](range.range#concept:borrowed_range "25.4.2 Ranges [range.range]") R> subrange(R&&) -> subrange<iterator_t<R>, sentinel_t<R>, ([sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R> || [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<sentinel_t<R>, iterator_t<R>>)? 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*<range_difference_t<R>>) -> subrange<iterator_t<R>, sentinel_t<R>, 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]")<I> 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]")<I> auto i, S s,
|
||
make-unsigned-like-t<iter_difference_t<I>> 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]")<subrange> R>
|
||
requires [borrowed_range](range.range#concept:borrowed_range "25.4.2 Ranges [range.range]")<R> &&
|
||
[convertible-to-non-slicing](#concept:convertible-to-non-slicing "25.5.4.1 General [range.subrange.general]")<iterator_t<R>, I> &&
|
||
[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<sentinel_t<R>, S>
|
||
constexpr subrange(R&& r) requires (!StoreSize || [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R>);
|
||
`
|
||
|
||
[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<decltype(*size_*)>(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]")<subrange> PairLike>
|
||
requires [pair-like-convertible-from](#concept:pair-like-convertible-from "25.5.4.1 General [range.subrange.general]")<PairLike, const I&, const S&>
|
||
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]")<I>;
|
||
`
|
||
|
||
[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 (<I>);
|
||
`
|
||
|
||
[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<iter_difference_t<I>> 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<I> n = 1) const &
|
||
requires [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_iterator [iterator.concept.forward]")<I>;
|
||
`
|
||
|
||
[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<I> 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<I> n = 1) const
|
||
requires [bidirectional_iterator](iterator.concept.bidir#concept:bidirectional_iterator "24.3.4.12 Concept bidirectional_iterator [iterator.concept.bidir]")<I>;
|
||
`
|
||
|
||
[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<I> 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]")<I>) {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<size_t N, class I, class S, subrange_kind K>
|
||
requires ((N == 0 && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")<I>) || N == 1)
|
||
constexpr auto get(const subrange<I, S, K>& r);
|
||
template<size_t N, class I, class S, subrange_kind K>
|
||
requires (N < 2)
|
||
constexpr auto get(subrange<I, S, K>&& 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();
|