Estoy jugando con las características funcionales de C++ 11. Una cosa que encuentro extraña es que el tipo de una función lambda en realidad NO es una función <> tipo. Además, las lambda no parecen jugar muy bien con el mecanismo de tipografía.¿Por qué las funciones lambda en C++ 11 no tienen función <> tipos?
Adjunto hay un pequeño ejemplo en el que probé volteando los dos argumentos de una función para agregar dos enteros. (El compilador que utilicé fue gcc 4.6.2 en MinGW). En el ejemplo, el tipo para addInt_f
se ha definido explícitamente usando la función <> mientras que addInt_l
es una lambda cuyo tipo está ingresado por tipo con auto
.
Cuando compilado el código, la función flip
puede aceptar la versión explícita tipo definido de addInt pero no la versión lambda, dando un error diciendo que, testCppBind.cpp:15:27: error: no matching function for call to 'flip(<lambda(int, int)>&)'
Las siguientes líneas muestran que la versión lambda (así como también una versión 'en bruto') puede ser aceptado si se emite explícitamente a la función apropiada <> tipo.
Así que mis preguntas son:
Por qué es que una función lambda no tiene un tipo
function<>
en el primer lugar? En el pequeño ejemplo, ¿por quéaddInt_l
no tienefunction<int (int,int)>
como tipo en lugar de tener un tipo diferente,lambda
? Desde la perspectiva de la programación funcional, ¿cuál es la diferencia entre una función/objeto funcional y una lambda?Si hay una razón fundamental para que estos dos tengan que ser diferentes. Escuché que las lambda pueden convertirse a
function<>
pero son diferentes. ¿Es este un problema de diseño/defecto de C++ 11, un problema de implementación o hay un beneficio en distinguir los dos tal como es? Parece que la firma de tipoaddInt_l
sola ha proporcionado suficiente información sobre el parámetro y los tipos de devolución de la función.¿Hay alguna manera de escribir la lambda para evitar el colado explícito de tipos mencionado anteriormente?
Gracias de antemano.
//-- testCppBind.cpp --
#include <functional>
using namespace std;
using namespace std::placeholders;
template <typename T1,typename T2, typename T3>
function<T3 (T2, T1)> flip(function<T3 (T1, T2)> f) { return bind(f,_2,_1);}
function<int (int,int)> addInt_f = [](int a,int b) -> int { return a + b;};
auto addInt_l = [](int a,int b) -> int { return a + b;};
int addInt0(int a, int b) { return a+b;}
int main() {
auto ff = flip(addInt_f); //ok
auto ff1 = flip(addInt_l); //not ok
auto ff2 = flip((function<int (int,int)>)addInt_l); //ok
auto ff3 = flip((function<int (int,int)>)addInt0); //ok
return 0;
}
No debería estar tomando argumentos 'std :: function', principalmente porque inhibe la deducción de tipo (que es su problema aquí). –
Relacionado: [C++ 11 no deduce el tipo cuando están involucradas las funciones std :: function o lambda] (http://stackoverflow.com/q/9998402/487781) – hardmath
Las lambdas se transforman en funtores anónimos (o funciones si no capturar un entorno). Transformarlos en std :: function introduciría un fuerte acoplamiento entre el lenguaje y la biblioteca y, por lo tanto, sería una muy mala idea. – MFH