26 Ranges library [ranges]

26.7 Range adaptors [range.adaptors]

26.7.29 Chunk by view [range.chunk.by]

26.7.29.1 Overview [range.chunk.by.overview]

chunk_­by_­view takes a view and a predicate, and splits the view into subranges between each pair of adjacent elements for which the predicate returns false.
The name views​::​chunk_­by denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and F, the expression views​::​chunk_­by(E, F) is expression-equivalent to chunk_­by_­view(E, F).
[Example 1: vector v = {1, 2, 2, 3, 0, 4, 5, 2}; for (auto r : v | views::chunk_by(ranges::less_equal{})) { cout << '['; auto sep = ""; for (auto i : r) { cout << sep << i; sep = ", "; } cout << "] "; } // The above prints [1, 2, 2, 3] [0, 4, 5] [2] — end example]

26.7.29.2 Class template chunk_­by_­view [range.chunk.by.view]

namespace std::ranges { template<forward_­range V, indirect_­binary_­predicate<iterator_t<V>, iterator_t<V>> Pred> requires view<V> && is_object_v<Pred> class chunk_by_view : public view_interface<chunk_by_view<V, Pred>> { V base_ = V(); // exposition only movable-box<Pred> pred_ = Pred(); // exposition only // [range.chunk.by.iter], class chunk_­by_­view​::​iterator class iterator; // exposition only public: chunk_by_view() requires default_­initializable<V> && default_­initializable<Pred> = default; constexpr explicit chunk_by_view(V base, Pred pred); constexpr V base() const & requires copy_­constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr const Pred& pred() const; constexpr iterator begin(); constexpr auto end(); constexpr iterator_t<V> find-next(iterator_t<V>); // exposition only constexpr iterator_t<V> find-prev(iterator_t<V>) // exposition only requires bidirectional_­range<V>; }; template<class R, class Pred> chunk_by_view(R&&, Pred) -> chunk_by_view<views::all_t<R>, Pred>; }
constexpr explicit chunk_by_view(V base, Pred pred);
Effects: Initializes base_­ with std​::​move(base) and pred_­ with std​::​move(pred).
constexpr const Pred& pred() const;
Effects: Equivalent to: return *pred_­;
constexpr iterator begin();
Preconditions: pred_­.has_­value() is true.
Returns: iterator(*this, ranges​::​begin(base_­), find-next(ranges​::​begin(base_­))).
Remarks: In order to provide the amortized constant-time complexity required by the range concept, this function caches the result within the chunk_­by_­view for use on subsequent calls.
constexpr auto end();
Effects: Equivalent to: if constexpr (common_­range<V>) { return iterator(*this, ranges::end(base_), ranges::end(base_)); } else { return default_sentinel; }
constexpr iterator_t<V> find-next(iterator_t<V> current);
Preconditions: pred_­.has_­value() is true.
Returns: ranges::next(ranges::adjacent_find(current, ranges::end(base_), not_fn(ref(*pred_))), 1, ranges::end(base_))
constexpr iterator_t<V> find-prev(iterator_t<V> current) requires bidirectional_­range<V>;
Preconditions:
  • current is not equal to ranges​::​begin(base_­).
  • pred_­.has_­value() is true.
Returns: An iterator i in the range [ranges​::​begin(base_­), current) such that:
  • ranges​::​adjacent_­find(i, current, not_­fn(ref(*pred_­))) is equal to current; and
  • if i is not equal to ranges​::​begin(base_­), then bool(invoke(*pred_­, *ranges​::​prev(i), *i)) is false.

26.7.29.3 Class chunk_­by_­view​::​iterator [range.chunk.by.iter]

namespace std::ranges { template<forward_­range V, indirect_­binary_­predicate<iterator_t<V>, iterator_t<V>> Pred> requires view<V> && is_object_v<Pred> class chunk_by_view<V, Pred>::iterator { chunk_by_view* parent_ = nullptr; // exposition only iterator_t<V> current_ = iterator_t<V>(); // exposition only iterator_t<V> next_ = iterator_t<V>(); // exposition only constexpr iterator(chunk_by_view& parent, iterator_t<V> current, // exposition only iterator_t<V> next); public: using value_type = subrange<iterator_t<V>>; using difference_type = range_difference_t<V>; using iterator_category = input_iterator_tag; using iterator_concept = see below; iterator() = default; constexpr value_type operator*() const; constexpr iterator& operator++(); constexpr iterator operator++(int); constexpr iterator& operator--() requires bidirectional_­range<V>; constexpr iterator operator--(int) requires bidirectional_­range<V>; friend constexpr bool operator==(const iterator& x, const iterator& y); friend constexpr bool operator==(const iterator& x, default_sentinel_t); }; }
iterator​::​iterator_­concept is defined as follows:
  • If V models bidirectional_­range, then iterator_­concept denotes bidirectional_­iterator_­tag.
  • Otherwise, iterator_­concept denotes forward_­iterator_­tag.
constexpr iterator(chunk_by_view& parent, iterator_t<V> current, iterator_t<V> next);
Effects: Initializes parent_­ with addressof(parent), current_­ with current, and next_­ with next.
constexpr value_type operator*() const;
Preconditions: current_­ is not equal to next_­.
Returns: subrange(current_­, next_­).
constexpr iterator& operator++();
Preconditions: current_­ is not equal to next_­.
Effects: Equivalent to: current_ = next_; next_ = parent_->find-next(current_); return *this;
constexpr iterator operator++(int);
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires bidirectional_­range<V>;
Effects: Equivalent to: next_ = current_; current_ = parent_->find-prev(next_); return *this;
constexpr iterator operator--(int) requires bidirectional_­range<V>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
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.next_­.