【C++20】Rangesライブラリ入門 | C++の新しいアルゴリズム操作

目次

はじめに

従来のC++標準ライブラリ(STL)アルゴリズムは、sort(v.begin(), v.end()) のように、必ずコンテナのイテレータをペアで渡す必要がありました。これは冗長であり、end()begin() と書き間違えるといった単純なミスも起こり得ました。

C++20で導入されたRangesライブラリは、この問題を解決します。Rangesは、vectorarrayのようなコンテナそのものを「レンジ(要素の範囲)」という単一の概念として扱うことができます。

この記事では、Rangesライブラリがもたらす3つの主要な改善点について、その概要を解説します。

  1. レンジ対応アルゴリズム: イテレータのペアの代わりに、コンテナを直接渡せる。
  2. レンジアダプタ(ビュー): パイプ(|)を使って、複数の操作をメソッドチェーンのように繋げられる。
  3. コンテナへの変換: ビューが表現する結果を、簡単に新しいコンテナに変換できる。

1. レンジ対応アルゴリズム

Rangesライブラリは、従来のアルゴリズムのレンジ対応版を提供します。これにより、コードが非常に簡潔になります。

サンプルコード

#include <iostream>
#include <vector>
#include <algorithm> // std::count
#include <ranges>    // std::ranges::count

using namespace std;

int main() {
    vector<int> numbers = {10, 20, 30, 20, 40};
    
    // 従来の方法
    long count1 = std::count(numbers.begin(), numbers.end(), 20);
    
    // レンジ対応の方法
    long count2 = std::ranges::count(numbers, 20);

    cout << "20の個数 (従来): " << count1 << endl;
    cout << "20の個数 (レンジ): " << count2 << endl;

    return 0;
}

解説: std::ranges::count では、.begin().end() を渡す必要がなく、コンテナ numbers を直接渡すだけで済みます。


2. レンジアダプタ(ビュー)とパイプ演算子

Rangesの最も強力な機能が、ビューパイプ演算子 (|) です。ビューは、元のデータをコピーせず、データに対する操作(フィルタリングや変換など)の連鎖を定義する軽量なオブジェクトです。

サンプルコード

#include <iostream>
#include <vector>
#include <ranges>

namespace views = std::ranges::views;

int main() {
    vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // データの流れ: data -> 偶数のみフィルタ -> 各要素を10倍
    auto view = data 
              | views::filter([](int n){ return n % 2 == 0; }) 
              | views::transform([](int n){ return n * 10; });
    
    // ビューをループ処理
    for (int result : view) {
        cout << result << " ";
    }
    cout << endl;

    return 0;
}

実行結果: 20 40 60 80 100

解説: data | views::filter(...) | views::transform(...) というコードは、「data の中から、偶数のものだけを(filter)、10倍(transform)してくれ」という処理の流れを、左から右へ、非常に直感的に表現しています。従来のforループとif文を組み合わせる方法よりも、はるかに宣言的で読みやすくなります。


3. ビューからコンテナへの変換 (C++23)

ビューはあくまで「眺め」であり、それ自体はデータを保持しません。ビューが示す結果を、新しいvectorlistとして実体化したい場合は、C++23で導入された std::ranges::to を使います。

サンプルコード (C++23)

#include <iostream>
#include <vector>
#include <list>
#include <ranges>

namespace views = std::ranges::views;
namespace ranges = std::ranges;

int main() {
    vector<int> source = {1, 2, 3, 4, 5, 6};

    // 偶数だけをフィルタリングしたビューを、新しいlistに変換
    list<int> evens = source 
                    | views::filter([](int n){ return n % 2 == 0; }) 
                    | ranges::to<list<int>>();
    
    for (int n : evens) {
        cout << n << " ";
    }
    cout << endl; // -> 2 4 6
    
    return 0;
}

解説: パイプの最後に | ranges::to<コンテナ型>() を繋げるだけで、ビューの結果が新しいコンテナに変換されます。


まとめ

今回は、C++20のRangesライブラリがもたらす主要な機能の概要を解説しました。

  • イテレータのペアの代わりに、コンテナを直接アルゴリズムに渡せるようになった。
  • ビューパイプ演算子 (|) を使うことで、宣言的で直感的なデータ操作が可能になった。
  • ビューの結果を、簡単に新しいコンテナに変換できるようになった (C++23)。

Rangesライブラリは、C++でのデータ操作を、より安全で、より表現力豊かで、より効率的なものへと進化させる、非常に重要な機能です。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次