43 KiB
[range.chunk]
25 Ranges library [ranges]
25.7 Range adaptors [range.adaptors]
25.7.29 Chunk view [range.chunk]
25.7.29.1 Overview [range.chunk.overview]
chunk_view takes a view and a number N and produces a range of views that are N-sized non-overlapping successive chunks of the elements of the original view, in order.
The last view in the range can have fewer than N elements.
The name views::chunk denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and N, the expression views::chunk(E, N) is expression-equivalent tochunk_view(E, N).
[Example 1: vector v = {1, 2, 3, 4, 5};
for (auto r : v | views::chunk(2)) { cout << '['; auto sep = ""; for (auto i : r) { cout << sep << i; sep = ", "; } cout << "] ";}// The above prints [1, 2] [3, 4] [5] â end example]
25.7.29.2 Class template chunk_view for input ranges [range.chunk.view.input]
namespace std::ranges {templateconstexpr I div-ceil(I num, I denom) { // exposition only I r = num / denom; if (num % denom)++r; return r; }template<view V>requires input_rangeclass chunk_view : public view_interface<chunk_view> { V base_; // exposition only range_difference_t n_; // exposition only range_difference_t remainder_ = 0; // exposition only**non-propagating-cache<iterator_t> current_; // exposition only// [range.chunk.outer.iter], class chunk_view::outer-iteratorclass outer-iterator; // exposition only// [range.chunk.inner.iter], class chunk_view::inner-iteratorclass inner-iterator; // exposition onlypublic:constexpr explicit chunk_view(V base, range_difference_t n); constexpr V base() const & requires copy_constructible { return base_; }constexpr V base() && { return std::move(base_); }constexpr outer-iterator begin(); constexpr default_sentinel_t end() const noexcept; constexpr auto size() requires sized_range; constexpr auto size() const requires sized_range; constexpr auto reserve_hint() requires approximately_sized_range; constexpr auto reserve_hint() const requires approximately_sized_range; }; template chunk_view(R&&, range_difference_t) -> chunk_view<views::all_t>;}
constexpr explicit chunk_view(V base, range_difference_t<V> n);
Preconditions: n > 0 is true.
Effects: Initializes base_ with std::move(base) andn_ with n.
constexpr outer-iterator begin();
Effects: Equivalent to:current_ = ranges::begin(base_);remainder_ = n_;return outer-iterator(*this);
constexpr default_sentinel_t end() const noexcept;
Returns: default_sentinel.
constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V>; constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>;
Effects: Equivalent to:return to-unsigned-like(div-ceil(ranges::distance(base_), n_));
constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")<V>; constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")<const V>;
Effects: Equivalent to:auto s = static_cast<range_difference_t<decltype((base_))>>(ranges::reserve_hint(base_));return to-unsigned-like(div-ceil(s, n_));
25.7.29.3 Class chunk_view::outer-iterator [range.chunk.outer.iter]
namespace std::ranges {template<view V>requires input_rangeclass chunk_view::outer-iterator { chunk_view* parent_; // exposition onlyconstexpr explicit outer-iterator(chunk_view& parent); // exposition onlypublic:using iterator_concept = input_iterator_tag; using difference_type = range_difference_t; // [range.chunk.outer.value], class chunk_view::outer-iterator::value_typestruct value_type; outer-iterator(outer-iterator&&) = default; outer-iterator& operator=(outer-iterator&&) = default; constexpr value_type operator*() const; constexpr outer-iterator& operator++(); constexpr void operator++(int); friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t); friend constexpr difference_type operator-(default_sentinel_t y, const outer-iterator& x)requires sized_sentinel_for<sentinel_t, iterator_t>; friend constexpr difference_type operator-(const outer-iterator& x, default_sentinel_t y)requires sized_sentinel_for<sentinel_t, iterator_t>; };}
constexpr explicit outer-iterator(chunk_view& parent);
Effects: Initializes parent_ with addressof(parent).
constexpr value_type operator*() const;
Preconditions: *this == default_sentinel is false.
Returns: value_type(**parent_*).
constexpr outer-iterator& operator++();
Preconditions: *this == default_sentinel is false.
Effects: Equivalent to:ranges::advance(**parent_*->current_, parent_->remainder_, ranges::end(parent_->base_));parent_->remainder_ = parent_->n_;return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this.
friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
Effects: Equivalent to:return *x.parent_->current_ == ranges::end(x.parent_->base_) && x.parent_->remainder_ != 0;
friend constexpr difference_type operator-(default_sentinel_t y, const outer-iterator& x) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<sentinel_t<V>, iterator_t<V>>;
Effects: Equivalent to:const auto dist = ranges::end(x.parent_->base_) - *x.parent_->current_;if (dist < x.parent_->remainder_) {return dist == 0 ? 0 : 1;}return div-ceil(dist - x.parent_->remainder_, x.parent_->n_) + 1;
friend constexpr difference_type operator-(const outer-iterator& x, default_sentinel_t y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<sentinel_t<V>, iterator_t<V>>;
Effects: Equivalent to: return -(y - x);
25.7.29.4 Class chunk_view::outer-iterator::value_type [range.chunk.outer.value]
namespace std::ranges {template<view V>requires input_rangestruct chunk_view::outer-iterator::value_type : view_interface<value_type> {private: chunk_view* parent_; // exposition onlyconstexpr explicit value_type(chunk_view& parent); // exposition onlypublic:constexpr inner-iterator begin() const noexcept; constexpr default_sentinel_t end() const noexcept; constexpr auto size() constrequires sized_sentinel_for<sentinel_t, iterator_t>; constexpr auto reserve_hint() const noexcept; };}
constexpr explicit value_type(chunk_view& parent);
Effects: Initializes parent_ with addressof(parent).
constexpr inner-iterator begin() const noexcept;
Returns: inner-iterator(**parent_*).
constexpr default_sentinel_t end() const noexcept;
Returns: default_sentinel.
constexpr auto size() const requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<sentinel_t<V>, iterator_t<V>>;
Effects: Equivalent to:return to-unsigned-like(ranges::min(parent_->remainder_, ranges::end(parent_->base_) - **parent_*->current_));
constexpr auto reserve_hint() const noexcept;
Effects: Equivalent to:return to-unsigned-like(parent_->remainder_);
25.7.29.5 Class chunk_view::inner-iterator [range.chunk.inner.iter]
namespace std::ranges {template<view V>requires input_rangeclass chunk_view::inner-iterator { chunk_view* parent_; // exposition onlyconstexpr explicit inner-iterator(chunk_view& parent) noexcept; // exposition onlypublic:using iterator_concept = input_iterator_tag; using difference_type = range_difference_t; using value_type = range_value_t; inner-iterator(inner-iterator&&) = default; inner-iterator& operator=(inner-iterator&&) = default; constexpr const iterator_t& base() const &; constexpr range_reference_t operator*() const; constexpr inner-iterator& operator++(); constexpr void operator++(int); friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t); friend constexpr difference_type operator-(default_sentinel_t y, const inner-iterator& x)requires sized_sentinel_for<sentinel_t, iterator_t>; friend constexpr difference_type operator-(const inner-iterator& x, default_sentinel_t y)requires sized_sentinel_for<sentinel_t, iterator_t>; friend constexpr range_rvalue_reference_t iter_move(const inner-iterator& i)noexcept(noexcept(ranges::iter_move(*i.parent_->current_))); friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y)noexcept(noexcept(ranges::iter_swap(*x.parent_->current_, *y.parent_->current_)))requires indirectly_swappable<iterator_t>; };}
constexpr explicit inner-iterator(chunk_view& parent) noexcept;
Effects: Initializes parent_ with addressof(parent).
constexpr const iterator_t<V>& base() const &;
Effects: Equivalent to: return **parent_*->current_;
constexpr range_reference_t<V> operator*() const;
Preconditions: *this == default_sentinel is false.
Effects: Equivalent to: return **parent_->current_;
constexpr inner-iterator& operator++();
Preconditions: *this == default_sentinel is false.
Effects: Equivalent to:++**parent_->current_;if (**parent_->current_ == ranges::end(parent_->base_))parent_->remainder_ = 0;else--parent_->remainder_;return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this.
friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
Returns: x.parent_->remainder_ == 0.
friend constexpr difference_type operator-(default_sentinel_t y, const inner-iterator& x) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<sentinel_t<V>, iterator_t<V>>;
Effects: Equivalent to:return ranges::min(x.parent_->remainder_, ranges::end(x.parent_->base_) - *x.parent_->current_);
friend constexpr difference_type operator-(const inner-iterator& x, default_sentinel_t y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<sentinel_t<V>, iterator_t<V>>;
Effects: Equivalent to: return -(y - x);
friend constexpr range_rvalue_reference_t<V> iter_move(const inner-iterator& i) noexcept(noexcept(ranges::iter_move(*i.parent_->current_)));
Effects: Equivalent to: return ranges::iter_move(*i.parent_->current_);
friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y) noexcept(noexcept(ranges::iter_swap(*x.parent_->current_, *y.parent_->current_))) requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_swappable [alg.req.ind.swap]")<iterator_t<V>>;
Effects: Equivalent to: ranges::iter_swap(*x.parent_->current_, *y.parent_->current_);
25.7.29.6 Class template chunk_view for forward ranges [range.chunk.view.fwd]
namespace std::ranges {template<view V>requires forward_rangeclass chunk_view : public view_interface<chunk_view> { V base_; // exposition only range_difference_t n_; // exposition only// [range.chunk.fwd.iter], class template chunk_view::iteratortemplate class iterator; // exposition onlypublic:constexpr explicit chunk_view(V base, range_difference_t n); constexpr V base() const & requires copy_constructible { return base_; }constexpr V base() && { return std::move(base_); }constexpr auto begin() requires () {return iterator(this, ranges::begin(base_)); }constexpr auto begin() const requires forward_range {return iterator(this, ranges::begin(base_)); }constexpr auto end() requires (
) {if constexpr (common_range && sized_range) {auto missing = (n_ - ranges::distance(base_) % n_) % n_; return iterator(this, ranges::end(base_), missing); } else if constexpr (common_range &&
) {return iterator(this, ranges::end(base_)); } else {return default_sentinel; }}constexpr auto end() const requires forward_range {if constexpr (common_range && sized_range) {auto missing = (n_ - ranges::distance(base_) % n_) % n_; return iterator(this, ranges::end(base_), missing); } else if constexpr (common_range &&
) {return iterator(this, ranges::end(base_)); } else {return default_sentinel; }}constexpr auto size() requires sized_range; constexpr auto size() const requires sized_range; constexpr auto reserve_hint() requires approximately_sized_range; constexpr auto reserve_hint() const requires approximately_sized_range; };}
constexpr explicit chunk_view(V base, range_difference_t<V> n);
Preconditions: n > 0 is true.
Effects: Initializes base_ with std::move(base) andn_ with n.
constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<V>; constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<const V>;
Effects: Equivalent to:return to-unsigned-like(div-ceil(ranges::distance(base_), n_));
constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")<V>; constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")<const V>;
Effects: Equivalent to:auto s = static_cast<range_difference_t<decltype((base_))>>(ranges::reserve_hint(base_));return to-unsigned-like(div-ceil(s, n_));
25.7.29.7 Class template chunk_view::iterator for forward ranges [range.chunk.fwd.iter]
namespace std::ranges {template<view V>requires forward_rangetemplateclass chunk_view::iterator {using Parent = maybe-const<Const, chunk_view>; // exposition onlyusing Base = maybe-const<Const, V>; // exposition only iterator_t<Base> current_ = iterator_t<Base>(); // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only range_difference_t<Base> n_ = 0; // exposition only range_difference_t<Base> missing_ = 0; // exposition onlyconstexpr iterator(Parent* parent, iterator_t<Base> current, // exposition only range_difference_t<Base> missing = 0); public:using iterator_category = input_iterator_tag; using iterator_concept = see below; using value_type = decltype(views::take(subrange(current_, end_), n_)); using difference_type = range_difference_t<Base>; iterator() = default; constexpr iterator(iterator i)requires Const && convertible_to<iterator_t, iterator_t<Base>>&& convertible_to<sentinel_t, sentinel_t<Base>>; constexpr iterator_t<Base> base() const; constexpr value_type operator*() const; constexpr iterator& operator++(); constexpr iterator operator++(int); constexpr iterator& operator--() requires bidirectional_range<Base>; constexpr iterator operator--(int) requires bidirectional_range<Base>; constexpr iterator& operator+=(difference_type x)requires random_access_range<Base>; constexpr iterator& operator-=(difference_type x)requires random_access_range<Base>; constexpr value_type operator[](difference_type n) constrequires random_access_range<Base>; friend constexpr bool operator==(const iterator& x, const iterator& y); friend constexpr bool operator==(const iterator& x, default_sentinel_t); friend constexpr bool operator<(const iterator& x, const iterator& y)requires random_access_range<Base>; friend constexpr bool operator>(const iterator& x, const iterator& y)requires random_access_range<Base>; friend constexpr bool operator<=(const iterator& x, const iterator& y)requires random_access_range<Base>; friend constexpr bool operator>=(const iterator& x, const iterator& y)requires random_access_range<Base>; friend constexpr auto operator<=>(const iterator& x, const iterator& y)requires random_access_range<Base> &&three_way_comparable<iterator_t<Base>>; friend constexpr iterator operator+(const iterator& i, difference_type n)requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, const iterator& i)requires random_access_range<Base>; friend constexpr iterator operator-(const iterator& i, difference_type n)requires random_access_range<Base>; friend constexpr difference_type operator-(const iterator& x, const iterator& y)requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>; friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x)requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>; friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y)requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>; };}
iterator::iterator_concept is defined as follows:
-
If Base models random_access_range, then iterator_concept denotes random_access_iterator_tag.
-
Otherwise, if Base models bidirectional_range, then iterator_concept denotes bidirectional_iterator_tag.
-
Otherwise, iterator_concept denotes forward_iterator_tag.
constexpr iterator(Parent* parent, iterator_t<Base> current, range_difference_t<Base> missing = 0);
Effects: Initializes current_ with current,end_ with ranges::end(parent->base_),n_ with parent->n_, andmissing_ with missing.
constexpr iterator(iterator<!Const> i) requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<iterator_t<V>, iterator_t<Base>> && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes current_ with std::move(i.current_),end_ with std::move(i.end_),n_ with i.n_, andmissing_ with i.missing_.
constexpr iterator_t<Base> base() const;
Returns: current_.
constexpr value_type operator*() const;
Preconditions: current_ != end_ is true.
Returns: views::take(subrange(current_, end_), n_).
constexpr iterator& operator++();
Preconditions: current_ != end_ is true.
Effects: Equivalent to:missing_ = ranges::advance(current_, n_, end_);return *this;
constexpr iterator operator++(int);
Effects: Equivalent to:auto tmp = *this;++*this;return tmp;
constexpr iterator& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<Base>;
Effects: Equivalent to:ranges::advance(current_, missing_ - n_);missing_ = 0;return *this;
constexpr iterator operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<Base>;
Effects: Equivalent to:auto tmp = *this;--*this;return tmp;
constexpr iterator& operator+=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<Base>;
Preconditions: If x is positive,ranges::distance(current_, end_) > n_ * (x - 1) is true.
[Note 1:
If x is negative, the Effects paragraph implies a precondition.
â end note]
Effects: Equivalent to:if (x > 0) { ranges::advance(current_, n_ * (x - 1)); missing_ = ranges::advance(current_, n_, end_);} else if (x < 0) { ranges::advance(current_, n_ * x + missing_); missing_ = 0;}return *this;
constexpr iterator& operator-=(difference_type x) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<Base>;
Effects: Equivalent to: return *this += -x;
constexpr value_type operator[](difference_type n) const requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<Base>;
Returns: *(*this + n).
friend constexpr bool operator==(const iterator& x, const iterator& y);
Returns: x.current_ == y.current_.
friend constexpr bool operator==(const iterator& x, default_sentinel_t);
Returns: x.current_ == x.end_.
friend constexpr bool operator<(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<Base>;
Returns: x.current_ < y.current_.
friend constexpr bool operator>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<Base>;
Effects: Equivalent to: return y < x;
friend constexpr bool operator<=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<Base>;
Effects: Equivalent to: return !(y < x);
friend constexpr bool operator>=(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<Base>;
Effects: Equivalent to: return !(x < y);
friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<Base> && [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_way_comparable [cmp.concept]")<iterator_t<Base>>;
Returns: x.current_ <=> y.current_.
friend constexpr iterator operator+(const iterator& i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<Base>; friend constexpr iterator operator+(difference_type n, const iterator& i) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<Base>;
Effects: Equivalent to:auto r = i; r += n;return r;
friend constexpr iterator operator-(const iterator& i, difference_type n) requires [random_access_range](range.refinements#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<Base>;
Effects: Equivalent to:auto r = i; r -= n;return r;
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<iterator_t<Base>, iterator_t<Base>>;
Returns: (x.current_ - y.current_ + x.missing_ - y.missing_) / x.n_.
friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<sentinel_t<Base>, iterator_t<Base>>;
Returns: div-ceil(x.end_ - x.current_, x.n_).
friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]")<sentinel_t<Base>, iterator_t<Base>>;
Effects: Equivalent to: return -(y - x);