2012-09-13 7 views
6

sagen, dass ich diese drei verschiedene Funktionen haben, die ich will kann Punkt:Verwendung std :: Funktion als Delegierter in C++ 11

float test1(int a, int b) { 
    return 7.0f; 
} 

struct TestClass { 
    float test2(int a, int b) { 
     return 5.0f; 
    } 
}; 

struct TestClass2 { 
    float test3(int a, int b) { 
     return 3.0f; 
    } 
}; 

Beachten Sie, wie alle drei die gleichen Argumente verwenden und Wert zurück. Ich möchte abstrahieren, ob es eine Mitgliedsfunktion ist und zu welcher Klasse es gehörte. Ich möchte einen Delegattyp, der sich nur auf eine dieser drei Funktionen beziehen kann, abhängig davon, wie er initialisiert wurde.

Hier ist mein erster Versuch:

typedef std::function<float(int, int)> MyDelegate; // is this right? 

int main() { 
    TestClass obj; 
    TestClass2 obj2; 

    MyDelegate a = test1; 
    MyDelegate b = std::bind(std::mem_fn(&TestClass::test2), obj); // is this right? 
    MyDelegate c = std::bind(std::mem_fn(&TestClass2::test3), obj2); // is this right? 

    return 0; 
} 

Die Idee ist, ich mag auch speichere den ‚diesen‘ Zeiger in zu dem Wrapper. Auf diese Weise ist es wie ein voll funktionsfähiger Delegat. Zum Beispiel sollte das Aufrufen von 'b (x, y)' wie das Aufrufen von obj.test2(x, y) sein.

Ich kann es nicht einmal kompilieren lassen, ich bin wahrscheinlich nicht ganz dabei. Ich bin etwas neu in diesen Bibliotheken und die Fehler in VS2012 sind katastrophal nicht hilfreich. Jede Hilfe wäre willkommen.

+0

mögliche Duplikate von [C++ 11 style Callbacks?] (Http://StackOverflow.com/questions/12338695/c11-styled-callbacks) – Klaim

Antwort

9

Sie müssen std::bind mitteilen, was mit den anderen Funktionsparametern zu tun ist. Um den Anruf b(x, y) Delegierten x und y zu den beiden ursprünglichen Funktionsparameter Sie Platzhalter verwenden vom std::placeholders Namespace vornehmen müssen:

std::bind(&TestClass::test2, obj, std::placeholders::_1, std::placeholders::_2); 

Und es gibt auch keine Notwendigkeit für std::mem_fn (es funktioniert, obwohl), da std::bind behandelt Member-Funktionen bereits korrekt (das implizite Argument this ist ein explizites erstes Argument, wie std::mem_fn tut).

3

Sie müssen zwei Argumente zur Verfügung zu stellen, um std :: bind oder bieten Platzhalter sie später zur Verfügung zu stellen :

std::function<float(int, int)> c = std::bind(&TestClass2::test3, obj2, 1, 2); 
c(); //returns result 

ODER

std::function<float(int, int)> c = std::bind(&TestClass2::test3, obj2, std::placeholders::_1, std::placeholders::_2); 
c(1, 2); //returns result 

Mehr Informationen über std :: bind here ist.

2

mit Visual C++ Compiler (CTP 2012) i ausspioniert, wie sie es taten std :: Funktion und ausgeliefert meine eigene Lösung Mitgliederfunktionen

Nutzung sieht aus wie zu handhaben: http://ideone.com/v5zfDn

class Window 
{ 
public: 
    void Show(int number) const 
    { 
     //... 
    } 

    void ShowDynamic(int number) volatile 
    { 
     //... 
    } 
}; 

void ShowWindows(int param) 
{ 
    //... 
} 

int main() 
{ 
    Window window; 

    typedef mezutils::Delegate< void(int) > Notifier; 
    Notifier notifier; 

    notifier = &ShowWindows; 
    notifier(0); 

    notifier = Notifier(&window, &Window::Show); 
    notifier(1); 

    notifier = [](int x) { /*...*/ }; 
    notifier(2); 

    void (*funpc)(int) = func; 
    notifier = funpc; 
    notifier(3); 

    notifier = [](int arg) { printf("asd %d\r\n",arg); }; 
    notifier(4); 
    return 0; 
} 

Delegierten Klasse Aussehen wie: http://ideone.com/DebQgR

natürlich ist es ein Prototyp für Spaß gemacht, aber Ich mag es, weil es klar ist,

Verwandte Themen