Lambda Expression
-
- Establishment
- Beiträge: 237
- Registriert: 04.02.2005, 09:12
- Benutzertext: www.gamedevstudio.com
- Echter Name: Thomas Mittelsdorf
- Wohnort: Meiningen
- Kontaktdaten:
Lambda Expression
Hallo,
ich möchte einen Zeiger auf eine Lambda Funktion an eine Methode weitergeben. Leider kriege ich dies nicht hin. Kann es sein das Lambda Funktionen nur in der Scope Methode aufgerufen werden dürfen in der sie auch definiert sind.
Ich wollte mir Callbacks elegant durch Lambdas ersetzen.
Im Scope wie hier das Funktioniert:
int m = 0;
auto MyLambda1([](int n)->int{return n*n;});
m = MyLambda1(3);
Doch ich möchte einen Zeiger übergeben:
class Test
{
public:
void FuncMitLambdaAufruf( auto Mylambda(int n)->bool );
};
Ich weiss aber nicht wie ich diese Function die ja eine rückrufbare Lambda Funktion aufrufen soll genutzt werden kann oder wie sie declariert werden soll.
Test a;
auto MyLambda2([](int n)->bool { return false; } );
a.FuncMitLambdaAufruf(MyLambda2);
Compiler Meldung ist folgende:
Konvertierung des Parameters 1 von '`anonymous-namespace'::<lambda1>' in 'bool (__cdecl *)(int)' nicht möglich.
Es sieht so aus als wenn der Compiler meinen Lambdaparameter in der Declaration als einfachen Callback erwartet. Ich nehme an das die Declaration in der class nicht als Lambda übergeben werden kann. Oder besser gesagt hier ist wahrscheinlich mein Problem.
Kenn jemand eine Lösung ? Wäre schon schön das zu nutzen, immerhin erhöht es die Übersichtlichkeit.
ich möchte einen Zeiger auf eine Lambda Funktion an eine Methode weitergeben. Leider kriege ich dies nicht hin. Kann es sein das Lambda Funktionen nur in der Scope Methode aufgerufen werden dürfen in der sie auch definiert sind.
Ich wollte mir Callbacks elegant durch Lambdas ersetzen.
Im Scope wie hier das Funktioniert:
int m = 0;
auto MyLambda1([](int n)->int{return n*n;});
m = MyLambda1(3);
Doch ich möchte einen Zeiger übergeben:
class Test
{
public:
void FuncMitLambdaAufruf( auto Mylambda(int n)->bool );
};
Ich weiss aber nicht wie ich diese Function die ja eine rückrufbare Lambda Funktion aufrufen soll genutzt werden kann oder wie sie declariert werden soll.
Test a;
auto MyLambda2([](int n)->bool { return false; } );
a.FuncMitLambdaAufruf(MyLambda2);
Compiler Meldung ist folgende:
Konvertierung des Parameters 1 von '`anonymous-namespace'::<lambda1>' in 'bool (__cdecl *)(int)' nicht möglich.
Es sieht so aus als wenn der Compiler meinen Lambdaparameter in der Declaration als einfachen Callback erwartet. Ich nehme an das die Declaration in der class nicht als Lambda übergeben werden kann. Oder besser gesagt hier ist wahrscheinlich mein Problem.
Kenn jemand eine Lösung ? Wäre schon schön das zu nutzen, immerhin erhöht es die Übersichtlichkeit.
- B.G.Michi
- Establishment
- Beiträge: 163
- Registriert: 07.03.2006, 20:38
- Alter Benutzername: B.G.Michi
- Kontaktdaten:
Re: Lambda Expression
Das sollte eigentlich funktionieren, aber nur so lange du keine (lokalen?) Variablen capturest also kein [&] oder [=] als Lambda. Welchen Compiler verwendest du?
-
- Establishment
- Beiträge: 237
- Registriert: 04.02.2005, 09:12
- Benutzertext: www.gamedevstudio.com
- Echter Name: Thomas Mittelsdorf
- Wohnort: Meiningen
- Kontaktdaten:
Re: Lambda Expression
Ich verwende Visual Studio 2010 Professional. Ich möchte aber auch mit [] Parameter übergeben. Im Beispiel habe ich das weggelassen (der Einfachheit halber). Der Compiler meckert aber auch ohne locale Variablen.
Wie gesagt ich gehe von einer falschen Declaraion in der Class Test aus. Geht es denn bei Dir und wenn ja welchen Compiler verwendest du ?
Wie gesagt ich gehe von einer falschen Declaraion in der Class Test aus. Geht es denn bei Dir und wenn ja welchen Compiler verwendest du ?
- B.G.Michi
- Establishment
- Beiträge: 163
- Registriert: 07.03.2006, 20:38
- Alter Benutzername: B.G.Michi
- Kontaktdaten:
Re: Lambda Expression
denn wenn Variablen gecaptured werden, und du die Lambda-Funktion durch einen einfachen Funktionspointer aufrufen könntest, kennt der Compiler die Variablen nicht mehr (diese können zu diesem Zeitpunkt ja auch schon nicht mehr existieren). Ich meine mich zu erinnern, dass die konvertierung in VC10 noch nicht vollständig funktioniert hat. Habe auch gerade keinen Compiler zur Hand.http://en.wikipedia.org/wiki/Anonymous_function#C.2B.2B hat geschrieben:A lambda function with an empty capture specification ([]) can be implicitly converted into a function pointer with the same type as the lambda was declared with.
ansonsten versuch mal mit "void FuncMitLambdaAufruf( auto (*pMylambda)(int n)->bool );". Also als Funktionspointer.
-
- Establishment
- Beiträge: 237
- Registriert: 04.02.2005, 09:12
- Benutzertext: www.gamedevstudio.com
- Echter Name: Thomas Mittelsdorf
- Wohnort: Meiningen
- Kontaktdaten:
Re: Lambda Expression
Hallo,
danke für deine schnelle Antwort. Das als Zeiger zu machen hatte ich auch schon probiert. Er meckert nicht an der Declaration sondern am Aufruf.
Es sieht so aus als ob die Declaration in der Klasse einfach nur als einfacher Funktionszeiger interpretiert wird und nicht einem Lambda Parameter entspricht.
a.FuncMitLambdaAufruf(&MyLambda2);
VS2010 Error: FuncMitLambdaAufruf': Konvertierung des Parameters 1 von '`anonymous-namespace'::<lambda1> *' in 'bool (__cdecl *)(int)' nicht möglich
a.FuncMitLambdaAufruf(MyLambda2);
VS2010 Error: FuncMitLambdaAufruf': Konvertierung des Parameters 1 von '`anonymous-namespace'::<lambda1>' in 'bool (__cdecl *)(int)' nicht möglich
danke für deine schnelle Antwort. Das als Zeiger zu machen hatte ich auch schon probiert. Er meckert nicht an der Declaration sondern am Aufruf.
Es sieht so aus als ob die Declaration in der Klasse einfach nur als einfacher Funktionszeiger interpretiert wird und nicht einem Lambda Parameter entspricht.
a.FuncMitLambdaAufruf(&MyLambda2);
VS2010 Error: FuncMitLambdaAufruf': Konvertierung des Parameters 1 von '`anonymous-namespace'::<lambda1> *' in 'bool (__cdecl *)(int)' nicht möglich
a.FuncMitLambdaAufruf(MyLambda2);
VS2010 Error: FuncMitLambdaAufruf': Konvertierung des Parameters 1 von '`anonymous-namespace'::<lambda1>' in 'bool (__cdecl *)(int)' nicht möglich
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Lambda Expression
Die Konvertierung eines Lambda ohne Capture in einen Funktionszeiger wird von MSVC 2010 noch nicht unterstützt, das Feature wurde afaik erst später in den Standard aufgenommen. MSVC 2012 unterstützt es.
-
- Establishment
- Beiträge: 237
- Registriert: 04.02.2005, 09:12
- Benutzertext: www.gamedevstudio.com
- Echter Name: Thomas Mittelsdorf
- Wohnort: Meiningen
- Kontaktdaten:
Re: Lambda Expression
Ob ich mir das neue VS 2012 kaufe steht noch in den Sternen. Danke für die Info.
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Lambda Expression
Gibt's auch als Express Edition... ;)
- Schrompf
- Moderator
- Beiträge: 5163
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: Lambda Expression
Nach meinem Verständnis darf das gar nicht funktionieren. Ein Lambda ist ein Funktor, also eine kleine Struktur mit überladenem ()-Operator. Du kannst keinen Zeiger auf eine Struktur in einen Zeiger auf eine Funktion umwandeln.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Lambda Expression
Wenn das Lambda nichts captured, ist sein Closure Type (deine "kleine Struktur") leer. In dem Fall kann das Lambda z.B. über eine statische Methode implementiert werden und daher einen Conversion Operator in einen Function Pointer anbieten. Und genau das ist auch der Fall:Schrompf hat geschrieben:Nach meinem Verständnis darf das gar nicht funktionieren. Ein Lambda ist ein Funktor, also eine kleine Struktur mit überladenem ()-Operator. Du kannst keinen Zeiger auf eine Struktur in einen Zeiger auf eine Funktion umwandeln.
Nur MSVC 10 unterstützt das noch nicht, da das erst später in den Standard aufgenommen wurde.ISO C++ Standard hat geschrieben:The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const
conversion function to pointer to function having the same parameter and return types as the closure type’s
function call operator. The value returned by this conversion function shall be the address of a function
that, when invoked, has the same effect as invoking the closure type’s function call operator.
- Schrompf
- Moderator
- Beiträge: 5163
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: Lambda Expression
Ah, das erklärt es. Danke.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
-
- Establishment
- Beiträge: 237
- Registriert: 04.02.2005, 09:12
- Benutzertext: www.gamedevstudio.com
- Echter Name: Thomas Mittelsdorf
- Wohnort: Meiningen
- Kontaktdaten:
Re: Lambda Expression
und es geht doch:
void s(std::function<void (int)> d)
{
d(1);
}
int _tmain(int argc, _TCHAR* argv[])
{
auto i = [] (int i)
{
std::cout << i << std::endl;
};
s(i);
return 0;
}
void s(std::function<void (int)> d)
{
d(1);
}
int _tmain(int argc, _TCHAR* argv[])
{
auto i = [] (int i)
{
std::cout << i << std::endl;
};
s(i);
return 0;
}
- CodingCat
- Establishment
- Beiträge: 1857
- Registriert: 02.03.2009, 21:25
- Wohnort: Student @ KIT
- Kontaktdaten:
Re: Lambda Expression
Ja, das sollte sogar mit gecaptureten lokalen Variablen funktionen. std::function ist genau dazu da, den vollständigen Typ zu verstecken, damit du auch Funktionen/Lambdas unbekannten Typs weitergeben kannst.
Lambdas mit gecaptureten Variablen haben keinen manuell ableitbaren Typ, deshalb ist die einzige Möglichkeit der Weitergabe, den Compiler den Typ selbst ableiten zu lassen. Das geht über Templates, d.h. in Funktions-Templates könntest du Lambdas sogar direkt entgegennehmen. Aus allen Funktionen, die mit Lambdas arbeiten, Templates zu machen, will man aber auf gar keinen Fall. Glücklicherweise führt std::function genau diese Template-Typ-Deduktion intern durch und versteckt das Ergebnis so, dass du die Funktion auch an Nicht-Templates weitergeben kannst.
Lambdas mit gecaptureten Variablen haben keinen manuell ableitbaren Typ, deshalb ist die einzige Möglichkeit der Weitergabe, den Compiler den Typ selbst ableiten zu lassen. Das geht über Templates, d.h. in Funktions-Templates könntest du Lambdas sogar direkt entgegennehmen. Aus allen Funktionen, die mit Lambdas arbeiten, Templates zu machen, will man aber auf gar keinen Fall. Glücklicherweise führt std::function genau diese Template-Typ-Deduktion intern durch und versteckt das Ergebnis so, dass du die Funktion auch an Nicht-Templates weitergeben kannst.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite