Estaba tratando de crear un vector de lambda, pero fallé:
auto ignore = [&]() { return 10; }; //1
std::vector<decltype(ignore)> v; //2
v.push_back([&]() { return 100; }); //3
Hasta la línea 2, se compila bien . Pero la línea # 3 da error de compilación :
error: no hay función coincidente para llamar a 'std :: vector <main () :: <lambda () >> :: push_back (main () :: <lambda ()>)'
No quiero un vector de punteros de función o un vector de objetos de función. Sin embargo, el vector de objetos de función que encapsulan expresiones lambda reales funcionaría para mí. es posible?
Respuestas:
Cada lambda tiene un tipo diferente, incluso si tienen la misma firma. Debe usar un contenedor de encapsulación en tiempo de ejecución, por ejemplo,
std::function
si desea hacer algo así.p.ej:
std::vector<std::function<int()>> functors; functors.push_back([&] { return 100; }); functors.push_back([&] { return 10; });
fuente
std::function<int()
, ¿podría usar diferentes prototipos de funciones?vector
almacenamiento tantostd::function
ystd::string
?' Y la respuesta es la misma: no, porque ese no es el uso previsto. Puede usar una clase de estilo 'variante' para realizar un borrado de tipo suficiente para poner cosas dispares en un contenedor, al tiempo que incluye un método para que un usuario determine el tipo 'real' y, por lo tanto, elija qué hacer con (por ejemplo, cómo llamar) cada elemento ... pero de nuevo, ¿por qué ir tan lejos? ¿Existe alguna justificación real?Todas las expresiones lambda tienen un tipo diferente, incluso si son idénticas carácter por carácter . Estás empujando una lambda de un tipo diferente (porque es otra expresión) en el vector, y eso obviamente no funcionará.
Una solución es hacer un vector de en su
std::function<int()>
lugar.auto ignore = [&]() { return 10; }; std::vector<std::function<int()>> v; v.push_back(ignore); v.push_back([&]() { return 100; });
En otra nota, no es una buena idea usarlo
[&]
cuando no está capturando nada.fuente
()
lambdas que no tengan argumentos.Si bien lo que otros han dicho es relevante, aún es posible declarar y usar un vector de lambda, aunque no es muy útil:
auto lambda = [] { return 10; }; std::vector<decltype(lambda)> vec; vec.push_back(lambda);
Por lo tanto, puede almacenar cualquier cantidad de lambdas allí, ¡siempre que sea una copia / movimiento de
lambda
!fuente
Si su lambda no tiene estado, es decir,
[](...){...}
C ++ 11 permite que se degrade en un puntero de función. En teoría, un compilador compatible con C ++ 11 podría compilar esto:auto ignore = []() { return 10; }; //1 note misssing & in []! std::vector<int (*)()> v; //2 v.push_back([]() { return 100; }); //3
fuente
auto ignore = *[] { return 10; };
haríaignore
unint(*)()
.explicit
, eliminar la referencia a una expresión lambda es válido y eliminar la referencia del puntero resultante de la conversión. Luego, el uso deauto
esa referencia vuelve a convertirse en un puntero. (Usandoauto&
oauto&&
habría mantenido la referencia.)()
intencional o accidental?Puede usar una función de generación de lambda (actualizada con la corrección sugerida por Nawaz):
#include <vector> #include <iostream> int main() { auto lambda_gen = [] (int i) {return [i](int x){ return i*x;};} ; using my_lambda = decltype(lambda_gen(1)); std::vector<my_lambda> vec; for(int i = 0; i < 10; i++) vec.push_back(lambda_gen(i)); int i = 0; for (auto& lambda : vec){ std::cout << lambda(i) << std::endl; i++; } }
Pero creo que básicamente hiciste tu propia clase en este momento. De lo contrario, si las lambdas tienen caputres / args completamente diferentes, etc., probablemente tenga que usar una tupla.
fuente
lambda_gen
que a su vez puede ser una lambda. Sin embargo,auto a = lambda_gen(1);
realiza una llamada innecesaria, que se puede evitar si escribimos estodecltype(lambda_gen(1))
.decltype
está evaluado , por lo que la llamada no se realiza realmente. Es el mismo caso consizeof
también. Además, este código no funcionará en C ++ 11 incluso si agrega un tipo de retorno final.Cada lambda es de un tipo diferente. Debe utilizar en
std::tuple
lugar destd::vector
.fuente