Sto giocando con le funzionalità funzionali di C++ 11. Una cosa che trovo strano è che il tipo di una funzione lambda NON è in realtà una funzione <>. Inoltre, le lambda non sembrano suonare molto bene con il meccanismo di inferenza del tipo.perché le funzioni lambda in C++ 11 non hanno tipi di funzione <>?
In allegato è un piccolo esempio in cui ho provato a capovolgere i due argomenti di una funzione per l'aggiunta di due numeri interi. (Il compilatore che ho usato era gcc 4.6.2 in MinGW.) Nell'esempio, il tipo per addInt_f
è stato definito in modo esplicito utilizzando la funzione <> mentre addInt_l
è un lambda il cui tipo è basato su tipo con auto
.
Quando ho compilato il codice, la funzione flip
può accettare la versione esplicitamente tipo definito di addInt ma non la versione lambda, dando un errore dicendo che, testCppBind.cpp:15:27: error: no matching function for call to 'flip(<lambda(int, int)>&)'
Le prossime righe mostrano che la versione lambda (così come una versione "grezza") può essere accettata se è espressamente trasmesso alla funzione appropriata <> type.
Quindi le mie domande sono:
Perché è che una funzione lambda non hai tipo
function<>
in primo luogo? Nel piccolo esempio, perchénon hafunction<int (int,int)>
come tipo invece di avere un diverso, tipolambda
? Dal punto di vista della programmazione funzionale, qual è la differenza tra una funzione/oggetto funzionale e una lambda?Se c'è una ragione fondamentale per cui questi due devono essere diversi. Ho sentito che i lambda possono essere convertiti in
function<>
ma sono diversi. Si tratta di un problema di progettazione/difetto di C++ 11, un problema di implementazione o c'è un vantaggio nel distinguere i due come sono? Sembra che la firma del tipo diaddInt_l
abbia fornito sufficienti informazioni sul parametro e sui tipi di ritorno della funzione.C'è un modo per scrivere la lambda in modo da evitare il suddetto tipo di casting esplicito?
Grazie in anticipo.
//-- 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;
}
Non dovresti utilizzare argomenti 'std :: function', principalmente perché inibisce la deduzione del tipo (che è il tuo problema qui). –
Correlato: [C++ 11 non deduce il tipo quando sono coinvolte le funzioni std :: function o lambda] (http://stackoverflow.com/q/9998402/487781) – hardmath
Lambdas vengono trasformati in anonimi Functional (o funzioni se non catturare un ambiente). Trasformarli in std :: function avrebbe introdotto un forte accoppiamento tra il linguaggio e la libreria e sarebbe quindi una pessima idea. – MFH