Me pregunto si es posible escribir una función que devuelva una función lambda en C ++ 11. Por supuesto, un problema es cómo declarar dicha función. Cada lambda tiene un tipo, pero ese tipo no se puede expresar en C ++. No creo que esto funcione:
auto retFun() -> decltype ([](int x) -> int)
{
return [](int x) { return x; }
}
Ni esto:
int(int) retFun();
No tengo conocimiento de ninguna conversión automática de lambdas a, digamos, punteros a funciones, o algo así. ¿La única solución es hacer a mano un objeto de función y devolverlo?
decltype
no es la misma que en el cuerpo de la función y, por lo tanto, tiene un tipo diferente (incluso si incluyó la declaración de retorno)decltype([](){})
osizeof([]() {})
está mal formado, no importa dónde lo escriba.Respuestas:
No necesita un objeto de función hecho a mano, solo use
std::function
, al que las funciones lambda son convertibles:Este ejemplo devuelve la función de identidad entera:
std::function<int (int)> retFun() { return [](int x) { return x; }; }
fuente
std::function
.std::function
emplea el borrado de tipos, lo que puede significar el costo de realizar una llamada de función virtual al llamar astd::function
. Algo a tener en cuenta si la función devuelta se utilizará en un bucle interno estrecho u otro contexto en el que la leve ineficiencia importa.Para este simple ejemplo, no es necesario
std::function
.Del estándar §5.1.2 / 6:
Debido a que su función no tiene una captura, significa que la lambda se puede convertir en un puntero a una función de tipo
int (*)(int)
:typedef int (*identity_t)(int); // works with gcc identity_t retFun() { return [](int x) { return x; }; }
Ese es mi entendimiento, corrígeme si me equivoco.
fuente
Puede devolver la función lambda desde otra función lambda, ya que no debe especificar explícitamente el tipo de retorno de la función lambda. Simplemente escriba algo así en el alcance global:
auto retFun = []() { return [](int x) {return x;}; };
fuente
Aunque la pregunta se refiere específicamente a C ++ 11, por el bien de otros que se topan con esto y tienen acceso a un compilador de C ++ 14, C ++ 14 ahora permite tipos de retorno deducidos para funciones ordinarias. Por lo tanto, el ejemplo de la pregunta se puede ajustar para que funcione como se desee simplemente soltando la
-> decltype
cláusula ... después de la lista de parámetros de la función:auto retFun() { return [](int x) { return x; } }
Sin embargo, tenga en cuenta que esto no funcionará si
return <lambda>;
aparece más de uno en la función. Esto se debe a que una restricción en la deducción del tipo de retorno es que todas las declaraciones de retorno deben devolver expresiones del mismo tipo, pero el compilador le da a cada objeto lambda su propio tipo único, por lo que lasreturn <lambda>;
expresiones tendrán un tipo diferente.fuente
auto retFun() { return [](auto const& x) { return x; }; }
Deberías escribir así:
auto returnFunction = [](int x){ return [&x](){ return x; }(); };
para obtener su devolución como función, y utilícela como:
int val = returnFunction(someNumber);
fuente
Si no tiene c ++ 11 y está ejecutando su código c ++ en microcontroladores, por ejemplo. Puede devolver un puntero vacío y luego realizar un molde.
void* functionThatReturnsLambda() { void(*someMethod)(); // your lambda someMethod = []() { // code of lambda }; return someMethod; } int main(int argc, char* argv[]) { void* myLambdaRaw = functionThatReturnsLambda(); // cast it auto myLambda = (void(*)())myLambdaRaw; // execute lambda myLambda(); }
fuente