Template-Parameter mit Klasse vergleichen
-
Hallo,
ich habe zwei Klassen Tree und Node und Tree hat eine Template Member Function:
template<class T> T* Tree::fctn();
In dieser Funktion würde ich gerne abfragen, ob T gleich meiner Klasse Node ist.
Kann mir jemand sagen, wie man das am einfachsten macht? Ich gehe davon aus, dass man es irgendwie so ähnlich machen kann, wie in "C++ Templates" (Josuttis) in Kapitel 19 (Type Classification) beschrieben, aber ich frage mich, ob es da auch einen built-in Weg gibt.
-
Warum so kompliziert? Vermutlich willst du doch für Node etwas anders machen, sonst würdest du dies ja nicht abfragen. Also spezialisier das Template für Node.
-
SeppJ schrieb:
Warum so kompliziert? Vermutlich willst du doch für Node etwas anders machen, sonst würdest du dies ja nicht abfragen. Also spezialisier das Template für Node.
In der realen Problemstellung müsste ich nicht nur auf Gleichheit mit der Klasse Node, sondern auch mit anderen Klassen prüfen. Für diese Klassen würde die Funktion dann ein und dasselbe tun.
-
ingobulla schrieb:
In der realen Problemstellung müsste ich nicht nur auf Gleichheit mit der Klasse Node, sondern auch mit anderen Klassen prüfen. Für diese Klassen würde die Funktion dann ein und dasselbe tun.
In dem Fall müsstest du einen Umweg über ein oder zwei weitere Templates gehen:
#include <iostream> template <class T> struct HasSpecialImplementation { const static bool value = false; //standard: nicht speziell }; //spezialisieren für alle "speziellen" Typen template<> struct HasSpecialImplementation<int> { const static bool value = true; }; template<> struct HasSpecialImplementation<float> { const static bool value = true; }; // dieser functor hat verschiedene Spezialisierungen für true und false, d.h. für die speziellen Typen template<class T, bool hasSpecialImplemetation = HasSpecialImplementation<T>::value> struct TreefctnFunctor { T* operator()() { std::cout << "Normaal" << std::endl; return 0; } }; template<class T> struct TreefctnFunctor<T, true> { T* operator()() { std::cout << "SPECIAL!!" << std::endl; return new T(); } }; //##################################################### class Tree { public: template<class T> T* fctn() { TreefctnFunctor<T> f; return f(); } }; int main() { Tree tree; bool* pb = tree.fctn<bool>(); int* pi = tree.fctn<int>(); std::cout << "pb is " << pb << "\npi is " << pi << std::endl; delete pi; delete pb; }
Output:
Normaal SPECIAL!! pb is 0 pi is 0x8051438
getestet auf codepad.org.
Nachtrag: statt bool kann auch ein enum-Typ verwendet werden, so dass mehr als 2 verschiedene Implementierungen machbar sind. Wenn die Funktion/der Functor auf Interna von Tree zugreifen soll, kann man ihn auch als interne Klasse von Tree definieren und hm eine Referenz auf den Tree liefern:
class Tree { // dieser functor hat verschiedene Spezialisierungen für true und false, d.h. für die speziellen Typen template<class T, bool hasSpecialImplemetation = HasSpecialImplementation<T>::value> struct TreefctnFunctor { T* operator()(Tree& t) { ++(t.i); std::cout << "Normaal" << std::endl; return 0; } }; template<class T> struct TreefctnFunctor<T, true> { T* operator()(Tree& t) { ++(t.i); std::cout << "SPECIAL!!" << std::endl; return new T(); } }; int i; public: Tree() : i(0) {} template<class T> T* fctn() { TreefctnFunctor<T> f; return f(*this); } };