[range.split] # 25 Ranges library [[ranges]](./#ranges) ## 25.7 Range adaptors [[range.adaptors]](range.adaptors#range.split) ### 25.7.17 Split view [range.split] #### [25.7.17.1](#overview) Overview [[range.split.overview]](range.split.overview) [1](#overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8383) split_view takes a view and a delimiter, and splits the view into subranges on the delimiter[.](#overview-1.sentence-1) The delimiter can be a single element or a view of elements[.](#overview-1.sentence-2) [2](#overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8388) The name views​::​split denotes a range adaptor object ([[range.adaptor.object]](range.adaptor.object "25.7.2 Range adaptor objects"))[.](#overview-2.sentence-1) Given subexpressions E and F, the expression views​::​split(E, F) is expression-equivalent tosplit_view(E, F)[.](#overview-2.sentence-2) [3](#overview-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8395) [*Example [1](#overview-example-1)*: string str{"the quick brown fox"};for (auto word : views::split(str, ' ')) { cout << string_view(word) << '*';}// The above prints the*quick*brown*fox* — *end example*] #### [25.7.17.2](#view) Class template split_view [[range.split.view]](range.split.view) [🔗](#lib:split_view) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [view](range.view#concept:view "25.4.5 Views [range.view]") &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]"), iterator_t, ranges::equal_to>class split_view : public view_interface> {private: V *base_* = V(); // *exposition only* Pattern *pattern_* = Pattern(); // *exposition only*// [[range.split.iterator]](#iterator "25.7.17.3 Class split_­view​::​iterator"), class split_view​::​*iterator*struct *iterator*; // *exposition only*// [[range.split.sentinel]](#sentinel "25.7.17.4 Class split_­view​::​sentinel"), class split_view​::​*sentinel*struct *sentinel*; // *exposition only*public: split_view()requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_­initializable [concept.default.init]") = default; constexpr explicit split_view(V base, Pattern pattern); template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") R>requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")> &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")>>constexpr explicit split_view(R&& r, range_value_t e); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]") { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr *iterator* begin(); constexpr auto end() {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")) {return *iterator*{*this, ranges::end(*base_*), {}}; } else {return *sentinel*{*this}; }}constexpr subrange> *find-next*(iterator_t); // *exposition only*}; template split_view(R&&, P&&) -> split_view, views::all_t

>; template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") R> split_view(R&&, range_value_t)-> split_view, single_view>>;} [🔗](#lib:split_view,constructor) `constexpr explicit split_view(V base, Pattern pattern); ` [1](#view-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8466) *Effects*: Initializes *base_* with std​::​move(base), and*pattern_* with std​::​move(pattern)[.](#view-1.sentence-1) [🔗](#lib:split_view,constructor_) `template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") R> requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")> && [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")>> constexpr explicit split_view(R&& r, range_value_t e); ` [2](#view-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8481) *Effects*: Initializes *base_* with views​::​all(std​::​forward(r)), and*pattern_* with views​::​single(std​::​move(e))[.](#view-2.sentence-1) [🔗](#lib:begin,split_view) `constexpr iterator begin(); ` [3](#view-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8493) *Returns*: {*this, ranges​::​begin(*base_*), *find-next*(ranges​::​begin(*base_*))}[.](#view-3.sentence-1) [4](#view-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8497) *Remarks*: In order to provide the amortized constant time complexity required by the [range](range.range#concept:range "25.4.2 Ranges [range.range]") concept, this function caches the result within the split_view for use on subsequent calls[.](#view-4.sentence-1) [🔗](#lib:find-next,split_view) `constexpr subrange> find-next(iterator_t it); ` [5](#view-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8511) *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}; #### [25.7.17.3](#iterator) Class split_view​::​*iterator* [[range.split.iterator]](range.split.iterator) [🔗](#lib:split_view::iterator) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [view](range.view#concept:view "25.4.5 Views [range.view]") &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]"), iterator_t, ranges::equal_to>class split_view::*iterator* {private: split_view* *parent_* = nullptr; // *exposition only* iterator_t *cur_* = iterator_t(); // *exposition only* subrange> *next_* = subrange>(); // *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>; using difference_type = range_difference_t; *iterator*() = default; constexpr *iterator*(split_view& parent, iterator_t current, subrange> next); constexpr iterator_t base() const; constexpr value_type operator*() const; constexpr *iterator*& operator++(); constexpr *iterator* operator++(int); friend constexpr bool operator==(const *iterator*& x, const *iterator*& y); };} [🔗](#lib:split_view::iterator,constructor) `constexpr iterator(split_view& parent, iterator_t current, subrange> next); ` [1](#iterator-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8565) *Effects*: Initializes *parent_* with addressof(parent),*cur_* with std​::​move(current), and*next_* with std​::​move(next)[.](#iterator-1.sentence-1) [🔗](#lib:base,split_view::iterator) `constexpr iterator_t base() const; ` [2](#iterator-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8578) *Effects*: Equivalent to: return *cur_*; [🔗](#lib:operator*,split_view::iterator) `constexpr value_type operator*() const; ` [3](#iterator-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8589) *Effects*: Equivalent to: return {*cur_*, *next_*.begin()}; [🔗](#lib:operator++,split_view::iterator) `constexpr iterator& operator++(); ` [4](#iterator-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8600) *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; [🔗](#lib:operator++,split_view::iterator_) `constexpr iterator operator++(int); ` [5](#iterator-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8626) *Effects*: Equivalent to:auto tmp = *this;++*this;return tmp; [🔗](#lib:operator==,split_view::iterator) `friend constexpr bool operator==(const iterator& x, const iterator& y); ` [6](#iterator-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8642) *Effects*: Equivalent to:return x.*cur_* == y.*cur_* && x.*trailing_empty_* == y.*trailing_empty_*; #### [25.7.17.4](#sentinel) Class split_view​::​*sentinel* [[range.split.sentinel]](range.split.sentinel) [🔗](#lib:split_view::sentinel) namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]") && [view](range.view#concept:view "25.4.5 Views [range.view]") &&[indirectly_comparable](alg.req.ind.cmp#concept:indirectly_comparable "24.3.7.5 Concept indirectly_­comparable [alg.req.ind.cmp]"), iterator_t, ranges::equal_to>struct split_view::*sentinel* {private: sentinel_t *end_* = sentinel_t(); // *exposition only*public:*sentinel*() = default; constexpr explicit *sentinel*(split_view& parent); friend constexpr bool operator==(const *iterator*& x, const *sentinel*& y); };} [🔗](#lib:split_view::sentinel,constructor) `constexpr explicit sentinel(split_view& parent); ` [1](#sentinel-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8677) *Effects*: Initializes *end_* with ranges​::​end(parent.*base_*)[.](#sentinel-1.sentence-1) [🔗](#lib:operator==,split_view::sentinel) `friend constexpr bool operator==(const iterator& x, const sentinel& y); ` [2](#sentinel-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L8688) *Effects*: Equivalent to: return x.*cur_* == y.*end_* && !x.*trailing_empty_*;