std::views::splitで文字列分割 @ C++23

C++2b(C++23) Rangesライブラリstd::views::splitstd::string_viewを利用した文字列分割処理。


// C++2b(C++23)
#include <iomanip>
#include <iostream>
#include <string_view>
#include <ranges>

int main() {
  std::string_view s = "apple,banana,cinnamon";
  for (std::string_view word : s | std::views::split(',')) {
    std::cout << std::quoted(word) << "\n";
// "apple"
// "banana"
// "cinnamon"

split2str関数は「char範囲を区切り文字delimで分割しstd::stringのViewへ変換するレンジアダプタ(range adaptor)」を返す。

// C++20(一部抜粋)
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()};

std::string_view s = "apple,banana,cinnamon";
for (const auto& word : s | split2str(',')) {
  std::cout << std::quoted(word) << "\n";
std::views::splitで文字列分割 - yohhoyの日記


  • P2210R2std::views::split仕様修正により、Rangeカテゴリが引き継がれる。これによりsplit分割後の要素=内部Rangeが、入力Rangeカテゴリを引き継いでContiguous Rangeとみなされる。
  • (PDF)P1989R2std::string_viewにRange版コンストラクタが追加される。これによりsplit分割後の内部Rangeから直接std::string_viewへと変換可能となる。

提案文書P2210R2 §4.Proposalより一部引用(下線部は強調)。

Introduce a new range adapter under the name views::split / ranges::split_view with the following design:

  • a. It can only support splitting forward-or-better ranges.
  • b. Splitting a V will yield subrange<iterator_t<V>>s, ensuring that the adapted range's category is preserved. Splitting a bidirectional range gives out bidirectional subranges. Spltiting a contiguous range gives out contiguous subranges.
  • c. views::split will not be const-iterable.

This could certainly break some C++20 code. But I would argue that views::split is so unergonomic for its most common intended use-case that the benefit of making it actually usable for that case far outweighs the cost of potentially breaking some code (which itself is likely to be small given both the usability issues and lack of implementations thus far).

P2210R2 Superior String Splitting