Funktion mithilfe von Templates zurückgeben
-
gegeben sei:
template <class T, void (T::*method)(int)> void invoke(T* objPtr, int i) { (objPtr->*method)(i); }und
struct Foo { void test(int i) // zu Testzwecken kein const, bitte keine Vorträge diesbezüglich ;) { std::cout << "test(" << i << ')' << std::endl; } };mithilfe von
typedef void (*func)(Foo*, int); int main(void) { Foo bar; func function = &invoke<Foo, &Foo::test>; function(&bar, 10); }erhalte ich die gewünschte Ausgabe ("test(10)")
Jetzt zu meiner eigentlichen Frage, wie kann ich das zurückgeben der invoke-Funktion in eine Funktion verpacken, damit ich einen Funktionsaufruf wie folgenden machen kann?
func function = getFunction(&bar, &Foo::test);meine Idee war
template <class T> func getFunction(T& t, void (T::*function)(int)) { return &invoke<t, function>; }was leider nicht ganz funktioniert. Hat da jemand nen Verbesserungsvorschlag?
Cheers
Cyres
-
C++11 auto std::function std::bind ...
1.) func ist nicht vom Typ F::*method.
2.) gibt es alles schon, std::function mit std::bind ist dein Freund, leider erst ab C++11
-
knivil schrieb:
2.) gibt es alles schon, std::function mit std::bind ist dein Freund, leider erst ab C++11
In boost gibt's das schon für ältere Compiler
-
Ich mag kein boost. Nur manchmal.
-
Ein solches bind gibt's auch schon in tr1, dann hat man's auch offiziell von vielen Compilern unterstützt.
-
knivil schrieb:
1.) func ist nicht vom Typ F::*method.
Das ist gewollt, func soll die Funktion "invoke" speichern. Wiegesagt, ohne "getFunction" geht es ja.
knivil schrieb:
2.) gibt es alles schon, std::function mit std::bind ist dein Freund, leider erst ab C++11
Ich benutze eh C++11, in dem Sinne nicht das Problem

manni66 schrieb:
In boost gibt's das schon für ältere Compiler
Die Boost-Lösung ist mir zu langsam, dadurch, dass in der main direkt "function" aufgerufen werden kann, spart das vorallem mit dem Release-Build sehr viel Zeit, die Zeit entspricht dann in etwa einem normalem Funktionsaufruf, Boost benötigt dafür etwa die 10x Zeit

Ist std::function schneller als Boost?
-
Cyres schrieb:
manni66 schrieb:
In boost gibt's das schon für ältere Compiler
Die Boost-Lösung ist mir zu langsam, dadurch, dass in der main direkt "function" aufgerufen werden kann, spart das vorallem mit dem Release-Build sehr viel Zeit, die Zeit entspricht dann in etwa einem normalem Funktionsaufruf, Boost benötigt dafür etwa die 10x Zeit

Ist std::function schneller als Boost?Ich behaupte mal, du machst bei der Messung etwas falsch. Das ist alles nur Abstraktion, Unterschiede sollte es nur in der Compilezeit geben.
-
Die Zeit habe ich wärend der Ausführung des Programmes bestimmt

template <class T> void getFunction(T& t, void (T::*function)(int)) { func fun = &invoke<T, function>; }Ich bekomme dabei den folgenden Fehler:
- error: parse error in template argument listWas er bedeutet ist mir klar, er Kann "function" nicht als Template-Argument gebrauchen, und ich weiß nicht warum, weil der Typ müsste doch der gleiche sein.
-
template <class T> void getFunction(T& t, void (T::*function)(int)) { func fun = &invoke<T, function>; }Der Wert von
T::*functionist ein Funktionsparameter und kann sich zur Laufzeit aendern. Er kann deswegen nicht als Templateparameter verwendet werden. Es ist eben kein Typ. In deinem Ausgangsbeispiel funktionier das, da WertFoo::testzur Kompilezeit bekannt ist.
-
Klar, darauf hätte ich auch selber kommen können
besten Dank!Ich gucke mir später oder morgen mal die bind und function aus C++11 an.
-
SeppJ schrieb:
Cyres schrieb:
manni66 schrieb:
In boost gibt's das schon für ältere Compiler
Die Boost-Lösung ist mir zu langsam, dadurch, dass in der main direkt "function" aufgerufen werden kann, spart das vorallem mit dem Release-Build sehr viel Zeit, die Zeit entspricht dann in etwa einem normalem Funktionsaufruf, Boost benötigt dafür etwa die 10x Zeit

