はじめに
C++で、コンテナ(vector
など)から「最初の3要素だけ」や「偶数の要素だけ」を取り出したい場合、従来は手動でfor
ループとif
文を組み合わせる必要がありました。
C++20で導入されたRanges(レンジ)ライブラリは、このようなデータシーケンスの操作を劇的に簡潔にするための強力なツールです。レンジアダプタ(views
)をパイプ演算子(|
)で繋げることで、まるでデータの流れを加工していくかのように、目的の要素を抽出できます。
この記事では、Rangesライブラリの中でも特に使用頻度の高い、以下の3つの基本的なレンジアダプタの使い方を解説します。
views::take
: 先頭から指定した数の要素を抜き出す。views::drop
: 先頭から指定した数の要素を読み飛ばす。views::filter
: 条件に一致する要素だけを抜き出す。
【前提】C++20とは?
C++20(シーピープラスにーぜろ)は、2020年に正式化されたC++言語のメジャーアップデート版です。RangesライブラリはこのC++20で導入された主要機能のため、利用するにはC++20に対応したコンパイラが必要です。
レンジアダプタを使ったサンプルコード
このコードは、一つのvector
に対して、take
, drop
, filter
の3つの異なるビューを適用し、それぞれの結果を出力します。
完成コード
#include <iostream>
#include <vector>
#include <ranges> // Rangesライブラリを使うために必要
namespace views = std::ranges::views; // views名前空間のエイリアス
int main() {
std::vector<int> numbers = {10, 25, 30, 45, 50, 65, 70, 85, 90};
// 1. views::take : 先頭から4つの要素を抜き出す
std::cout << "先頭4要素 (take): ";
for (int n : numbers | views::take(4)) {
std::cout << n << " ";
}
std::cout << std::endl;
// 2. views::drop : 先頭5つの要素を読み飛ばし、残りを抜き出す
std::cout << "先頭5要素を飛ばす (drop): ";
for (int n : numbers | views::drop(5)) {
std::cout << n << " ";
}
std::cout << std::endl;
// 3. views::filter : 条件(10の倍数)に一致する要素だけを抜き出す
std::cout << "10の倍数のみ (filter): ";
auto is_multiple_of_10 = [](int n) { return n % 10 == 0; };
for (int n : numbers | views::filter(is_multiple_of_10)) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}
実行結果
先頭4要素 (take): 10 25 30 45
先頭5要素を飛ばす (drop): 65 70 85 90
10の倍数のみ (filter): 10 30 50 70 90
コードの解説
|
パイプ演算子
numbers | views::take(4)
のように、コンテナとレンジアダプタを |
(パイプ)で繋ぎます。これは、「numbers
というデータの流れを、views::take(4)
というフィルターに通す」というイメージです。
1. views::take(n)
元のコンテナの先頭から n
個の要素だけを含むビューを作成します。
2. views::drop(n)
元のコンテナの先頭から n
個の要素を無視し、それ以降の全ての要素を含むビューを作成します。
3. views::filter(条件)
引数として渡された条件を満たす (true
を返す) 要素だけを含むビューを作成します。
auto is_multiple_of_10 = [](int n) { return n % 10 == 0; };
: この部分はラムダ式と呼ばれ、その場で使える簡単な関数を定義しています。「int
型のn
を受け取り、n
が10
で割り切れればtrue
を返す」という条件を表します。
ビューの特性:遅延評価
views
は「ビュー(眺め)」という名前の通り、元のコンテナのデータをコピーしません。views::take(4)
は、元の numbers
を「先頭4つだけ眺める」という設定を作成するだけで、実際にデータにアクセスするのは for
ループが始まったときです。この「遅延評価」という仕組みにより、Rangesライブラリは非常に効率的に動作します。
まとめ
今回は、C++20のRangesライブラリを使って、コンテナから特定の要素を抽出する3つの基本的なアダプタを解説しました。
views::take
: 先頭からN個views::drop
: 先頭N個を飛ばして、残り全部views::filter
: 条件に合うものだけ
Rangesライブラリは、これらのアダプタを |
で繋げて、numbers | views::filter(...) | views::take(3)
のように、複数の操作を組み合わせることも可能です。これにより、複雑なデータ操作を、宣言的で非常に読みやすいコードで記述することができます。