C++2a(C++20) Rangesライブラリstd::views::split
を利用した文字列分割処理。*1
2021-06-24追記:次期C++2b(C++23)標準ライブラリではよりシンプルな実装が可能となる。
split2str
関数は「char
範囲を区切り文字delim
で分割しstd::string
のViewへ変換するレンジアダプタ(range adaptor)」を返す。
// C++2a(C++20) #include <iomanip> #include <iostream> #include <string> #include <string_view> #include <ranges> auto split2str(char delim) { return std::views::split(std::views::single(delim)) | std::views::transform([](auto v) { auto cv = v | std::views::common; return std::string{cv.begin(), cv.end()}; }); } int main() { std::string_view s = "apple,banana,cinnamon"; for (const auto& word : s | split2str(',')) { std::cout << std::quoted(word) << "\n"; } } // "apple" // "banana" // "cinnamon"
ノート:std::views::split
は区切り要素(char
)ではなく “区切りパターン(range)” を引数にとるため、std::views::single(delim)
のように単一要素レンジを明示する必要がある雰囲気。C++2a Rangesライブラリは処理系任せの部分が大きく、トラブル時の振る舞いを説明しづらい。単に理解不足かorzsplit
に左辺値delim
を指定すると意図通りに動作せず、キャストによりchar
型右辺値を与えるとなぜか動く。
- 2021-06-23追記:GCC HEAD 12.0.0 20210621(experimental)で再確認したところ、単に
std::views::split(delim) | ...
と記述しても期待通りに動作した。
C++2a DIS(N4861) 24.7/p1, 24.7.1/p1より引用。
This subclause defines range adaptors, which are utilities that transform a
range
into aview
with custom behaviors. These adaptors can be chained to create pipelines of range transformations that evaluate lazily as the resulting view is iterated.
A range adaptor closure object is a unary function object that accepts a
viewable_range
argument and returns aview
. For a range adaptor closure objectC
and an expressionR
such thatdecltype((R))
modelsviewable_range
, the following expressions are equivalent and yield a view:C(R) R | CGiven an additional range adaptor closure object
D
, the expressionC | D
is well-formed and produces another range adaptor closure object such that the following two expressions are equivalent:R | C | D R | (C | D)
関連URL