【C++】views::enumerate でインデックス付きforループをスマートに書く方法

目次

はじめに

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++でもついに利用可能になりました。これにより、日々のコーディングがさらに快適で安全になります。

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

この記事を書いた人

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

目次