このページは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パラメータによる関数テンプレートの簡易定義