Wie funktioniert generisches Lambda in C ++ 14?

Wie funktioniert generisches Lambda ( auto Schlüsselwort als Argumenttyp) in C ++ 14 Standard?

Basiert es auf C ++ – Vorlagen, wo der Compiler für jeden unterschiedlichen Argumenttyp eine neue function mit demselben Textkörper generiert, aber Typen ersetzt (Kompilierzeit-Polymorphismus) oder ist er den Java-Generika (Typlöschung) ähnlicher?

Codebeispiel:

 auto glambda = [](auto a) { return a; }; 

Generische Lambdas wurden in C++14 .

Der durch den Lambda-Ausdruck definierte Verschlusstyp hat einfach einen Templates- Call-Operator anstelle des normalen, nicht-Template-Call-Operators von C++11 ‘s Lambdas (natürlich, wenn auto mindestens einmal in der Parameterliste erscheint).

Also dein Beispiel:

 auto glambda = [] (auto a) { return a; }; 

glambda eine Instanz dieses Typs:

 class /* unnamed */ { public: template T operator () (T a) const { return a; } }; 

In Absatz 5.1.2 / 5 des C ++ 14 Standard Draft n3690 ist festgelegt, wie der Aufrufoperator des Closure-Typs eines gegebenen Lambda-Ausdrucks definiert wird:

Der Closure-Typ für einen nicht-generischen Lambda-Ausdruck hat einen öffentlichen Inline-functionsaufrufoperator (13.5.4), dessen Parameter und Rückgabetyp durch die parameter-declaration-clause des lambda-Ausdrucks und den schleppenden Rückgabetyp beschrieben werden. Für einen generischen Lambda hat der Closure-Typ eine öffentliche Inline-functionsaufruf-Operator-Member-Vorlage (14.5.2), deren Template-Parameter-Liste aus einem Template-Parameter vom Typ erfunden für jedes Auftreten von Auto in der Parameter-Deklarationsklausel des Lambda besteht. in der Reihenfolge des Auftretens . Der Template-Parameter vom Typ dated ist ein Parameterpack, wenn die entsprechende Parameterdeklaration ein functionsparameter-Pack (8.3.5) deklariert. Der Rückgabetyp und die functionsparameter des functionsaufruf-Operator-Templates werden aus dem Trailing-Return-Typ und der Parameter-Deklarationsklausel des Lambda-Ausdrucks abgeleitet, indem jedes Vorkommen von Auto in den Deklarationsspezifizierern der Parameterdeklarationsklausel durch den Namen von ersetzt wird der entsprechende erfundene Template-Parameter.

Endlich:

Ähnelt es Templates, bei denen der Compiler für jeden unterschiedlichen Argumenttyp functionen mit dem gleichen Body, aber geänderten Typen erzeugt oder ist er den Java-Generics ähnlicher?

Wie der obige Absatz erklärt, sind generische Lambdas nur syntaktische Zucker für einzigartige, unbenannte Funktoren mit einem Templat-Call-Operator. Das sollte deine Frage beantworten 🙂

Leider sind sie nicht Teil von C ++ 11 ( http://ideone.com/NsqYuq ):

 auto glambda = [](auto a) { return a; }; int main() {} 

Mit g ++ 4.7:

 prog.cpp:1:24: error: parameter declared 'auto' ... 

Wie es jedoch in C ++ 14 gemäß dem Portland-Vorschlag für generische Lambdas implementiert werden könnte:

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

Dies würde zum größten Teil die übliche Erstellung einer anonymen Funktorklasse ergeben, aber mit dem Fehlen von Typen würde der Compiler einen templated member- operator() ausgeben:

 struct anonymous { template  auto operator()(T const& x, U& y) const -> decltype(x+y) { return x + y; } }; 

Oder gemäß dem neueren Vorschlag für generische (polymorphe) Lambda-Ausdrücke

 auto L = [](const auto& x, auto& y){ return x + y; }; ---> struct /* anonymous */ { template  auto operator()(const T& x, U& y) const // N3386 Return type deduction { return x + y; } } L; 

Also, ja, für jede Permutation von Parametern würde eine neue Instantiierung entstehen, jedoch würden die Mitglieder dieses Funktors immer noch geteilt werden (dh die eingefangenen Argumente).

Es ist eine vorgeschlagene C ++ 14-function (nicht in C ++ 11) ähnlich (oder sogar gleichwertig) zu Vorlagen. Zum Beispiel bietet N3559 dieses Beispiel:

Zum Beispiel diese generische lambda-expression containing statement:

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

kann zur Erstellung eines Verschlusstyps und eines Objekts führen, das sich ähnlich wie die folgende Struktur verhält:

 struct /* anonymous */ { template  auto operator()(const T& x, U& y) const // N3386 Return type deduction { return x + y; } } L;