funciones examples c++ lambda auto c++14

examples - ¿Cómo funciona lambda genérico en C++ 14?



std c++ (3)

Es una característica propuesta de C ++ 14 (no en C ++ 11) similar (o incluso equivalente) a las plantillas. Por ejemplo, N3559 proporciona este ejemplo:

Por ejemplo, esta declaración que contiene una expresión lambda genérica:

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

podría dar como resultado la creación de un tipo de cierre y un objeto que se comporte de manera similar a la estructura siguiente:

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

¿Cómo funciona lambda genérico (palabra clave auto como tipo de argumento) en C ++ 14 estándar?

¿Está basado en plantillas de C ++ donde para cada argumento de tipo diferente el compilador genera una nueva función con el mismo cuerpo pero tipos reemplazados (polimorfismo en tiempo de compilación) o es más similar a los genéricos de Java (tipo de borrado)?

Ejemplo de código:

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


Las lambdas genéricas se introdujeron en C++14 .

Simplemente, el tipo de cierre definido por la expresión lambda tendrá un operador de llamada con plantilla en lugar del operador de llamada regular sin plantilla C++11 las lambdas de C++11 (por supuesto, cuando aparece auto al menos una vez en la lista de parámetros).

Entonces tu ejemplo:

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

Hará glambda una instancia de este tipo:

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

El párrafo 5.1.2 / 5 del borrador estándar n3690 de C ++ 14 especifica cómo se define el operador de llamada del tipo de cierre de una expresión lambda determinada:

El tipo de cierre para una expresión lambda no genérica tiene un operador de llamada de función pública en línea (13.5.4) cuyos parámetros y tipo de retorno están descritos por lambda-expression''s parameter-declaration-clause y trailing-return-type, respectivamente. Para una lambda genérica, el tipo de cierre tiene una plantilla de miembro de operador de llamada de función pública en línea (14.5.2) cuya plantilla-lista-parámetro consiste en un tipo-parámetro de tipo inventado para cada aparición de auto en la cláusula-declaración-parámetro de lambda, en orden de aparición El parámetro de plantilla de tipo inventado es un paquete de parámetros si la correspondiente declaración de parámetro declara un paquete de parámetros de función (8.3.5). El tipo de retorno y los parámetros de función de la plantilla de operador de llamada de función se derivan de las cláusulas de declaración de retorno y tipo de declaración de parámetro lambda -extract reemplazando cada ocurrencia de auto en los especificadores de decl del parámetro-declaration-clause con el nombre de el correspondiente template-parameter inventado.

Finalmente:

¿Es similar a las plantillas donde, para cada argumento de tipo diferente, el compilador genera funciones con el mismo cuerpo pero tipos modificados o es más similar a los genéricos de Java?

Como se explica en el párrafo anterior, las lambdas genéricas son simplemente azúcar sintáctica para funtores únicos sin nombre con un operador de llamada con plantilla. Eso debería responder a su pregunta :)


Desafortunadamente , no son parte de C ++ 11 ( http://ideone.com/NsqYuq ):

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

Con g ++ 4.7:

prog.cpp:1:24: error: parameter declared ‘auto’ ...

Sin embargo , la forma en que podría implementarse en C ++ 14 según la propuesta de Portland para lambdas genéricos :

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

Esto generaría en su mayor parte la creación habitual de una clase de functor anónima, pero con la falta de tipos el compilador emitiría un miembro miembro operator() :

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

O según la propuesta más nueva Propuesta para Expresiones Lambda Genéricas (Polimórficas)

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;

Entonces, sí, por cada permutación de parámetros, surgiría una nueva instanciación, sin embargo, los miembros de ese funtor aún serían compartidos (es decir, los argumentos capturados).