Tenía la percepción de que el tipo de lambda es un puntero de función. Cuando realicé la siguiente prueba, encontré que estaba equivocado ( 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 !
}
¿Al código anterior le falta algún punto? Si no es así, ¿cuál es la typeof
expresión lambda cuando se deduce con la auto
palabra clave?
Respuestas:
El tipo de una expresión lambda no está especificado.
Pero generalmente son meros azúcares sintácticos para los functors. Una lambda se traduce directamente en un functor. Todo lo que está dentro
[]
se convierte en parámetros de constructor y miembros del objeto functor, y los parámetros dentro()
se convierten en parámetros para el functoroperator()
.Una lambda que no captura variables (nada dentro de la
[]
's) se puede convertir en un puntero de función (MSVC2010 no admite esto, si ese es su compilador, pero esta conversión es parte del estándar).Pero el tipo real de lambda no es un puntero de función. Es un tipo de functor no especificado.
fuente
operator()
básicamente stackoverflow.com/questions/356950/c-functors-and-their-usesEs una estructura única sin nombre que sobrecarga el operador de llamada de función. Cada instancia de una lambda introduce un nuevo tipo.
En el caso especial de una lambda que no captura, la estructura además tiene una conversión implícita a un puntero de función.
fuente
type_info::name()
está definido por la implementación, por lo que puede devolver cualquier cosa. En la práctica, el compilador nombrará el tipo por el bien del enlazador.La cláusula continúa para enumerar las diferentes propiedades de este tipo. Aquí hay algunos puntos destacados:
La consecuencia de este pasaje final es que, si se ha utilizado una conversión, que sería capaz de asignar
LAMBDA
apFptr
.fuente
Los tipos de funciones son de hecho iguales, pero la lambda introduce un nuevo tipo (como un functor).
fuente
__PRETTY_FUNCTION__
, como entemplate<class T> const char* pretty(T && t) { return __PRETTY_FUNCTION__; }
, y me quito el extra si comienza a llenarse. Prefiero ver los pasos que se muestran en la sustitución de plantillas. Si falta__PRETTY_FUNCTION__
, existen alternativas para MSVC, etc., pero los resultados siempre dependen del compilador por la misma razón por la que CXXABI es necesario.También debe tener en cuenta que lambda es convertible a puntero de función. Sin embargo, typeid <> devuelve un objeto no trvial que debe diferir de lambda a 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 es si un tipo dado es convertible a un tipo de destino.
fuente
Una solución práctica de ¿Cómo puedo almacenar un objeto boost :: bind como miembro de la clase? , prueba
boost::function<void(int)>
ostd::function<void(int)>
.fuente