c++ c++14 c++20 generic-lambda

¿Cuál es la necesidad de la plantilla lambda introducida en C++ 20 cuando C++ 14 ya tiene lambda genérica?



c++14 c++20 (4)

c ++ 14 introdujo lambdas genéricas que permitieron escribir lo siguiente:

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

Es muy claro que esta func lambda genérica func misma manera que una función de func plantilla funcionaría.

¿Por qué el comité de C ++ decidió agregar la sintaxis de la plantilla para la lamda genérica?


La nueva "sintaxis de plantilla familiar" para las lambdas introducida en C ++ 20 hace que las construcciones como for_types y for_range viables y mucho más legibles en comparación con las alternativas de C ++ 17.

(fuente: iteración en tiempo de compilación con C ++ 20 lambdas )

Otra cosa interesante que se puede hacer con las lambdas genéricas de C ++ 14 y C ++ 17 es llamar directamente al operator() al pasar explícitamente un parámetro de plantilla:

C ++ 14:

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

C ++ 20:

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

El ejemplo anterior de C ++ 14 es bastante inútil: no hay manera de referirse al tipo proporcionado a operator() en el cuerpo de la lambda sin dar un nombre al argumento y usar decltype . Además, nos vemos obligados a pasar una discusión aunque no la necesitemos.

El ejemplo de C ++ 20 muestra cómo T es fácilmente accesible en el cuerpo de la lambda y que un lambda nulo ahora puede ser arbitrariamente arbitrado. Esto será muy útil para la implementación de las construcciones en tiempo de compilación mencionadas anteriormente.


La proposal que fue aceptada en C ++ 20 tiene una larga sección de motivación, con ejemplos. La premisa de esto es esta:

Hay algunas razones clave por las que el autor considera que la sintaxis actual para definir lambdas genéricas es insuficiente. La esencia de esto es que algunas cosas que se pueden hacer fácilmente con las plantillas de funciones normales requieren que se realicen importantes saltos de aro con lambdas genéricas, o no se pueden hacer en absoluto. Así como las plantillas de funciones normales.

A continuación hay algunos ejemplos.


Las lambdas genéricas de C ++ 14 son una forma genial de generar un functor con un operator () que se parece a esto:

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

Pero no así:

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

Tampoco así:

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

Tampoco de esta manera (aunque esto es un poco difícil de usar):

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

Las lambdas de C ++ 14 están bien, pero C ++ 20 nos permite implementar estos casos sin problemas.


Ya que puedes usar lambdas templadas en C ++ 20, puedes restringir tus tipos de una manera más fácil que una expresión SFINAE:

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

Esta lambda funcionará solo con tipos de vectores.