c++ - examples - ¿Cómo crear una variada lambda genérica?
lambda examples c++ (2)
No estoy seguro de cuál es su intención, pero en lugar de almacenarlo en una std::function
, puede usar la lambda para capturar los parámetros. Este es un ejemplo discutido en la lista de correo de impulso. Se usa en la implementación boost :: hana
auto list = [](auto ...xs) {
return [=](auto access) { return access(xs...); };
};
auto head = [](auto xs) {
return xs([](auto first, auto ...rest) { return first; });
};
auto tail = [](auto xs) {
return xs([](auto first, auto ...rest) { return list(rest...); });
};
auto length = [](auto xs) {
return xs([](auto ...z) { return sizeof...(z); });
};
// etc...
// then use it like
auto three = length(list(1, ''2'', "3"));
Desde C ++ 14 podemos usar lambdas genéricos:
auto generic_lambda = [] (auto param) {};
Esto básicamente significa que su operador de llamada está modelado basado en los parámetros marcados como automáticos.
La pregunta es cómo crear una lambda que pueda aceptar un número variado de parámetros de manera similar a cómo funcionaría una plantilla de función variadica. Si esto no es posible, ¿qué es lo más cercano que se podría usar de la misma manera? ¿Cómo lo almacenarías? ¿Es posible en una std::function
?
Sintaxis
¿Cómo se crea una variada lambda genérica?
Puede crear un lambda genérico variadic con la siguiente sintaxis:
auto variadic_generic_lambda = [] (auto... param) {};
Básicamente, solo agrega ...
entre auto
(posiblemente ref calificado) y su nombre de paquete de parámetros.
Por lo tanto, típicamente el uso de referencias universales daría:
auto variadic_generic_lambda = [] (auto&&... param) {};
Uso
¿Cómo se usan los parámetros?
Debe considerar que el parámetro genérico variadic tiene un tipo de paquete de parámetros de plantilla, porque es el caso. Esto más o menos implica que la mayoría, si no todo, el uso de esos parámetros requerirá plantillas de una forma u otra.
Aquí está un ejemplo típico:
#include <iostream>
void print(void)
{
}
template <typename First, typename ...Rest>
void print(const First& first, Rest&&... Args)
{
std::cout << first << std::endl;
print(Args...);
}
int main(void)
{
auto variadic_generic_lambda = [] (auto... param)
{
print(param...);
};
variadic_generic_lambda(42, "lol", 4.3);
}
Almacenamiento
¿Cómo se almacena una variada lambda genérica?
Puede usar auto
para almacenar un lambda en una variable de su propio tipo, o puede almacenarlo en una std::function
pero solo podrá llamarlo con la firma fija que le dio a esa std::function
auto variadic_generic_lambda = [] (auto... param) {};
std::function<void(int, int)> func = variadic_generic_lambda;
func(42, 42); // Compiles
func("lol"); // Doesn''t compile
¿Qué pasa con las colecciones de variantes genéricas de lambdas?
Como cada lambda tiene un tipo diferente, no puede almacenar su tipo directo en los contenedores homogéneos habituales de la STL. La forma en que se hace con lambdas no genéricas es almacenarlas en una std::function
correspondiente que tendrá una llamada de firma fija y que no restringirá nada ya que su lambda no es genérica en primer lugar y solo puede invocarse camino:
auto non_generic_lambda_1 = [] (int, char) {};
auto non_generic_lambda_2 = [] (int, char) {};
std::vector<std::function<void(int, char)>> vec;
vec.push_back(non_generic_lambda_1);
vec.push_back(non_generic_lambda_2);
Como se explica en la primera parte de esta sección de almacenamiento , si puede restringirse a una firma de llamada fija determinada, entonces puede hacer lo mismo con varias lambdas genéricas.
Si no puede necesitará algún tipo de contenedor heterogéneo como:
-
std::vector<boost::variant>
-
std::vector<boost::any>
-
boost::fusion::vector
Vea esta pregunta para un ejemplo de contenedor heterogéneo.
Qué más ?
Para obtener más información general sobre lambdas y para obtener más información sobre los miembros generados y cómo utilizar los parámetros dentro de la lambda, consulte:
- http://en.cppreference.com/w/cpp/language/lambda
- ¿Cómo funciona lambda genérico en C ++ 14?
- ¿Cómo llamar a una función en todos los argumentos de la plantilla variadic?
- ¿Cuál es la forma más fácil de imprimir un paquete de parámetros variados usando std :: ostream?