Lambda an Funktion übergeben



  • Hi Leute,

    ich fange gerade an, C++0x zu verstehen. Nun versuche ich, eine Funktion zu schreiben, an die ich per Parameter eine Lambda Expression übergeben kann.

    Wie muss also der Funktionskopf aussehen, damit ich im Aufruf eine Lambda Expression in die Parameterliste eintragen kann?

    Danke!

    Grüße,
    Hendrik



  • ha^^

    dafür würd ich erstmal gern wissen was lambda funktionen sind und wofür sie da sind... 😉



  • Unbenannte Funktionen, die als Parameter benutzt werden koennen. http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions



  • SeveQ schrieb:

    ich fange gerade an, C++0x zu verstehen.

    Na dann fang doch gleich schonmal mit dem neuen Namen an: C++11 bzw C++2011. 🙂

    SeveQ schrieb:

    Nun versuche ich, eine Funktion zu schreiben, an die ich per Parameter eine Lambda Expression übergeben kann.

    Wie muss also der Funktionskopf aussehen, damit ich im Aufruf eine Lambda Expression in die Parameterliste eintragen kann?

    Ein Lambda-Ausdruck liefert ein "Funktions-Objekt" eines einzigartigen Typs (jeder Lambda-Ausdruck hat seinen eigenen Typ!), der keinen Namen hat. Ein "Funktions-Objekt" ist ein Objekt eines Typs, für den der Funktions-Aufruf-Operator definiert ist. Da so ein Typ keinen Namen hat, kannst Du den natürlich auch nicht direkt in einer Funktionsdeklaration verwendet.

    Möglichkeit 1: Einen Wrapper verwenden

    void foo(function<void()> f) {
      f();
    }
    
    int main() {
      foo([]{
        cout<<"Hello!"<<endl;
      });
    }
    

    Möglichkeit 2: Aus der Funktion ein Template machen:

    template<class FunObjType>
    void foo(FunObjType f) {
      f();
    }
    
    int main() {
      foo([]{
        cout<<"Hello!"<<endl;
      });
    }
    

    wobei das function<>-Template aus dem std-Namensraum kommt und über den <functional>-Header verfügbar sein müsste. Stimmt die Signatur überein, kann ein Funktionsobjekt zu einem function<?>-Objekt implizit konvertiert werden. Hier ist aber mit etwas Overhead zu rechnen.

    Lokal halten lässt sich ein Lambda-Objekt auch mit auto:

    int main() {
      auto lamobj = []{
        cout<<"Hello!"<<endl;
      };
      foo(lamobj);
    }
    


  • Es gibt noch zwei eine weitere Möglichkeiten:

    1. Funktionszeiger. Jede Lambda-Funktion lässt sich laut Standard in einen Funktionszeiger der entsprechenden Signatur konvertieren.

    2. decltype

    [s]void f(decltype([](){return 42;}) x);[/s]
    

    Ein bisschen witzlos, weil man nur genau diese eine Lambda-Funktion übergeben kann, der Vollständigkeit wegen wollte ich es aber erwähnen.



  • ipsec schrieb:

    1. Funktionszeiger. Jede Lambda-Funktion lässt sich laut Standard in einen Funktionszeiger der entsprechenden Signatur konvertieren.

    Also das halte ich einfach mal für falsch. Ich kann mich hier schwach an eine Diskussion erinnern, bei der schließlich herausgekommen ist, dass dies nur für eine void(*)() gilt, oder so ähnlich.



  • 314159265358979 schrieb:

    ipsec schrieb:

    1. Funktionszeiger. Jede Lambda-Funktion lässt sich laut Standard in einen Funktionszeiger der entsprechenden Signatur konvertieren.

    Also das halte ich einfach mal für falsch. Ich kann mich hier schwach an eine Diskussion erinnern, bei der schließlich herausgekommen ist, dass dies nur für eine void(*)() gilt, oder so ähnlich.

    Zum Glück ist der Draft frei verfügbar: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3290.pdf

    5.1.2.6 schrieb:

    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.

    Also bei jeder Lambda mit leerer Capture-Clause.
    Nebenbei steht etwas weiter oben, dass meine Variante mit decltype doch nicht geht, da der Typ der Lambda-Funktion auf den kleinsten umgebenden Scope beschränkt ist.



  • Achja richtig, ohne Capturing, das wars.


Anmelden zum Antworten