【C++学習|初心者向け】C++20でコードを劇的に美しく! std::rangesとパイプライン処理入門

1. 導入:なぜstd::rangesが必要なのか?

これまでのC++では、コンテナ(vectorなど)の要素を加工したり抽出したりする場合、`std::begin`と`std::end`を渡す必要がありました。これだとコードが長くなりがちで、何をしているのか読み解くのが大変でしたよね。C++20から導入されたstd::rangesを使えば、まるでコマンドを繋げるような「パイプライン処理」が可能になります。コードの可読性が上がるだけでなく、メモリ効率も良くなるという素晴らしいメリットがあります。

2. 基礎知識:イテレータの管理から解放される

従来のSTLアルゴリズムでは、「範囲」を指定するために`begin()`と`end()`をペアで指定する必要がありました。しかし、std::rangesはコンテナそのものを直接受け取ることができます。
また、今回の肝である「パイプライン演算子(|)」は、処理を左から右へと流すように記述できます。さらに重要なのが遅延評価という仕組みです。これは「実際にその値が必要になるまで計算を行わない」という仕組みで、不要な中間データを作らないため、プログラムの高速化に直結します。

3. 実装/解決策:パイプラインで処理を繋ぐ

`std::views`名前空間にある機能を使うと、データの「抽出(filter)」や「変換(transform)」を連結できます。例えば、「偶数だけを取り出して、それを2乗する」といった複雑な処理も、以下の手順で簡潔に記述できます。

4. サンプルプログラム

以下のコードをコピーして、C++20対応のコンパイラで実行してみてください。

include
include
include // C++20のranges機能
include

int main() {
std::vector nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// パイプライン処理の定義
// 1. filterで偶数のみ抽出
// 2. transformで値を2乗する
auto pipeline = nums
| std::views::filter([](int n) { return n % 2 == 0; })
| std::views::transform([](int n) { return n n; });

// 範囲for文で結果を表示(ここで初めて計算が実行される:遅延評価)
for (int n : pipeline) {
std::cout << n << " "; // 出力: 4 16 36 64 100 } return 0; }

5. 応用・注意点:現場で役立つ知識

注意点:
パイプライン処理は「遅延評価」であるため、`pipeline`という変数自体には計算結果は格納されていません。`for`ループなどで実際に値を取り出すタイミングで初めて計算が走ります。もし、処理結果をすぐに配列として保持したい場合は、`std::ranges::to()`(C++23以降)や、ループで直接コンテナへ格納する必要があります。

現場での活用:
コンパイラは、このパイプライン処理を「一つの最適化されたループ」として解釈してくれます。中間データ用のメモリ確保が発生しないため、大規模なデータ処理を行う際にもメモリ使用量を抑えられ、CPUのキャッシュ効率も向上します。まずは簡単なフィルタリングから、ぜひ日々のコードに取り入れてみてください。

コメント

タイトルとURLをコピーしました