Ist std::function schneller als Boost?Ich behaupte mal, du machst bei der Messung etwas falsch. Das ist alles nur Abstraktion, Unterschiede sollte es nur in der Compilezeit geben.
Wer sagt denn dass Abstraktion keine Laufzeitkosten haben kann? Quasi jede Abstraktion die nicht vollstdänig inlined werden kann hat Laufzeitkosten, und std/boost::function kann halt meistens nicht vollständig inlined werden. Weil es halt Polymorphie auf die eine oder andere Art erfordert (entweder klassisch oder über Type-Erasure).
Davon auszugehen dass boost/std::function gleich schnell ist wie ein Call über eine Trampolin-Funktion (die idealerweise auf einem einzigen "jump" Besteht) finde ich schon sehr gewagt.
-
hustbaer schrieb:
SeppJ schrieb:
Cyres schrieb:
manni66 schrieb:
In boost gibt's das schon für ältere Compiler
Die Boost-Lösung ist mir zu langsam, dadurch, dass in der main direkt "function" aufgerufen werden kann, spart das vorallem mit dem Release-Build sehr viel Zeit, die Zeit entspricht dann in etwa einem normalem Funktionsaufruf, Boost benötigt dafür etwa die 10x Zeit

Ist std::function schneller als Boost?Ich behaupte mal, du machst bei der Messung etwas falsch. Das ist alles nur Abstraktion, Unterschiede sollte es nur in der Compilezeit geben.
Wer sagt denn dass Abstraktion keine Laufzeitkosten haben kann? Quasi jede Abstraktion die nicht vollstdänig inlined werden kann hat Laufzeitkosten, und std/boost::function kann halt meistens nicht vollständig inlined werden. Weil es halt Polymorphie auf die eine oder andere Art erfordert (entweder klassisch oder über Type-Erasure).
Davon auszugehen dass boost/std::function gleich schnell ist wie ein Call über eine Trampolin-Funktion (die idealerweise auf einem einzigen "jump" Besteht) finde ich schon sehr gewagt.
Dass die Tests durchaus vom Compiler abhängen ist mir bewusst, ich benutze derzeit g++ 4.7, da mit -O3. Aufgrund dessen, da mit der Templatesyntax wie im ersten Post einem Funktionspointer direkt eine Funktion zugeordnet wurde, gibt es halt keinen Overhead wie beim dynamischen Binden etc., was, wie du schon sagtest, weder bei boost::function, noch bei std::function funktionieren wird/kann. Nichts desto trotz ist es Fakt, dass es schnellere Implementationen von delegates gibt. Ob es dadurch besser wird ist eine andere sache. Und für gewöhnlich werden solche Delegates ja auch nicht für laufzeitkritische Dinge benutzt, häufig eher für sachen wie Callbacks/Gui-Benachrichtigung etc.
Ich wollte hier aber auch keine große Disskussion anfechten, warum die simple schreibweise nicht so funktioniert wie z.B. bei Boost ist mir jetzt klar

Als Beispielimplementation, wie ich sie oben meinte, würde ich jetzt aufführen: (Links führen alle nach www.codeproject.com, falls das nicht erwünscht ist, nehme ich sie wieder raus)
- The Impossibly Fast C++ Delegates von Sergey Ryazanov
- Member Function Pointers and the Fastest Possible C++ Delegates von Don Clugston
- Fast C++ Delegate von JaeWook Choi
Ein interessanter Artikel darüber auch auf www.stackoverflow.com: 5 years later, is there something better than the “Fastest Possible C++ Delegates”?
\edit: codeporject in codeproject verbessert

-
@Cyres
Meine Antwort war ja auch an SeppJ gerichtet, der meinte es müsste an deiner Messung was nicht stimmen. Was ich eben nicht glaube, deine Messung kann schon passen.
-
hustbaer schrieb:
@Cyres
Meine Antwort war ja auch an SeppJ gerichtet, der meinte es müsste an deiner Messung was nicht stimmen. Was ich eben nicht glaube, deine Messung kann schon passen.Hab ich auch erst beim zweiten mal bemerkt, trotzallem trägt es ja zum Thema bei, nichts für Ungut
