最終更新日時(UTC): 2025年07月10日 01時26分30秒
Koichi Murase が更新

履歴 編集

# ジェネリックラムダ [N3649](C++14)

このページはC++14に採用された言語機能の変更を解説しています。

のちのC++規格でさらに変更される場合があるため関連項目を参照してください。

## 概要

ジェネリックラムダ(generic lambdas)は、C++11のラムダ式を拡張して、パラメータにテンプレートを使用できるようにした機能である。

    auto plus = [](auto a, auto b) { return a + b; };

このラムダ式は、以下のような関数呼び出し演算子を持つ関数オブジェクトを生成する。

    template <class T1, class T2>
    auto operator()(T1 a, T2 b) const
    {
      return a + b;
    }

## 仕様

- ラムダ式のパラメータには、具体的な型に加えて、`auto`を指定できる。
- `auto`は、型をテンプレートパラメータにするためのプレースホルダーである。

- ラムダ式のパラメータに`auto`を指定し、`[](auto x) {}`のように記述した場合、以下のような関数オブジェクトが生成される：

      struct F {
        template <class T>
        auto operator()(T x) const {}
      };

- 複数のパラメータ型をそれぞれ`auto`に指定した場合、各パラメータは異なるテンプレートパラメータが割り当てられる：

      auto f = [](auto a, auto b) {}

      struct F {
        template <class T1, class T2>
        auto operator()(T1 a, T2 b) const {}
      };

- ラムダ式に指定する`auto`は、テンプレートと同様に、`const`、`volatile`、参照、ポインタといった修飾ができる：

      auto plus = [](const auto& a, const auto& b) { return a + b; };

- `auto`などに続いて「`...`」を記述することにより、関数パラメーターパックを宣言できる：

      auto f = [](auto... args) {} // argsは関数パラメーターパック

      struct F {
        template <class... Args>
        auto operator()(Args... args) const {}
      };

- 関数テンプレートと違い、ラムダ式の`auto`パラメータは、パラメータのテンプレートパラメータを推論する目的には使用できない：

      auto f = [](std::vector<auto> a) {}; // コンパイルエラー

- キャプチャを含まないジェネリックラムダは、関数ポインタへの変換演算子を持つ。変換先の関数ポインタは、パラメータ型を推論した結果のラムダ式のシグニチャと、完全に一致しなければならない：

      int(*fp1)(int) = [](auto x) { return x; }; // OK
      char(*fp2)(int) = [](auto x) { return x; }; // コンパイルエラー

## 備考

ジェネリックラムダはパラメータの型がテンプレートであるために、パラメータをテンプレートのまま`std::function`クラスのオブジェクトに代入はできない。

## 例

    #include <iostream>
    #include <string>

    using namespace std::string_literals;

    int main()
    {
      // ラムダ式のパラメータ型をautoにすることで、
      // 任意の型をパラメータとして受け取れる
      auto plus = [](auto a, auto b) { return a + b; };

      int result1 = plus(3, 2);
      std::string result2 = plus("Hello"s, "World"s);

      std::cout << result1 << std::endl;
      std::cout << result2 << std::endl;
    }

### 出力

    5
    HelloWorld

## 検討されたほかの選択肢

ジェネリックラムダの構文として、最初は`auto`を書かずにパラメータの変数名と型修飾のみを書くように考えられていた。

    [](const& x, & y) { return x + y; }

これが現在`auto`を書くようになったのは、可読性のためである。

## 関連項目

- C++11 ラムダ式
- C++14 ラムダ式の初期化キャプチャ
- C++14 通常関数の戻り値型推論
- C++20 ジェネリックラムダのテンプレート構文
- C++20 autoパラメータによる関数テンプレートの簡易定義

## 参照

- N3418 Proposal for Generic (Polymorphic) Lambda Expressions
- N3559 Proposal for Generic (Polymorphic) Lambda Expressions (Revision 2)
- N3649 Generic (Polymorphic) Lambda Expressions (Revision 3)