一个C++20下的string split实现

众所周知,C++一直没有一个官方提供的string split用于分割字符串,在过去(C++20之前)我们可能需要使用std::regex、std::string::find系列方法、甚至是继承自C的strtok函数来自行封装一个split,非常繁琐与不便。
然而,这一切都在C++20中发生了变化。C++20引入了范围库ranges,其中提供的两个范围适配器std::split、std::lazy_split可以使我们以一种更为优雅的形式实现split。x

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <concept>
#include <ranges>
#include <algorithm>
#include <format>
#include <iostream>

#define stdr std::ranges
#define stdrv std::ranges::views

template<template<typename> typename Container = std::vector, typename Arg = std::string_view>
auto Split(std::string_view str, std::string_view delimiter)
{
Container<Arg> myCont;
auto temp = str
| stdrv::split(delimiter)
| stdrv::transform([](auto&& r)
{
return Arg(std::addressof(*r.begin()), stdr::distance(r));
});
auto iter = std::inserter(myCont, myCont.end());
stdr::for_each(temp, [&](auto&& x) { iter = {x.begin(), x.end()}; });
return myCont;
}
int main()
{
std::string str = "Hello233C++20233and233New233Spilt";
std::string delimiter = "233";
auto&& strCont = Split<std::list, std::string>(str, delimiter);
stdr::for_each(strCont, [](auto&& x) { std::cout << std::format("{} ", x); });
}
//output: Hello C++20 and New Spilt

PS:std::split与std::lazy_split存在细微区别,在此不作详细说明,感兴趣可以参考:
https://stackoverflow.com/questions/68067612/what-is-the-difference-between-the-split-view-and-the-lazy-split-view-in-c
PS2:C++20没有提供关键的ranges::to函数,导致demo中还需要额外封装并手写for_each来写入数据,等到C++23实装了该函数,split的实现会比现在简洁优雅的多,真正做到方便泛用、无需封装:

1
2
3
auto&& strCont = str
| stdrv::lazy_split(delimiter)
| stdr ::to<std::vector<std::string>>;

原文链接: https://zhuanlan.zhihu.com/p/474447289