Using std::views::split in C++ with Delimiters
In modern C++, std::views::split is a range adaptor that
divides an underlying view into a sequence of subranges using a
specified pattern or delimiter. This article explains how
std::views::split detects delimiters, handles lazy
evaluation, produces subranges without memory allocation, and processes
both single-element and multi-element patterns.
How std::views::split
Works
Introduced in C++20 and refined in C++23,
std::views::split operates as a range adaptor closure
object found in the <ranges> header. It takes two
primary components: an underlying range to be split and a delimiter
pattern.
The delimiter can be a single element (such as a character
' ') or a forward range (such as a string literal
" - " or another subview). When applied,
std::views::split creates a lazy view over the original
data. Instead of allocating memory or generating a container of tokens
immediately, it computes token boundaries on demand as iterators
advance.
Dividing Views by Pattern
When traversing the input view, std::views::split
searches for matches against the delimiter pattern:
- Pattern Matching: It scans the source sequence
using an algorithm conceptually equivalent to
std::search. If the delimiter is a sequence of multiple elements,std::views::splitensures the exact contiguous sequence matches before breaking the range. - Subrange Production: Each element yielded by
iterating through the split view is itself a subrange
(
std::ranges::subrange). This subrange references the elements in the original view that sit between two matching delimiters (or between the boundary and a delimiter). - Delimiter Skipping: The matching delimiter elements are omitted from the yielded subranges. Once a match is found, the start of the next subrange is positioned immediately after the delimiter.
Code Example
The following example demonstrates splitting a string using a multi-character delimiter pattern:
#include <iostream>
#include <ranges>
#include <string_view>
int main() {
std::string_view text = "Apple-->Banana-->Orange-->Grape";
std::string_view delimiter = "-->";
// Split the view using a multi-character pattern
auto tokens = text | std::views::split(delimiter);
for (auto token : tokens) {
// Construct a string_view from the subrange to print cleanly
std::cout << std::string_view(token) << '\n';
}
return 0;
}Output:
Apple
Banana
Orange
Grape
Key Behaviors and Nuances
- Empty Subranges: If two delimiters appear
consecutively, or if the source range begins or ends with a delimiter,
std::views::splitproduces empty subranges at those locations. - Zero Allocations: Because it produces views rather
than instantiating copies,
std::views::splitcauses zero heap allocations. It operates safely over non-owning views such asstd::string_vieworstd::span. - C++20 vs. C++23 Evolution: In C++20,
std::views::splitproduced inner subranges with an iterator type that could not easily be converted into standard standard string views. C++23 redesignedstd::views::splitso that the inner ranges modelstd::ranges::forward_rangewhen possible, moving the original C++20 forward-range-agnostic implementation tostd::views::lazy_split.