Lambda Expression

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
gdsWizard
Establishment
Beiträge: 237
Registriert: 04.02.2005, 09:12
Benutzertext: www.gamedevstudio.com
Echter Name: Thomas Mittelsdorf
Wohnort: Meiningen
Kontaktdaten:

Lambda Expression

Beitrag von gdsWizard »

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.
Benutzeravatar
B.G.Michi
Establishment
Beiträge: 163
Registriert: 07.03.2006, 20:38
Alter Benutzername: B.G.Michi
Kontaktdaten:

Re: Lambda Expression

Beitrag von B.G.Michi »

Das sollte eigentlich funktionieren, aber nur so lange du keine (lokalen?) Variablen capturest also kein [&] oder [=] als Lambda. Welchen Compiler verwendest du?
gdsWizard
Establishment
Beiträge: 237
Registriert: 04.02.2005, 09:12
Benutzertext: www.gamedevstudio.com
Echter Name: Thomas Mittelsdorf
Wohnort: Meiningen
Kontaktdaten:

Re: Lambda Expression

Beitrag von gdsWizard »

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 ?
Benutzeravatar
B.G.Michi
Establishment
Beiträge: 163
Registriert: 07.03.2006, 20:38
Alter Benutzername: B.G.Michi
Kontaktdaten:

Re: Lambda Expression

Beitrag von B.G.Michi »

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.
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.

ansonsten versuch mal mit "void FuncMitLambdaAufruf( auto (*pMylambda)(int n)->bool );". Also als Funktionspointer.
gdsWizard
Establishment
Beiträge: 237
Registriert: 04.02.2005, 09:12
Benutzertext: www.gamedevstudio.com
Echter Name: Thomas Mittelsdorf
Wohnort: Meiningen
Kontaktdaten:

Re: Lambda Expression

Beitrag von gdsWizard »

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
Benutzeravatar
dot
Establishment
Beiträge: 1746
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Lambda Expression

Beitrag von dot »

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.
gdsWizard
Establishment
Beiträge: 237
Registriert: 04.02.2005, 09:12
Benutzertext: www.gamedevstudio.com
Echter Name: Thomas Mittelsdorf
Wohnort: Meiningen
Kontaktdaten:

Re: Lambda Expression

Beitrag von gdsWizard »

Ob ich mir das neue VS 2012 kaufe steht noch in den Sternen. Danke für die Info.
Benutzeravatar
dot
Establishment
Beiträge: 1746
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Lambda Expression

Beitrag von dot »

Gibt's auch als Express Edition... ;)
Benutzeravatar
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

Beitrag von Schrompf »

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.
Benutzeravatar
dot
Establishment
Beiträge: 1746
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Lambda Expression

Beitrag von dot »

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.
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:
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.
Nur MSVC 10 unterstützt das noch nicht, da das erst später in den Standard aufgenommen wurde.
Benutzeravatar
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

Beitrag von Schrompf »

Ah, das erklärt es. Danke.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
gdsWizard
Establishment
Beiträge: 237
Registriert: 04.02.2005, 09:12
Benutzertext: www.gamedevstudio.com
Echter Name: Thomas Mittelsdorf
Wohnort: Meiningen
Kontaktdaten:

Re: Lambda Expression

Beitrag von gdsWizard »

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;
}
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Lambda Expression

Beitrag von CodingCat »

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.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Antworten