C++20標準ライブラリ提供レンジアダプタstd::views::splitとstd::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
| 入力\出力 | splitOuter |
splitInner |
lazy_splitOuter |
lazy_splitInner |
|---|---|---|---|---|
| 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要素以下のレンジ指定が必要となる。