C++ - passing-Methode pointer als template-argument
Ich habe ein Anrufer die Funktion wie folgt:
template<typename T, void (T::*method)()>
void CallMethod(T *object){
(object->*method)(args);
}
während dieser perfekt funktioniert:
void (*function)(A *) = &CallMethod<A, &A::method>;
dieser code nicht kompilieren mit dem Fehler in der zweiten Zeile:
void (A::*method)() = &A::method;
void (*function)(A *) = &CallMethod<A, method>;
Gibt es eine Möglichkeit es zu beheben? Ich brauche die CallMethod Vorlage zu nehmen, ein konstanter Zeiger auf eine Methode, die in einer Variablen gespeichert ist.
- Ist, dass der eigentliche code, der nicht kompiliert? Was ist die "Methode" hier? Sie bei der Zuordnung einer member-Funktion namens Methode auf eine variable auch als Methode plus die member-Funktion variable deklariert ist falsch..
- warum nimmst du nicht std::tr1::function/boost::function mit binden für diese?
- 'Methode' ist nur eine Methode von A. Es ist nicht eine tatsächliche code, ich habe versucht, um es zu vereinfachen, so viel wie möglich.
- boost:Funktion/bind funktioniert nicht, wenn das, was er eigentlich will, ist eine Funktion, die einen A* - parameter. Ich denke, er wird versuchen, dynamisch zu erstellen.
- Sie können
bind
eine member-Funktion eines Objekts, die Funktion Zeiger von derfunction
zurückgegeben, und die Arbeit mit, dass... - er hat eine C-Schnittstelle, die will eine normale Funktion, nicht eine member-Funktion. Sie können einen boost::function noch brauchst aber einen adapter, wie das in meiner Antwort zu bekommen, es funktioniert in eine C-Schnittstelle.
- siehe den ersten link in meiner Antwort aktualisiert, um zu sehen, eine Methode, eine Funktion Zeiger von einer
function
Objekt.
Du musst angemeldet sein, um einen Kommentar abzugeben.
In diesem Punkt habe ich festgestellt, dass Sie eine API, die eine Funktion und einen Zeiger, und Sie brauchen, um zu liefern, es zu tun. Ich gehe davon aus, dass Sie immer die Versorgung ist es Ein a* Zeiger?
Wenn es ist ein sehr allgemeiner Rückruf, sondern muss eine Funktion (kann nicht sein, boost::function) und muss ein Zeiger (möglicherweise void*), dann benötigen Sie eine Funktion, die ein bisschen wie diese:
So, in diesem Fall bin ich der Aufruf von delete auf der call Zeit, also muss ich davon ausgehen, nennen wir neu bei aufrufen Zeit, also, wenn Sie, erstellen Sie den Mauszeiger auf die Ihr Anruf ist gemacht. Natürlich könnte es nicht sein, dass dein Zeiger übergeben Sie gelöscht wird beim ersten Aufruf, so zu verwalten, die Lebensdauer entsprechend.
Wenn Sie sind in der Kontrolle der "anderen Seite" dann tun Sie das nicht durch design, sondern lassen Sie die Seite, halten Sie die boost::function und rufen Sie es.
Memory management kann noch ein Problem, die Sie brauchen zu kümmern. Zum Beispiel, wenn Sie anrufen, boost::bind es legt Dinge in eine Struktur, die hinter den kulissen für Sie. Wenn diese Hinweise, die Sie zugewiesen mit neuen zu löschen, muss man Sie irgendwann. Wenn Sie Referenzen Sie müssen noch gültig sein, am point-of-call. Zeiger auf lokale Variablen kann auch ein problem sein. shared_ptrs sind ideal, natürlich. Und das bug-tracking um die boost::bind Fehler ist sehr sehr schwer zu finden, wenn Sie mit diesem Konzept eine Menge.
Alle template-Parameter muss zur Kompilierzeit bekannt ist. Also, wenn
method
ist wirklich eine variable und nicht eine bestimmte Funktion, es gibt keine Möglichkeit, das zu tun, was Sie wollen.Stattdessen werden Sie in der Lage, eine
template struct
die einen Zeiger auf member-Funktion als Mitglied und implementiert eineoperator()
was wirkt ähnlich wieCallMethod<A, method>
.A*
Zeiger als nur Funktion-argument ist nicht genug, um herauszufinden, welche Methode zu nennen. Siehe @CashCow Antwort.Es sieht aus wie Sie versuchen, zu implementieren eine Schnittstelle, über die Vorlagen. Es könnte möglich sein, aber wäre es nicht schöner, wenn eine Basisklasse eine virtuelle Funktion, und verwenden Sie eine Basisklasse Zeiger zum Zugriff auf die virtuelle Funktion über einen einfachen Funktionsaufruf?
Header:
Quelldatei:
Beispiel:
Können Sie speichern einen Vektor von Zeigern (oder smart-Pointer, wenn Sie die Verwendung von boost und C++0x), die Sie Durchlaufen, und verwenden Sie diese um alle Arten von Unterklasse abhängige Sachen.
Nutzen Sie alternativ
boost::function
oderstd::function
(C++0x), die ein Objekt mit der member-Funktion in Frage, und übergeben, die als template-parameter, mit dem Objekt-Instanz, die als erstes argument. Das kommt darauf an, eine Abhilfe der oben genannten.UPDATE: Sehen Sie, Sie brauchen eine einfache C-Funktion Zeiger, gibt es einige tricks, die vielleicht imapct runtime-performance im c++0x oder-boost:
bind
,function::target
und so weiter...Müssen Sie dies, um eine Funktion Zeiger aus einem
std/boost::function
, und diese binden das erste argument ein Objekt.bind
Handlungen zur Laufzeit, also vielleicht eine Vorlage wäre in diesem Fall besser...function::target
wird nicht funktionieren hier. [Die Antwort][1], um das verknüpfte Frage ist im Grunde das gleiche wie @CashCow ist dieses. [1] stackoverflow.com/questions/282372/...Erste, erstellen Sie bitte Typdefinitionen http://www.parashift.com/c++-faq-lite/Zeiger-zu-member.html#faq-33.5
Zweite,
In diesem Fall Methode ist eine variable und die Variablen können nicht-template-Argumente. Ich habe es noch nicht getestet, aber vielleicht könntest du versuchen...
Was ist, wenn 2 Methoden haben genau die gleiche Signatur ?
Die Vorlage nicht unterscheiden kann, auf die er (Sie wählt auf die Art, nicht Wert) und damit der gleichen generierten template-Funktion ruft die erste Methode oder die zweite wäre, setzen Sie Ihre hand auf ihn ?
Können Sie nutzen einige tricks, um einen anderen Typ zur compile-Zeit, mit der __LINE__ makro, aber es geht Misch-makro mit dem aktuellen code, wird es schwer zu Folgen.
Dieser code:
Aber Sie werden nicht in der Lage zu speichern, die Zeiger auf eine Methode in einer Variablen und eine "auto-wrapper" aus. Es ist jetzt die Laufzeit, benötigen Sie eine runtime-Lösung für dieses.