← SEARCHABLE ARCHIVE
C / C++ · 2026-08-12

C++ 基礎からマスターまで — 第18回

Ranges と Views で遅延データパイプラインを作る

INTERACTIVE READING MODE →

本ブログの記事は、講義を目的として作成しています。 内容に誤りが含まれる可能性があるため、対象コンパイラと標準ライブラリの資料も確認してください。

Iterator はコンテナとアルゴリズムを分離しますが、従来の呼び出しでは begin と end を毎回渡します。C++20 Ranges は範囲そのものを受け取り、Views はデータをコピーしない遅延変換を合成します。

範囲を直接渡す

std::vector<int> scores{30, 80, 50, 100};
std::ranges::sort(scores);

auto found = std::ranges::find(scores, 80);
if (found != scores.end())
{
    // 値が見つかった。
}

begin と end を別々に書かないため、異なるコンテナの iterator を混ぜる危険が減ります。projection ならメンバを直接指定できます。

std::ranges::sort(players, {}, &Player::Score);

View は必要なときに計算する

auto visibleNames = players
    | std::views::filter([](const Player& p) { return p.IsVisible; })
    | std::views::transform([](const Player& p) -> const std::string&
      {
          return p.Name;
      })
    | std::views::take(10);

for (const std::string& name : visibleNames)
    DrawName(name);

この処理は三つの中間 vector を作りません。反復で要素が要求されたときに filter と transform が動き、take(10) は最大十件で止まります。

多くの View はデータを所有しない

auto MakeBadView()
{
    std::vector<int> local{1, 2, 3};
    return local | std::views::filter([](int value) { return value > 1; });
}

返された View はローカル vector を参照していますが、関数終了時に vector は破棄されます。後の反復は寿命の切れたオブジェクトにアクセスします。

View を保存・返却する前に、元の range がすべての利用より長く生きることを確認します。独立した所有権が必要なら、明示的にコンテナへ収集します。

遅延評価では、エラーや副作用も反復時まで遅れます。元のコンテナを変更すれば、通常と同じ iterator 無効化規則が適用されます。

Ranges の価値は短い構文より、データの流れを段階として表現できることです。パイプラインが長い、または状態変更が混ざる場合は中間処理に名前を付けるか、明示的なアルゴリズムへ戻します。