Files
2025-10-25 03:02:53 +03:00

170 lines
13 KiB
Markdown
Raw Permalink 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.take]
# 25 Ranges library [[ranges]](./#ranges)
## 25.7 Range adaptors [[range.adaptors]](range.adaptors#range.take)
### 25.7.10 Take view [range.take]
#### [25.7.10.1](#overview) Overview [[range.take.overview]](range.take.overview)
[1](#overview-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5864)
take_view produces a view of the first N elements
from another view, or all the elements if the adapted
view contains fewer than N[.](#overview-1.sentence-1)
[2](#overview-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5869)
The name views::take denotes a
range adaptor object ([[range.adaptor.object]](range.adaptor.object "25.7.2Range adaptor objects"))[.](#overview-2.sentence-1)
Let E and F be expressions,
let T be remove_cvref_t<decltype((E))>, and
let D be range_difference_t<decltype((E))>[.](#overview-2.sentence-2)
If decltype((F)) does not model[convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<D>,views::take(E, F) is ill-formed[.](#overview-2.sentence-3)
Otherwise, the expression views::take(E, F) is expression-equivalent to:
- [(2.1)](#overview-2.1)
If T is a specialization
of empty_view ([[range.empty.view]](range.empty.view "25.6.2.2Class template empty_­view")),
then ((void)F, *decay-copy*(E)),
except that the evaluations of E and F are indeterminately sequenced[.](#overview-2.1.sentence-1)
- [(2.2)](#overview-2.2)
Otherwise, if T models[random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]") and [sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]") and is a specialization ofspan ([[views.span]](views.span "23.7.2.2Class template span")),basic_string_view ([[string.view]](string.view "27.3String view classes")), orsubrange ([[range.subrange]](range.subrange "25.5.4Sub-ranges")),
thenU(ranges::begin(E),
ranges::begin(E) + std::min<D>(ranges::distance(E), F)),
except that E is evaluated only once,
where U is a type determined as follows:
* [(2.2.1)](#overview-2.2.1)
if T is a specialization of span,
then U is span<typename T::element_type>;
* [(2.2.2)](#overview-2.2.2)
otherwise, if T is a specialization of basic_string_view,
then U is T;
* [(2.2.3)](#overview-2.2.3)
otherwise, T is a specialization of subrange, andU is subrange<iterator_t<T>>;
- [(2.3)](#overview-2.3)
otherwise, if T is
a specialization of iota_view ([[range.iota.view]](range.iota.view "25.6.4.2Class template iota_­view"))
that models [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]") and [sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]"),
theniota_view(*ranges::begin(E),*(ranges::begin(E) + std::min<D>(ranges::distance(E), F))),
except that E is evaluated only once[.](#overview-2.3.sentence-1)
- [(2.4)](#overview-2.4)
Otherwise, if T is
a specialization of repeat_view ([[range.repeat.view]](range.repeat.view "25.6.5.2Class template repeat_­view")):
* [(2.4.1)](#overview-2.4.1)
if T models [sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]"),
thenviews::repeat(*E.*value_*, std::min<D>(ranges::distance(E), F)) except that E is evaluated only once;
* [(2.4.2)](#overview-2.4.2)
otherwise, views::repeat(*E.*value_*, static_cast<D>(F))[.](#overview-2.4.sentence-1)
- [(2.5)](#overview-2.5)
Otherwise, take_view(E, F)[.](#overview-2.5.sentence-1)
[3](#overview-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L5938)
[*Example [1](#overview-example-1)*: vector<int> is{0,1,2,3,4,5,6,7,8,9};for (int i : is | views::take(5)) cout << i << ' '; // prints 0 1 2 3 4 — *end example*]
#### [25.7.10.2](#view) Class template take_view [[range.take.view]](range.take.view)
[🔗](#lib:take_view)
namespace std::ranges {template<[view](range.view#concept:view "25.4.5Views[range.view]") V>class take_view : public view_interface<take_view<V>> {private: V *base_* = V(); // *exposition only* range_difference_t<V> *count_* = 0; // *exposition only*// [[range.take.sentinel]](#sentinel "25.7.10.3Class template take_­view::sentinel"), class template take_view::*sentinel*template<bool> class *sentinel*; // *exposition only*public: take_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12Concept default_­initializable[concept.default.init]")<V> = default; constexpr explicit take_view(V base, range_difference_t<V> count); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14Concept copy_­constructible[concept.copyconstructible]")<V> { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2Helper concepts[range.utility.helpers]")<V>) {if constexpr ([sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")<V>) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<V>) {return ranges::begin(*base_*); } else {auto sz = range_difference_t<V>(size()); return counted_iterator(ranges::begin(*base_*), sz); }} else if constexpr ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<sentinel_t<V>, iterator_t<V>>) {auto it = ranges::begin(*base_*); auto sz = std::min(*count_*, ranges::end(*base_*) - it); return counted_iterator(std::move(it), sz); } else {return counted_iterator(ranges::begin(*base_*), *count_*); }}constexpr auto begin() const requires [range](range.range#concept:range "25.4.2Ranges[range.range]")<const V> {if constexpr ([sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")<const V>) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<const V>) {return ranges::begin(*base_*); } else {auto sz = range_difference_t<const V>(size()); return counted_iterator(ranges::begin(*base_*), sz); }} else if constexpr ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<sentinel_t<const V>, iterator_t<const V>>) {auto it = ranges::begin(*base_*); auto sz = std::min(*count_*, ranges::end(*base_*) - it); return counted_iterator(std::move(it), sz); } else {return counted_iterator(ranges::begin(*base_*), *count_*); }}constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2Helper concepts[range.utility.helpers]")<V>) {if constexpr ([sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")<V>) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<V>)return ranges::begin(*base_*) + range_difference_t<V>(size()); elsereturn default_sentinel; } else if constexpr ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<sentinel_t<V>, iterator_t<V>>) {return default_sentinel; } else {return *sentinel*<false>{ranges::end(*base_*)}; }}constexpr auto end() const requires [range](range.range#concept:range "25.4.2Ranges[range.range]")<const V> {if constexpr ([sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")<const V>) {if constexpr ([random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<const V>)return ranges::begin(*base_*) + range_difference_t<const V>(size()); elsereturn default_sentinel; } else if constexpr ([sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<sentinel_t<const V>, iterator_t<const V>>) {return default_sentinel; } else {return *sentinel*<true>{ranges::end(*base_*)}; }}constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")<V> {auto n = ranges::size(*base_*); return ranges::min(n, static_cast<decltype(n)>(*count_*)); }constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")<const V> {auto n = ranges::size(*base_*); return ranges::min(n, static_cast<decltype(n)>(*count_*)); }constexpr auto reserve_hint() {if constexpr ([approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3Approximately sized ranges[range.approximately.sized]")<V>) {auto n = static_cast<range_difference_t<V>>(ranges::reserve_hint(*base_*)); return *to-unsigned-like*(ranges::min(n, *count_*)); }return *to-unsigned-like*(*count_*); }constexpr auto reserve_hint() const {if constexpr ([approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3Approximately sized ranges[range.approximately.sized]")<const V>) {auto n = static_cast<range_difference_t<const V>>(ranges::reserve_hint(*base_*)); return *to-unsigned-like*(ranges::min(n, *count_*)); }return *to-unsigned-like*(*count_*); }}; template<class R> take_view(R&&, range_difference_t<R>)-> take_view<views::all_t<R>>;}
[🔗](#lib:take_view,constructor)
`constexpr explicit take_view(V base, range_difference_t<V> count);
`
[1](#view-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6071)
*Preconditions*: count >= 0 is true[.](#view-1.sentence-1)
[2](#view-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6075)
*Effects*: Initializes *base_* with std::move(base) and*count_* with count[.](#view-2.sentence-1)
#### [25.7.10.3](#sentinel) Class template take_view::*sentinel* [[range.take.sentinel]](range.take.sentinel)
[🔗](#lib:take_view::sentinel)
namespace std::ranges {template<[view](range.view#concept:view "25.4.5Views[range.view]") V>template<bool Const>class take_view<V>::*sentinel* {private:using *Base* = *maybe-const*<Const, V>; // *exposition only*template<bool OtherConst>using *CI* = counted_iterator<iterator_t<*maybe-const*<OtherConst, V>>>; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*public:*sentinel*() = default; constexpr explicit *sentinel*(sentinel_t<*Base*> end); constexpr *sentinel*(*sentinel*<!Const> s)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<sentinel_t<V>, sentinel_t<*Base*>>; constexpr sentinel_t<*Base*> base() const; friend constexpr bool operator==(const *CI*<Const>& y, const *sentinel*& x); template<bool OtherConst = !Const>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept sentinel_­for[iterator.concept.sentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr bool operator==(const *CI*<OtherConst>& y, const *sentinel*& x); };}
[🔗](#lib:take_view::sentinel,constructor)
`constexpr explicit sentinel(sentinel_t<Base> end);
`
[1](#sentinel-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6118)
*Effects*: Initializes *end_* with end[.](#sentinel-1.sentence-1)
[🔗](#lib:take_view::sentinel,constructor_)
`constexpr sentinel(sentinel<!Const> s)
requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
`
[2](#sentinel-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6130)
*Effects*: Initializes *end_* with std::move(s.*end_*)[.](#sentinel-2.sentence-1)
[🔗](#lib:base,take_view::sentinel)
`constexpr sentinel_t<Base> base() const;
`
[3](#sentinel-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6141)
*Effects*: Equivalent to: return *end_*;
[🔗](#lib:operator==,take_view::sentinel)
`friend constexpr bool operator==(const CI<Const>& y, const sentinel& x);
template<bool OtherConst = !Const>
requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept sentinel_­for[iterator.concept.sentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr bool operator==(const CI<OtherConst>& y, const sentinel& x);
`
[4](#sentinel-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L6156)
*Effects*: Equivalent to:return y.count() == 0 || y.base() == x.*end_*;