Ich spiele mit den funktionalen Funktionen von C++ 11 herum. Eine Sache, die ich seltsam finde, ist, dass der Typ einer Lambda-Funktion tatsächlich KEINE Funktion <> Typ ist. Lambda's scheinen mit dem Typ-Inferenz-Mechanismus nicht besonders gut zu spielen.Warum haben Lambda-Funktionen in C++ 11 keine Funktion <> Typen?
Attached ist ein kleines Beispiel, in dem ich getestet habe, wie man die zwei Argumente einer Funktion zum Hinzufügen von zwei Ganzzahlen umkehrt. (Der verwendete Compiler war gcc 4.6.2 unter MinGW.) Im Beispiel wurde der Typ für addInt_f
explizit mit der Funktion <> definiert, während addInt_l
ein Lambda ist, dessen Typ typeninferenziert ist mit .
Wenn ich den Code kompiliert, kann die flip
Funktion explizit typisierte Version von addInt akzeptieren, aber die Lambda-Version nicht, einen Fehler zu geben zu sagen, dass, testCppBind.cpp:15:27: error: no matching function for call to 'flip(<lambda(int, int)>&)'
Die nächsten paar Zeilen zeigen, dass die Lambda-Version (sowie eine 'rohe' Version) kann akzeptiert werden, wenn sie explizit in die entsprechende Funktion <> type umgewandelt wird.
Also meine Fragen sind:
Warum ist es, dass eine Lambda-Funktion nicht in erster Linie
function<>
Typ hat? In dem kleinen Beispiel, warum nichtaddInt_l
function<int (int,int)>
als der Typ anstelle eines anderen,lambda
Typ haben? Was ist der Unterschied zwischen einer Funktion/einem funktionalen Objekt und einem Lambda?Wenn es einen grundlegenden Grund gibt, dass diese zwei unterschiedlich sein müssen. Ich habe gehört, dass Lambdas in
function<>
konvertiert werden können, aber sie sind anders. Ist das ein Design-Problem/ein Fehler von C++ 11, ein Implementierungsproblem oder gibt es einen Vorteil darin, die beiden so zu unterscheiden, wie es ist? Es scheint, dass die Typensignatur vonaddInt_l
allein genügend Informationen über den Parameter und die Rückgabetypen der Funktion bereitgestellt hat.Gibt es eine Möglichkeit, das Lambda zu schreiben, damit das oben erwähnte explizite Typ-Casting vermieden werden kann?
Vielen Dank im Voraus.
//-- 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;
}
Sie sollten nicht 'std :: function' Argumente nehmen, hauptsächlich, weil es den Typabzug hemmt (was Ihr Problem hier ist). –
Verwandt: [C++ 11 leitet Typ nicht ab, wenn std :: function oder Lambda-Funktionen beteiligt sind] (http://stackoverflow.com/q/9998402/487781) – hardmath
Lambdas werden in anonyme Functors (oder Funktionen, wenn sie Erfasse keine Umgebung). Die Umwandlung in std :: function würde eine starke Kopplung zwischen der Sprache und der Bibliothek einführen und wäre daher eine sehr schlechte Idee. – MFH