std::function und member function



  • hallo leute

    wie stelle ich es an das ich einer std::function eine member function zuweisen kann ?
    moechte folgendes erreichen:

    using my_function = std::function<void(int, int)>;
    
    struct test
    {
       void func(int, int)
       {
          MessageBoxA(ß, "aufruf", "message", MB_OK);
       }
    };
    
    int main(void)
    {
       test tt;
       my_function func = ... // tja was nun. dachte da an std::bind(&test::func, &tt) geht aber nicht
       func(0,0);
    }
    

    wie geht das richtig ?

    Meep Meep


  • Mod

    Selbstverständlich wird bind nicht funktionieren, wenn du nicht entsprechende placeholder mitgibst:

    my_function func = std::bind(&test::func, &tt, std::placeholders::_1, std::placeholders::_2);
    

    Ist jedoch mit Lambdas hübscher, und seit C++14 ganz besonders:

    my_function func = [&] (auto... args) {return tt.func(args...);};
    

    (Oder, wenn man flexibel bleiben möchte,

    my_function func = [&] (auto&&... args) {return tt.func(std::forward<decltype(args)>(args)...);};
    

    )



  • dank dir.

    ich muss mir mal das bind zeugs zu gemuete fuehren.
    da grausts mich jetzt schon 🙂



  • Meep Meep schrieb:

    ich muss mir mal das bind zeugs zu gemuete fuehren.
    da grausts mich jetzt schon 🙂

    Das ist nicht nötig, die zweite Variante ist besser. std::bind ist ein Überbleibsel aus alten Zeiten vor C++11 (wir ignorieren hier jetzt mal, dass es offiziell erst ab C++11 in die Standardbibliothek aufgenommen wurde). Inzwischen geht fast alles besser ohne bind, außer vielleicht in einigen Situationen mit variadic templates.



  • bind brauchen wir dank Lambdas dafür nicht mehr. Es ist zwar kurz aufgeschrieben, kann aber tierisch nerven, wenn man es mit Überladung zu tun hat. Überlädst Du tt::func , musst du nämlich den Typ von &tt::func explizit erwähnen, damit der Compiler weiß, welches func Du meinst. Außerdem ist ein großer Nachteil von std::bind(&tt::func,...) , dass die Information, welche Funktion ausgeführt werden soll, nicht mehr im Typ des bind-Ausdrucks vorhanden ist. Es ist ja nur ein Funktionszeiger. Du tust Dir damit keinen Gefallen, wenn Du so etwas in ein std::function<void(int,int)> reinstecken willst. Du hättest dann, wenn du das function -Objekt benutzt, unnötig viele "Funktionszeigersprünge" dabei.

    Mit nicht-generischen Lambdas (gibt es auch ab C++11), sähe das so aus:

    my_function func = [&tt](int a, int b){ tt.func(a, b); };
    

    Apropos Funktionszeiger: Die Programmiersprache Rust arbeitet da übrigens etwas anders. Dort ist der Typ des Äquivalents zu &tt::func einzigartig und bezieht sich auf die Funktion, was Inlining immer noch sehr einfach für den Compiler macht. Da braucht man keine Lambdas, nur um Inlining zu fördern.


Log in to reply