⛓️
[C++] <ranges>のviewを見る11 - drop_while_view
drop_while_view
drop_while_view
は元となるシーケンスの先頭から条件を満たす連続した要素を取り除いたシーケンスを生成するViewです。
#include <ranges>
iint main() {
// 先頭のホワイトスペースを取り除く
std::ranges::drop_while_view dv{" drop while view", [](char c) { return c == ' '; }};
for (char c : dv) {
std::cout << c;
}
}
drop_while_view
はかなりdrop_view
と似た振る舞いをします。
オーバーラン防止と遅延評価
drop_while_view
もdrop_view
と同様の方法によって遅延評価とオーバーランの防止を行なっています。
すなわち、drop_while_view
はそのイテレータの取得時(begin()
の呼び出し時)に元となるシーケンスの先頭イテレータを条件を満たさない最初の要素まで進めて返します。その際、元のシーケンス上で終端チェックを行いながら進めることでオーバーランしないようになっています。これはC++20から追加されたstd::ranges::find_if_not(base_view, pred)
を使用して行われます。
// drop_view構築時にはまだ何もしない
std::ranges::drop_while_view dv{" drop while view", [](char c) { return c == ' '; }};
// イテレータ取得時にスキップ処理が行われる
// 元のシーケンスの先頭イテレータを条件を満たす間進めるだけ
// その際終端チェックを同時に行う
auto it = std::ranges::begin(dv);
// その他の操作は元のシーケンスのイテレータそのまま
++it;
*it;
drop_while_view
は元となるシーケンスのイテレータを完全に流用するので、drop_while_view
のrangeは元のシーケンスのrangeカテゴリと同じになります。
drop_while_view
のbegin()
の呼び出しも、元のシーケンスがforward_range
(以上の強さ)であるときキャッシュされることが規定されています。これによってdrop_while_view
のbegin()
も計算量は償却定数となります。
views::drop_while
drop_while_view
に対応するrange adaptor objectがstd::views::drop_while
です。
#include <ranges>
int main() {
for (char c : std::views::drop_while(" drop while view", [](char c) { return c == ' '; })) {
std::cout << c;
}
std::cout << '\n';
// パイプラインスタイル
for (char c : " drop while view" | std::views::drop_while([](char c) { return c == ' '; })) {
std::cout << c;
}
}
views::drop_while
はカスタマイゼーションポイントオブジェクトであり、2つの引数を受け取りそれらを転送してdrop_while_view
を構築して返します。
Discussion