¿Se pueden crear plantillas para las funciones lambda?
En C++ 11, ¿hay alguna manera de crear una plantilla para una función lambda? ¿O es intrínsecamente demasiado específico para utilizarlo como modelo?
Entiendo que puedo definir una clase/functor con plantilla clásica, pero la pregunta es más bien: ¿el lenguaje permite crear plantillas de funciones lambda?
ACTUALIZACIÓN 2018: C++20 vendrá con lambdas conceptualizadas y con plantillas. La característica ya se ha integrado en el borrador estándar.
ACTUALIZACIÓN 2014: C++14 se lanzó este año y ahora proporciona lambdas polimórficas con la misma sintaxis que en este ejemplo. Algunos compiladores importantes ya lo implementan.
Tal como está (en C++ 11), lamentablemente no. Las lambdas polimórficas serían excelentes en términos de flexibilidad y potencia.
La razón original por la que terminaron siendo monomórficos fue por conceptos. Los conceptos dificultaron esta situación de código:
template <Constraint T>
void foo(T x)
{
auto bar = [](auto x){}; // imaginary syntax
}
En una plantilla restringida sólo puedes llamar a otras plantillas restringidas. (De lo contrario, no se podrían verificar las restricciones). ¿Se puede foo
invocar bar(x)
? ¿Qué restricciones tiene lambda (después de todo, su parámetro es solo una plantilla)?
Los conceptos no estaban preparados para abordar este tipo de cosas; requeriría más cosas como late_check
(donde el concepto no se verificaba hasta que se invocaba) y esas cosas. Lo más sencillo era dejarlo todo y ceñirse a lambdas monomórficas.
Sin embargo, con la eliminación de conceptos de C++0x, las lambdas polimórficas vuelven a ser una propuesta simple. Sin embargo, no encuentro ninguna propuesta al respecto. :(
En C++20 esto es posible usando la siguiente sintaxis:
auto lambda = []<typename T>(T t){
// do something
};
Las lambdas de C++ 11 no pueden tener plantillas como se indica en otras respuestas, pero decltype()
parece ayudar cuando se usa una lambda dentro de una clase o función con plantilla.
#include <iostream>
#include <string>
using namespace std;
template<typename T>
void boring_template_fn(T t){
auto identity = [](decltype(t) t){ return t;};
std::cout << identity(t) << std::endl;
}
int main(int argc, char *argv[]) {
std::string s("My string");
boring_template_fn(s);
boring_template_fn(1024);
boring_template_fn(true);
}
Huellas dactilares:
My string
1024
1
Descubrí que esta técnica ayuda cuando se trabaja con código con plantilla, pero me doy cuenta de que aún significa que las lambdas mismas no pueden tener plantilla.
En C++11, las funciones lambda no pueden tener plantillas, pero en la próxima versión del estándar ISO C++ (a menudo llamado C++14), se introducirá esta característica. [Fuente]
Ejemplo de uso:
auto get_container_size = [] (auto container) { return container.size(); };
Tenga en cuenta que, aunque la sintaxis utiliza la palabra clave auto
, la deducción de tipos no utilizará las reglas de auto
deducción de tipos, sino que utilizará las reglas de deducción de argumentos de plantilla. Consulte también la propuesta para expresiones lambda genéricas (y la actualización de esta).