13 KiB
[range.take]
25 Ranges library [ranges]
25.7 Range adaptors [range.adaptors]
25.7.10 Take view [range.take]
25.7.10.1 Overview [range.take.overview]
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.
The name views::take denotes a range adaptor object ([range.adaptor.object]).
Let E and F be expressions, let T be remove_cvref_t<decltype((E))>, and let D be range_difference_t<decltype((E))>.
If decltype((F)) does not modelconvertible_to,views::take(E, F) is ill-formed.
Otherwise, the expression views::take(E, F) is expression-equivalent to:
-
If T is a specialization of empty_view ([range.empty.view]), then ((void)F, decay-copy(E)), except that the evaluations of E and F are indeterminately sequenced.
-
Otherwise, if T modelsrandom_access_range and sized_range and is a specialization ofspan ([views.span]),basic_string_view ([string.view]), orsubrange ([range.subrange]), thenU(ranges::begin(E), ranges::begin(E) + std::min(ranges::distance(E), F)), except that E is evaluated only once, where U is a type determined as follows:
if T is a specialization of span, then U is span<typename T::element_type>;
otherwise, if T is a specialization of basic_string_view, then U is T;
otherwise, T is a specialization of subrange, andU is subrange<iterator_t>;
-
otherwise, if T is a specialization of iota_view ([range.iota.view]) that models random_access_range and sized_range, theniota_view(ranges::begin(E),(ranges::begin(E) + std::min(ranges::distance(E), F))), except that E is evaluated only once.
-
Otherwise, if T is a specialization of repeat_view ([range.repeat.view]):
if T models sized_range, thenviews::repeat(*E.value_, std::min(ranges::distance(E), F)) except that E is evaluated only once;
otherwise, views::repeat(*E.value_, static_cast(F)).
[Example 1: vector 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 Class template take_view [range.take.view]
namespace std::ranges {template<view V>class take_view : public view_interface<take_view> {private: V base_ = V(); // exposition only range_difference_t count_ = 0; // exposition only// [range.take.sentinel], class template take_view::sentineltemplate class sentinel; // exposition onlypublic: take_view() requires default_initializable = default; constexpr explicit take_view(V base, range_difference_t count); constexpr V base() const & requires copy_constructible { return base_; }constexpr V base() && { return std::move(base_); }constexpr auto begin() requires () {if constexpr (sized_range) {if constexpr (random_access_range) {return ranges::begin(base_); } else {auto sz = range_difference_t(size()); return counted_iterator(ranges::begin(base_), sz); }} else if constexpr (sized_sentinel_for<sentinel_t, iterator_t>) {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 {if constexpr (sized_range) {if constexpr (random_access_range) {return ranges::begin(base_); } else {auto sz = range_difference_t(size()); return counted_iterator(ranges::begin(base_), sz); }} else if constexpr (sized_sentinel_for<sentinel_t, iterator_t>) {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 (
) {if constexpr (sized_range) {if constexpr (random_access_range)return ranges::begin(base_) + range_difference_t(size()); elsereturn default_sentinel; } else if constexpr (sized_sentinel_for<sentinel_t, iterator_t>) {return default_sentinel; } else {return sentinel{ranges::end(base_)}; }}constexpr auto end() const requires range {if constexpr (sized_range) {if constexpr (random_access_range)return ranges::begin(base_) + range_difference_t(size()); elsereturn default_sentinel; } else if constexpr (sized_sentinel_for<sentinel_t, iterator_t>) {return default_sentinel; } else {return sentinel{ranges::end(base_)}; }}constexpr auto size() requires sized_range {auto n = ranges::size(base_); return ranges::min(n, static_cast<decltype(n)>(count_)); }constexpr auto size() const requires sized_range {auto n = ranges::size(base_); return ranges::min(n, static_cast<decltype(n)>(count_)); }constexpr auto reserve_hint() {if constexpr (approximately_sized_range) {auto n = static_cast<range_difference_t>(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) {auto n = static_cast<range_difference_t>(ranges::reserve_hint(base_)); return to-unsigned-like(ranges::min(n, count_)); }return to-unsigned-like(count_); }}; template take_view(R&&, range_difference_t)-> take_view<views::all_t>;}
constexpr explicit take_view(V base, range_difference_t<V> count);
Preconditions: count >= 0 is true.
Effects: Initializes base_ with std::move(base) andcount_ with count.
25.7.10.3 Class template take_view::sentinel [range.take.sentinel]
namespace std::ranges {template<view V>templateclass take_view::sentinel {private:using Base = maybe-const<Const, V>; // exposition onlytemplateusing CI = counted_iterator<iterator_t<maybe-const<OtherConst, V>>>; // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition onlypublic:sentinel() = default; constexpr explicit sentinel(sentinel_t<Base> end); constexpr sentinel(sentinel s)requires Const && convertible_to<sentinel_t, sentinel_t<Base>>; constexpr sentinel_t<Base> base() const; friend constexpr bool operator==(const CI& y, const sentinel& x); templaterequires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>friend constexpr bool operator==(const CI& y, const sentinel& x); };}
constexpr explicit sentinel(sentinel_t<Base> end);
Effects: Initializes end_ with end.
constexpr sentinel(sentinel<!Const> s) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes end_ with std::move(s.end_).
constexpr sentinel_t<Base> base() const;
Effects: Equivalent to: return end_;
`friend constexpr bool operator==(const CI& y, const sentinel& x);
template requires sentinel_for<sentinel_t, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const CI& y, const sentinel& x); `
Effects: Equivalent to:return y.count() == 0 || y.base() == x.end_;