yohhoyの日記

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

std::views::splitとstd::views::lazy_split

C++20標準ライブラリ提供レンジアダプタstd::views::splitstd::views::lazy_splitの比較。*1

まとめ:

  • 入力レンジを区切りパターン(単一要素またはレンジ)を用いて分割し、「部分レンジ(subrange)のレンジ」へと変換するレンジアダプタ(range adaptor)。*2
  • 大半のユースケースsplitを用いればよい。
    • 使い勝手を重視:部分レンジ(std::ranges::subrange)への分割処理を遅延評価する。*3
    • 入力レンジの特性が出力レンジへと引き継がれる。(例:文字列の分割結果を文字列として扱える)
  • 特殊ケースに対してのみlazy_splitを検討する。
    • 一般性を重視:最大限に怠惰(lazy)な分割アルゴリズムを用い、遅延生成される部分レンジを遅延生成する。
    • 入力がinput_rangeの場合や、出力レンジを Const-iterable としたい場合など。

入力レンジとパターンの制約

分割対象Vと区切りパターンPatternに対するテンプレートパラメータ制約は次の通り。

  • split: Vはforward_rangeを満たすview。
  • lazy_split: Vはforward_rangeを満たすview、またはVはinput_rangeを満たすviewかつPatternが確定サイズ1要素以下のレンジ。*4
  • 共通: Patternはforward_rangeを満たすview。

入出力レンジコンセプト

レンジアダプタの適用対象Vが満たすコンセプトに対して、適用結果の外部(Outer)レンジ/内部(Inner)レンジが満たすコンセプトは下表の通り。*5

入力\出力 split
Outer
split
Inner
lazy_split
Outer
lazy_split
Inner
input *6 (N/A) (N/A) input input
forward forward forward forward forward
bidirectional forward bidirectional forward forward
random_access forward random_access forward forward
contiguous forward contiguous forward forward

Const-iterable性

レンジアダプタ適用後レンジの const-iterable 性(→id:yohhoy:20210701)は次の通り。

  • split: 適用結果は const-iterable ではない。
  • lazy_split: 対象Vがforward_rangeを満たすならば、適用結果は const-iterable となる。input_rangeの場合は 非const-iterable。

関連URL

*1:ISO C++20発行後に P2210R2 が Defect Report として遡及適用されている。

*2:C++標準レンジアダプタはいずれも遅延評価を行う。実際にレンジ要素へのアクセスが必要になるまで、レンジアダプタによる各種アルゴリズムは実行されない。

*3:https://wandbox.org/permlink/1ebAmAsmrqLrLFQ8

*4:split, lazy_split ともに、確定サイズ0要素の区切りパターン(例:std:::ranges::empty<T>)によるレンジ分割にも対応する。結果として、内部(Inner)レンジ==対象レンジ要素を1個づつ取り出した単一要素レンジが得られる。

*5:表中の input は std::ranges::input_range コンセプトの略記。他 forward, bidirectional, random_access, contiguous も同様。

*6:区切りパターンに任意の forward レンジを指定できず、確定サイズが1要素以下のレンジ指定が必要となる。