Was ist die in C ++ 20 eingeführte Vorlage Lambda, wenn C ++ 14 bereits generisches Lambda enthält?

99

führte generische Lambdas ein, die es ermöglichten, Folgendes zu schreiben:

auto func = [](auto a, auto b){
    return a + b;
};
auto Foo = func(2, 5);
auto Bar = func("hello", "world");

Es ist sehr klar, dass dieses generische Lambda funcgenau so funktioniert, wie eine Vorlagenfunktion funktionieren funcwürde.

Warum hat das C ++ - Komitee beschlossen, eine Vorlagensyntax für generisches Lamda hinzuzufügen?

coder3101
quelle
5
Was ist, wenn Sie einen anderen Vorlagentyp als für die Argumente oder den Rückgabetyp verwenden müssen? Und was ist, wenn es im Körper gebraucht wird?
Einige Programmierer Typ
Mir wurde gesagt, dies sei ein interessanter Anwendungsfall.
Max Langhof

Antworten:

115

C ++ 14 generische Lambdas sind eine sehr coole Möglichkeit, einen Funktor mit einem folgenden Format zu generieren operator ():

template <class T, class U>
auto operator()(T t, U u) const;

Aber nicht so:

template <class T>
auto operator()(T t1, T t2) const; // Same type please

Noch so:

template <class T, std::size_t N>
auto operator()(std::array<T, N> const &) const; // Only `std::array` please

Auch nicht so (obwohl es etwas schwierig wird, es tatsächlich zu benutzen):

template <class T>
auto operator()() const; // No deduction

C ++ 14 Lambdas sind in Ordnung, aber mit C ++ 20 können wir diese Fälle problemlos implementieren.

QUentin
quelle
2
Schön und prägnant. Fügen Sie einfach Folgendes hinzu: Der erste (gleiche Typ) kann (auto a, decltype(a) b)in C ++ 14 gelöst werden .
Sebastian Mach
13
@SebastianMach fast. Mit dieser Lösung bwird nicht abgeleitet, und ihr Argument wird implizit in den Typ von astattdessen konvertiert .
Quentin
32

Da Sie in C ++ 20 Lambdas mit Vorlagen verwenden können, können Sie Ihre Typen einfacher einschränken als mit einem SFINAE-Ausdruck:

auto lambda = []<typename T>(std::vector<T> t){};

Dieses Lambda funktioniert nur mit Vektortypen.

Antoine Morrier
quelle
8
Wie hängt das constevalmit der neuen Syntax zusammen? Es ist cool und alles, aber ich verstehe die Relevanz nicht.
Geschichtenerzähler - Unslander Monica
Es ist eher eine Information darüber, was C ++ 20 zum Lambda-Ausdruck hinzufügt, als eine Antwort auf die Frage
Antoine Morrier
24

Der Vorschlag , der in C ++ 20 angenommen wurde, enthält einen langen Motivationsabschnitt mit Beispielen. Die Prämisse davon ist folgende:

Es gibt einige Hauptgründe, warum die aktuelle Syntax zur Definition generischer Lambdas vom Autor als unzureichend angesehen wird. Der Kern davon ist, dass einige Dinge, die mit normalen Funktionsvorlagen leicht erledigt werden können, ein erhebliches Reifenspringen erfordern, um mit generischen Lambdas ausgeführt zu werden, oder überhaupt nicht ausgeführt werden können. Der Autor ist der Ansicht, dass Lambdas wertvoll genug sind, dass C ++ sie unterstützen sollte genauso gut wie normale Funktionsvorlagen.

Daran schließen sich einige Beispiele an.

Geschichtenerzähler - Unslander Monica
quelle
21

Die in C ++ 20 eingeführte neue "vertraute Vorlagensyntax" für Lambdas macht Konstrukte wie  for_types und  for_range lebensfähig und im Vergleich zu C ++ 17-Alternativen viel lesbarer.

(Quelle: Iteration zur Kompilierungszeit mit C ++ 20 Lambdas )

Eine weitere interessante Funktion, die sowohl für generische C ++ 14- als auch für C ++ 17-Lambdas ausgeführt werden kann, ist das direkte Aufrufen  operator() durch explizite Übergabe eines Vorlagenparameters:

C ++ 14:

   auto l = [](auto){ };
   l.template operator()<int>(0);

C ++ 20:

  auto l = []<typename T>(){ };
  l.template operator()<int>();

Das obige C ++ 14-Beispiel ist ziemlich nutzlos: Es gibt keine Möglichkeit, auf den Typ zu verweisen, der  operator() im Hauptteil des Lambda angegeben ist, ohne dem Argument einen Namen zu geben und es zu verwenden  decltype. Außerdem müssen wir ein Argument übergeben, obwohl wir es möglicherweise nicht benötigen.

Das C ++ 20-Beispiel zeigt, wie T im Körper des Lambda leicht zugänglich ist und dass ein Null-Lambda nun willkürlich als Vorlage verwendet werden kann. Dies wird für die Implementierung der oben genannten Konstrukte zur Kompilierungszeit sehr nützlich sein

Hamza.S
quelle