24 Ranges library [ranges]

24.7 Range adaptors [range.adaptors]

24.7.14 Split view [range.split]

24.7.14.1 Overview [range.split.overview]

split_­view takes a view and a delimiter, and splits the view into subranges on the delimiter.
The delimiter can be a single element or a view of elements.
The name views​::​split denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and F, the expression views​::​split(E, F) is expression-equivalent to split_­view(E, F).
[Example 1: string str{"the quick brown fox"}; for (string_view word : split(str, ' ')) { cout << word << '*'; } // The above prints: the*quick*brown*fox* — end example]

24.7.14.2 Class template split_­view [range.split.view]

namespace std::ranges { template<forward_­range V, forward_­range Pattern> requires view<V> && view<Pattern> && indirectly_­comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> class split_view : public view_interface<split_view<V, Pattern>> { private: V base_ = V(); // exposition only Pattern pattern_ = Pattern(); // exposition only // [range.split.iterator], class split_­view​::​iterator struct iterator; // exposition only // [range.split.sentinel], class split_­view​::​sentinel struct sentinel; // exposition only public: split_view() requires default_­initializable<V> && default_­initializable<Pattern> = default; constexpr split_view(V base, Pattern pattern); template<forward_­range R> requires constructible_­from<V, views::all_t<R>> && constructible_­from<Pattern, single_view<range_value_t<R>>> constexpr split_view(R&& r, range_value_t<R> e); constexpr V base() const& requires copy_­constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr iterator begin(); constexpr auto end() { if constexpr (common_­range<V>) { return iterator{*this, ranges::end(base_), {}}; } else { return sentinel{*this}; } } constexpr subrange<iterator_t<V>> find-next(iterator_t<V>); // exposition only }; template<class R, class P> split_view(R&&, P&&) -> split_view<views::all_t<R>, views::all_t<P>>; template<forward_­range R> split_view(R&&, range_value_t<R>) -> split_view<views::all_t<R>, single_view<range_value_t<R>>>; }
constexpr split_view(V base, Pattern pattern);
Effects: Initializes base_­ with std​::​move(base), and pattern_­ with std​::​move(pattern).
template<forward_­range R> requires constructible_­from<V, views::all_t<R>> && constructible_­from<Pattern, single_view<range_value_t<R>>> constexpr split_view(R&& r, range_value_t<R> e);
Effects: Initializes base_­ with views​::​all(std​::​forward<R>(r)), and pattern_­ with views​::​
single(std​::​move(e))
.
constexpr iterator begin();
Returns: {*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 split_­view for use on subsequent calls.
constexpr subrange<iterator_t<V>> find-next(iterator_t<V> it); // exposition only
Effects: Equivalent to: auto [b, e] = ranges::search(subrange(it, ranges::end(base_)), pattern_); if (b != ranges::end(base_) && ranges::empty(pattern_)) { ++b; ++e; } return {b, e};

24.7.14.3 Class split_­view​::​iterator [range.split.iterator]

namespace std::ranges { template<forward_­range V, forward_­range Pattern> requires view<V> && view<Pattern> && indirectly_­comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> class split_view<V, Pattern>::iterator { private: split_view* parent_ = nullptr; // exposition only iterator_t<V> cur_ = iterator_t<V>(); // exposition only subrange<iterator_t<V>> next_ = subrange<iterator_t<V>>(); // exposition only bool trailing_empty_ = false; // exposition only public: using iterator_concept = forward_iterator_tag; using iterator_category = input_iterator_tag; using value_type = subrange<iterator_t<V>>; using difference_type = range_difference_t<V>; iterator() = default; constexpr iterator(split_view& parent, iterator_t<V> current, subrange<iterator_t<V>> next); constexpr iterator_t<V> base() const; constexpr value_type operator*() const; constexpr iterator& operator++(); constexpr iterator operator++(int); friend constexpr bool operator==(const iterator& x, const iterator& y); }; }
constexpr iterator(split_view& parent, iterator_t<V> current, subrange<iterator_t<V>> next);
Effects: Initializes parent_­ with addressof(parent), cur_­ with std​::​move(current), and next_­ with std​::​move(next).
constexpr iterator_t<V> base() const;
Effects: Equivalent to return cur_­;
constexpr value_type operator*() const;
Effects: Equivalent to return {cur_­, next_­.begin()};
constexpr iterator& operator++();
Effects: Equivalent to: cur_ = next_.begin(); if (cur_ != ranges::end(parent_->base_)) { cur_ = next_.end(); if (cur_ == ranges::end(parent_->base_)) { trailing_empty_ = true; next_ = {cur_, cur_}; } else { next_ = parent_->find-next(cur_); } } else { trailing_empty_ = false; } return *this;
constexpr iterator operator++(int);
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
friend constexpr bool operator==(const iterator& x, const iterator& y);
Effects: Equivalent to: return x.cur_ == y.cur_ && x.trailing_empty_ == y.trailing_empty_;

24.7.14.4 Class split_­view​::​sentinel [range.split.sentinel]

namespace std::ranges { template<forward_­range V, forward_­range Pattern> requires view<V> && view<Pattern> && indirectly_­comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> struct split_view<V, Pattern>::sentinel { private: sentinel_t<V> end_ = sentinel_t<V>(); // exposition only public: sentinel() = default; constexpr explicit sentinel(split_view& parent); friend constexpr bool operator==(const iterator& x, const sentinel& y); }; }
constexpr explicit sentinel(split_view& parent);
Effects: Initializes end_­ with ranges​::​end(parent.base_­).
friend constexpr bool operator==(const iterator& x, const sentinel& y);
Effects: Equivalent to: return x.cur_­ == y.end_­ && !x.trailing_­empty_­;