Boost.Range で入力シーケンスを処理しようとしています。このライブラリにはまだ多くの要望が残されているため、追加の範囲アダプターを自分で作成する必要があります。それらのほとんどは簡単ですが、Haskell の groupBy (または range-v3 の group_by_view) に相当するものを実装しようとしたときに、いくつかの問題に遭遇しました。これは、入力範囲を取り、範囲の範囲を返す変換です。各範囲には、特定のバイナリ述語を満たす入力からの一連の隣接する要素が含まれます。たとえば、二項述語が単にstd::equal_to<int>()
の場合、シーケンスは
{1, 1, 2, 3, 5, 5, 5, 4, 1}
にマッピングされます
{{1, 1}, {2}, {3}, {5, 5, 5}, {4}, {1}}
私の問題は、このアダプターのインターフェースにあります。仮定する
auto i = (input | grouped_by(std::equal_to<int>())).begin();
がインクリメントされた場合i
、2 が見つかるまで基になるシーケンスをスキャンする必要があります。ただし、最初にスキャンする場合*i
(これは range です{1, 1}
)、基本的に最初のグループの終わりをすでに見つけているため、によって引き起こされるトラバーサルは++i
冗長になります。 . 内側の反復子から外側の反復子への何らかのフィードバック パスを持つことは可能です。つまりi
、内側の反復子が最後に到達した要素からスキャンを開始する必要がありますが、多くのオーバーヘッドが発生し、ダングリング イテレータが作成されるリスクがあります。
この問題に対処する慣用的な方法があるかどうか疑問に思っています。理想的grouped_by
には、問題を完全に回避するインターフェイスの再定義です。明らかに、各グループの先頭を見つけるために入力範囲をスキャンする必要がありますが、理由もなく要素を再スキャンせずにそれを行うための堅牢な方法が必要です。(ロバストとは、基礎となる入力範囲の反復子が有効である限り、反復子を無効にしないことを意味し、スキャン自体の間ではありません。)
だから..これに対する既知の/証明された/エレガントな解決策はありますか?