Files
cppdraft_translate/cppdraft/range/subrange.md
2025-10-25 03:02:53 +03:00

241 lines
16 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.5Views[range.view]") concept[.](#general-1.sentence-1)
Additionally, it models the[sized_range](range.sized#concept:sized_range "25.4.4Sized 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.1General[range.subrange.general]") = // *exposition only* is_pointer_v<From> && is_pointer_v<To> &&![convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<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.1General[range.subrange.general]") = // *exposition only*[convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<From, To> &&![*uses-nonqualification-pointer-conversion*](#concept:uses-nonqualification-pointer-conversion "25.5.4.1General[range.subrange.general]")<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.1General[range.subrange.general]") = // *exposition only*![range](range.range#concept:range "25.4.2Ranges[range.range]")<T> && !is_reference_v<T> && [*pair-like*](tuple.syn#concept:pair-like "22.4.2Header <tuple> synopsis[tuple.syn]")<T> &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11Concept constructible_­from[concept.constructible]")<T, U, V> &&[*convertible-to-non-slicing*](#concept:convertible-to-non-slicing "25.5.4.1General[range.subrange.general]")<U, tuple_element_t<0, T>> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept 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.6Concept input_­or_­output_­iterator[iterator.concept.iterator]") I, [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept sentinel_­for[iterator.concept.sentinel]")<I> S = I, subrange_kind K =[sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<S, I> ? subrange_kind::sized : subrange_kind::unsized>requires (K == subrange_kind::sized || ![sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<S, I>)class subrange : public view_interface<subrange<I, S, K>> {private:static constexpr bool *StoreSize* = // *exposition only* K == subrange_kind::sized && ![sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<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.12Concept default_­initializable[concept.default.init]")<I> = default; constexpr subrange([*convertible-to-non-slicing*](#concept:convertible-to-non-slicing "25.5.4.1General[range.subrange.general]")<I> auto i, S s) requires (!*StoreSize*); constexpr subrange([*convertible-to-non-slicing*](#concept:convertible-to-non-slicing "25.5.4.1General[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.2Helper concepts[range.utility.helpers]")<subrange> R>requires [borrowed_range](range.range#concept:borrowed_range "25.4.2Ranges[range.range]")<R> &&[*convertible-to-non-slicing*](#concept:convertible-to-non-slicing "25.5.4.1General[range.subrange.general]")<iterator_t<R>, I> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<sentinel_t<R>, S>constexpr subrange(R&& r) requires (!*StoreSize* || [sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")<R>); template<[borrowed_range](range.range#concept:borrowed_range "25.4.2Ranges[range.range]") R>requires [*convertible-to-non-slicing*](#concept:convertible-to-non-slicing "25.5.4.1General[range.subrange.general]")<iterator_t<R>, I> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept 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.2Helper concepts[range.utility.helpers]")<subrange> PairLike>requires [*pair-like-convertible-from*](#concept:pair-like-convertible-from "25.5.4.1General[range.subrange.general]")<PairLike, const I&, const S&>constexpr operator PairLike() const; constexpr I begin() const requires [copyable](concepts.object#concept:copyable "18.6Object concepts[concepts.object]")<I>; constexpr I begin() requires (![copyable](concepts.object#concept:copyable "18.6Object concepts[concepts.object]")<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.11Concept 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.12Concept 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.6Concept input_­or_­output_­iterator[iterator.concept.iterator]") I, [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept 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.6Concept input_­or_­output_­iterator[iterator.concept.iterator]") I, [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept 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.2Ranges[range.range]") R> subrange(R&&) -> subrange<iterator_t<R>, sentinel_t<R>, ([sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")<R> || [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept 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.2Ranges[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.1General[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.1General[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.4Sized 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.8Concept 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.2Helper concepts[range.utility.helpers]")<subrange> R>
requires [borrowed_range](range.range#concept:borrowed_range "25.4.2Ranges[range.range]")<R> &&
[convertible-to-non-slicing](#concept:convertible-to-non-slicing "25.5.4.1General[range.subrange.general]")<iterator_t<R>, I> &&
[convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<sentinel_t<R>, S>
constexpr subrange(R&& r) requires (!StoreSize || [sized_range](range.sized#concept:sized_range "25.4.4Sized 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.2Helper concepts[range.utility.helpers]")<subrange> PairLike>
requires [pair-like-convertible-from](#concept:pair-like-convertible-from "25.5.4.1General[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.6Object 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 (![copyable](concepts.object#concept:copyable "18.6Object concepts[concepts.object]")<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.11Concept 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.12Concept 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.12Concept 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.6Object 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();