yohhoyの日記

技術的メモをしていきたい日記

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

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

C++標準ライブラリのアップデートによりC++20時点よりシンプルに記述可能となり、またstd::stringを介さないため実行効率改善も見込める。

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

int main() {
  std::string_view s = "apple,banana,cinnamon";
  for (auto word : s | std::views::split(',')) {
    std::cout << std::quoted(std::string_view(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の日記

これらは、C++2b標準ライブラリのRangeライブラリ仕様変更とへの小さな機能追加により実現される。前者P2210R2は仕様欠陥扱いとされ、C++20に対しても遡及適用される。

  • P2210R2std::views::split仕様修正により、Rangeカテゴリが引き継がれる。これによりsplit分割後の要素=内部Rangeが、入力Rangeカテゴリを引き継いでContiguous Rangeとみなされる。
  • (PDF)P1989R2std::string_viewにRange版コンストラクタが追加される。これによりsplit分割後の内部Rangeから直接std::string_viewへと変換可能となる。
    • 2022-10-13追記:2022年7月会合*1にてP2499R0が採択され、Range版std::string_viewコンストラクタがexplicit指定された。

提案文書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

関連URL