はじめに
C++の範囲for
文 (for (auto item : items)
) は、コンテナの全要素を簡潔にループ処理できる非常に便利な機能です。しかし、ループの中で「今が何番目の要素か」というインデックス番号も同時に使いたい場合、従来はループの外でカウンター変数を別途用意する必要があり、少し不格好でした。
この問題を解決するために、C++23では std::views::enumerate
という新しいレンジアダプタが導入されました。enumerate
を使うと、範囲for
文の中で、要素とそのインデックスをペアで直接受け取ることができるようになります。
この記事では、views::enumerate
を使って、インデックス付きのループ処理をいかに簡潔で安全に記述できるかを、従来の方法と比較しながら解説します。
【前提】C++23とは?
C++23(シーピープラスにーさん)は、2023年に正式化された、C++言語の比較的新しい規格です。std::views::enumerate
はこのC++23で追加された機能のため、利用するにはC++23に対応した最新のコンパイラ(と、その機能を有効にするための設定)が必要になります。
views::enumerate
を使ったサンプルコード
このコードは、vector
に格納された文字列を、従来の方法とC++23の views::enumerate
を使った方法の2通りで、インデックス付きで出力します。
完成コード
#include <iostream>
#include <vector>
#include <string>
#include <ranges> // views::enumerate を使うために必要
using namespace std;
int main() {
vector<string> data = {"りんご", "みかん", "ぶどう"};
// --- 従来の方法 (C++20まで) ---
cout << "--- 従来の方法 ---" << endl;
int manual_index = 0;
for (const auto& item : data) {
cout << "[" << manual_index << "]: " << item << endl;
manual_index++;
}
cout << "\n--- C++23 views::enumerate を使った方法 ---" << endl;
// --- C++23の方法 ---
for (const auto& [index, item] : views::enumerate(data)) {
cout << "[" << index << "]: " << item << endl;
}
return 0;
}
実行結果
--- 従来の方法 ---
[0]: りんご
[1]: みかん
[2]: ぶどう
--- C++23 views::enumerate を使った方法 ---
[0]: りんご
[1]: みかん
[2]: ぶどう
コードの解説
従来の方法
int manual_index = 0;
for (const auto& item : data) {
// ...
manual_index++;
}
ループの外側でカウンター変数 manual_index
を宣言・初期化し、ループの最後で手動でインクリメントする必要がありました。
views::enumerate
を使った方法
for (const auto& [index, item] : views::enumerate(data))
これが enumerate
を使った新しい書き方です。
views::enumerate(data)
:enumerate
は、コンテナdata
を受け取り、各要素を{インデックス, 要素}
というペアの集まり(ビュー)に変換します。[index, item]
: これはC++17で導入された「構造化束縛 (structured binding)」という構文です。enumerate
が生成したペア{インデックス, 要素}
を受け取り、その最初の値をindex
に、2番目の値をitem
という名前の変数に、それぞれ自動で分解して代入してくれます。
この2つの機能を組み合わせることで、ループ変数を宣言するだけで、インデックスと要素を直接、かつ安全に取り出すことができます。カウンター変数の手動管理が不要になるため、コードが簡潔になり、インクリメントのし忘れといったバグも防げます。
まとめ
今回は、C++23で導入された std::views::enumerate
を使って、インデックス付きのループ処理をスマートに記述する方法を解説しました。
std::views::enumerate(コンテナ)
で、インデックスと要素のペアのビューを作成する。- 範囲
for
文と構造化束縛[index, item]
を組み合わせて、ペアを直接受け取る。
enumerate
は、Pythonなどの他の言語では標準的に備わっていた便利な機能であり、C++でもついに利用可能になりました。これにより、日々のコーディングがさらに快適で安全になります。