boost signals & Argumentliste
-
Moin,
ich schreibe momentan eine Wrapperklasse für die Signals aus der Boost-Bibliothek und habe ein Problem damit, für den Aufruf der Slots die richtige Anzahl der Parameter für meine Wrappermethode zu setzen.
Beispiel für die Nutzung der signals:
struct A{ void operator()(int,float){ //do something; } }a; boost::signal<void (int,float)> s; s.connect(a); s(4,4.5); // Aufruf der verbundenen SlotsNun angenommen, ich wollte den Aufruf des ()-Operators der Signal-Klasse durch eine Methode - nennen wir sie mal "send" - meiner Klasse "wrappen"; wie stelle ich es an, dass send die gleichen Parameter annimmt, wie der ()-operator?
Ich habe zuvor schonmal kurz in die Signals-Doku geschaut und folgendes gefunden:
// Wir sind in der signal-Klasse // static constants static const int arity = N; // The number of arguments taken by the signal. // member classes/structs/unions template<unsigned n> class arg { public: // types typedef Tn type; // The type of the signal's (n+1)th argument };Irgendwie baut die signal-Klasse die Funktionssignatur also schon auseinander und stellt die Argumenttypen über
boost::signal<void (int,float)>::arg<0> // int boost::signal<void (int,float)>::arg<1> // floatnach außen hin zur Verfügung.
Ich weiß jetzt nur nicht, wie ich dies dazu nutzen kann, meiner Methode send die gleiche Argumentliste zur Verfügung zu stellen, wie dem ()-operator. Geht das und wenn ja, wie stelle ich das an?
-
Ich habe das Problem nicht verstanden. Hast Du schon irgendwo irgendwas von Deiner Wrapper-Klasse gezeigt?
-
Hast Du schon irgendwo irgendwas von Deiner Wrapper-Klasse gezeigt?
Dies sollte dem ungefährem Aufbau entsprechen:
template<typename signature> class A{ private: boost::signal<signature> s; public: void send(){ // Hier steckt das Problem s(); } // andere Methoden, z.B. die für das connecten der Slots }; A<void (int)> a; // send benötigt int als Parameter A<void (float, bool)> b; // send benötigt float und bool als ParameterWie bereits oben beschrieben, muss send die gleichen Parametertypen akzeptieren wie s(), um diese entsprechend forwarden zu können. Da die Signals-Klasse die übergebene Signatur bereits zerlegt und über
boost::signal<void (int,float)>::arg<0> // int boost::signal<void (int,float)>::arg<1> // float boost::signal<void (int,float)>::arity // 2 (Parameter)Informationen über Argumenttypen und Argumentanzahl zur Verfügung stellt, dachte ich, ich könnte diese Informationen nutzen, um mir gleich eine passende Argumentliste für send zu bauen. Geht das und wenn ja wie?
-
Stichwort Spezialisierung:
template<typename FunSig> class foo; template<typename Ret, typename Arg> class foo<Ret(Arg)> { ... boost::signal<Ret(Arg)> s; ... Ret send(Arg a) const { return s(a); } ... };In C++0x eher so:
template<typename FunSig> class foo; template<typename Ret, typename ... Args> class foo<Ret(Arg)> { ... boost::signal<Ret(Args...)> s; ... Ret send(Args ... args) const { return s(std::forward<Args>(args)...); } ... };
-
Upps, es muss natürlich im letzten Beispiel
class foo<Ret(Args...)>stattfoo<Ret(Arg)>heißen.