¿Cuál es el tipo de lambda cuando se deduce con “auto” en C ++ 11?

Tenía la percepción de que el tipo de lambda es un puntero a la función. Cuando realicé la siguiente prueba, descubrí que estaba equivocada ( demo ).

#define LAMBDA [] (int i) -> long { return 0; } int main () { long (*pFptr)(int) = LAMBDA; // ok auto pAuto = LAMBDA; // ok assert(typeid(pFptr) == typeid(pAuto)); // assertion fails ! } 

¿El código anterior no tiene ningún punto? Si no, ¿cuál es el tipo de expresión lambda cuando se deduce con auto palabra clave auto ?

El tipo de una expresión lambda no está especificado.

Pero en general son meros azúcares sintácticos para los funtores. Una lambda se traduce directamente en un funtor. Cualquier cosa dentro de [] se convierte en parámetros de constructor y miembros del objeto del functor, y los parámetros dentro de () se convierten en parámetros para el operator() del operator() .

Una lambda que no captura variables (nada dentro de [] ‘s] se puede convertir en un puntero de función (MSVC2010 no es compatible con esto, si ese es su comstackdor, pero esta conversión es parte del estándar).

Pero el tipo real de la lambda no es un puntero de función. Es un tipo de functor no especificado.

Es una estructura única sin nombre que sobrecarga el operador de llamada de función. Cada instancia de un lambda introduce un nuevo tipo.

En el caso especial de una lambda no capturable, la estructura además tiene una conversión implícita a un puntero de función.

[C++11: 5.1.2/3]: el tipo de expresión lambda (que también es el tipo del objeto de cierre) es un tipo de clase no sindicalizado sin nombre, llamado tipo de cierre , cuyas propiedades son descrito abajo. Este tipo de clase no es un agregado (8.5.1). El tipo de cierre se declara en el ámbito de bloque más pequeño, scope de clase o ámbito de espacio de nombres que contiene la expresión lambda correspondiente. [..]

La cláusula continúa para enumerar las propiedades variables de este tipo. Aquí hay algunos puntos destacados:

[C++11: 5.1.2/5]: el tipo de cierre para una expresión lambda tiene un operador de llamada de función pública en inline (13.5.4) cuyos parámetros y tipo de retorno se describen mediante la statement de parámetro lambda-expression -clause y trailing-return-type respectivamente. [..]

[C++11: 5.1.2/6]: el tipo de cierre para una expresión lambda sin captura lambda tiene una función de conversión de const no-pública pública no explícita a puntero a función que tiene el mismo parámetro y tipos de retorno como el operador de llamada de función del tipo de cierre. El valor devuelto por esta función de conversión será la dirección de una función que, cuando se invoca, tiene el mismo efecto que invocar al operador de llamada de función del tipo de cierre.

La consecuencia de este pasaje final es que, si utilizó una conversión, podría asignar LAMBDA a pFptr .

 #include  #include  #define LAMBDA [] (int i)->long { return 0l; } int main () { long (*pFptr)(int) = LAMBDA; // ok auto pAuto = LAMBDA; // ok std::cout< 

Los tipos de funciones son de hecho iguales, pero el lambda introduce un nuevo tipo (como un funtor).

Una solución práctica de ¿Cómo puedo almacenar un objeto boost :: bind como un miembro de la clase? , pruebe boost::function o std::function .

También debe tener en cuenta que lambda es convertible a puntero de función. Sin embargo, typeid <> devuelve un objeto no trivial que debe diferir de lambda en puntero de función genérico. Entonces la prueba para typeid <> no es una suposición válida. En general, C ++ 11 no quiere que nos preocupemos por la especificación de tipo, todo lo que importa si un tipo determinado es convertible a un tipo de destino.