Ich möchte Memberfunktionen, die dem Typ 'void (ClassType :: Function) (ArgType)' entsprechen, mit einer Vorlagenklasse umschließen. Später möchte ich eine Instanz von Classtype auf eine Instanz dieser Vorlage passieren und haben es die verpackte Methode aufrufen:C++ - ist es möglich, Klassen- und Argumenttypen aus einem Elementfunktionstyp in einer Vorlage zu extrahieren?
class Foo {
public:
Foo() : f_(0.0) {}
void set(double v) { f_ = v * 2.1; }
double get() { return f_; }
private:
double f_;
};
template <typename ArgType, typename ClassType, void (ClassType::*Method)(ArgType)>
class Wrapper {
public:
explicit Wrapper(ClassType *cls) : cls_(cls) {}
void do_something(ArgType value) {
(cls_->*Method)(value);
}
private:
ClassType *cls_;
};
#include <iostream>
int main(int argc, char ** argv) {
Foo foo;
Wrapper<double, Foo, &Foo::set> wrapper(&foo);
wrapper.do_something(1.0);
std::cout << foo.get() << std::endl;
// outputs "2.1"
return 0;
}
Hinweis in der Instanziierung Wrapper <> dass „Foo“ zweimal angegeben ist - es sieht hier überflüssig aus.
Also was ich gerne wissen würde ist, ob es möglich ist, den Vorlagenparameter ClassType zu vermeiden. Wenn es zum Beispiel möglich ist, es aus dem Elementfunktions-Zeigerparameter zu implizieren oder zu extrahieren, dann müsste es nicht explizit in der Instanziierung von Wrapper <> angegeben werden.
In ähnlicher Weise wäre es nützlich zu vermeiden, explizit anzugeben, ArgType auch, wie (vielleicht) kann es aus Foo :: Set ermittelt werden?
Ist das in C++ möglich? Vielleicht etwas in diese (völlig fantastical) Linien:
template <void (ClassType::*Method)(ArgType)>
class Wrapper2 {
public:
explicit Wrapper(Method::ClassType *cls) : cls_(cls) {}
void do_something(Method::ArgType value) {
(cls_->*Method)(value);
}
private:
Method::ClassType *cls_;
};
// ...
int main() {
Foo foo;
Wrapper<&Foo::set> wrapper(&foo);
// ...
}
Oder vielleicht eine andere Ebene der Vorlage Magie gibt es, die aufgerufen werden kann, dass etwas in dieser Richtung tun würde:
Wrapper<Magic<&Foo::set> > wrapper(&foo);
Ich bin interessiert an wissen, welche Mechanismen eventuell zur Verfügung stehen.
Ich benutze C++ 03 als Voraussetzung, nicht C++ 11, sondern auch interessiert zu wissen, was C++ 11 bieten könnte.
BEARBEITEN: Weitere Informationen - Ich beabsichtige, diesen Mechanismus zu verwenden, ~ 300 Mitgliedsfunktionen (alle gehören ClassType oder eine Reihe von sehr ähnlichen Klassen) zu wickeln, aber es wird nur rund sechs oder so Signaturen berücksichtigt werden:
- void (Classtype :: Function) (ArgType) - wo ArgType ist 'schwebenden'
- void (Classtype :: Function) (ArgType) - wo ArgType ist 'Integral'
- void (Classtype :: Funktion) (bool)
- void (ClassType :: Function) (IndexType, ArgType) - die obigen drei wi th extra ‚index‘ Argument
Die Member-Funktionen ‚Setter‘ Funktionen für sind das, was ich „Eigenschaften“ in einer großen Konfiguration ‚Sammlung‘ Klasse, zum Beispiel (eher als die einfach Foo oben) rufen:
Ich bin mir ziemlich sicher, dass es mit einer Klassenspezialisierung möglich sein wird. Da der Abzug umgekehrt funktioniert, könnten Sie den Methodendeklarationstyp in drei Vorlagentypen auflösen, ausgehend von der Basisschablonendeklaration, die nur einen Vorlagentyp enthält. Und puff, extrahiert. Ich werde das sofort in gcc versuchen. –