webentwicklung-frage-antwort-db.com.de

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, bei denen der Compiler für jeden Argumenttyp eine neue Funktion mit demselben Textkörper generiert, jedoch Typen ersetzt (Polymorphismus zur Kompilierungszeit), oder ähnelt es eher den Generika von Java (Typlöschung)?

Codebeispiel:

auto glambda = [](auto a) { return a; };
107
sasha.sochka

Generische Lambdas wurden eingeführt in C++14.

Einfach gesagt hat der durch den Lambda-Ausdruck definierte Verschlusstyp einen Templat-Aufrufoperator und nicht den regulären Nicht-Template-Aufrufoperator von C++11 s Lambdas (natürlich, wenn auto mindestens einmal in der Parameterliste erscheint).

Also dein Beispiel:

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

Wird glambda zu einer Instanz dieses Typs machen:

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

In Abschnitt 5.1.2/5 des C++ 14 Standard Draft n3690 wird festgelegt, wie der Aufrufoperator des Abschlusstyps eines bestimmten Lambda-Ausdrucks definiert wird:

Der Verschlusstyp für einen nicht generischen Lambda-Ausdruck hat einen öffentlichen Inline-Funktionsaufrufoperator (13.5.4), dessen Parameter und Rückgabetyp durch die Parameterdeklarationsklausel des Lambda-Ausdrucks bzw. den nachfolgenden Rückgabetyp beschrieben werden. Für ein generisches Lambda hat der Schließungstyp eine öffentliche Inline-Funktionsaufruf-Operator-Member-Vorlage (14.5.2), deren Vorlagenparameterliste aus einem erfundenen Typvorlagenparameter für jedes Vorkommen von auto in den Lambda-Parameter besteht.) Deklarationsklausel, in der Reihenfolge ihres Auftretens. Der erfundene Typ template-parameter ist ein Parameterpaket, wenn die entsprechende Parameterdeklaration ein Funktionsparameterpaket deklariert (8.3.5). Der Rückgabetyp und die Funktionsparameter der Operatorvorlage für Funktionsaufrufe werden aus der Trailing-Return-Klausel und der Parameterdeklarationsklausel des Lambda-Ausdrucks abgeleitet, indem jedes Vorkommen von auto in den Deklarationsklauseln der Parameterdeklarationsklausel durch den Namen von ersetzt wird der entsprechende erfundene template-parameter.

Endlich:

Ist es Vorlagen ähnlich, bei denen der Compiler für jeden unterschiedlichen Argumenttyp Funktionen mit demselben Textkörper generiert, aber Typen ändert, oder ist es Javas Generika ähnlicher?

Wie im obigen Abschnitt erläutert, sind generische Lambdas nur syntaktischer Zucker für eindeutige, nicht benannte Funktoren mit einem Aufrufoperator mit Vorlagen. Das sollte deine Frage beantworten :)

124
Andy Prowl

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’
...

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

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

Dies würde den größten Teil der üblichen Erstellung einer anonymen Funktorklasse ergeben, aber bei fehlenden Typen würde der Compiler ein Templated-Member -operator() ausgeben:

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

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

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

--->

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

Ja, für jede Permutation von Parametern würde eine neue Instanziierung entstehen, jedoch würden die Mitglieder dieses Funktors weiterhin gemeinsam genutzt (d. H. Die erfassten Argumente).

25
Sebastian Mach

Es ist eine vorgeschlagene C++ 14-Funktion (nicht in C++ 11), die Vorlagen ähnelt (oder sogar äquivalent ist). Zum Beispiel liefert N3559 folgendes Beispiel:

Zum Beispiel enthält dieser generische Lambda-Ausdruck folgende Anweisung:

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

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

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