Auf Template Typ prüfen?
-
Du könntest eine Spezialisierung für das Template anlegen, die (anstelle einer allgemeinen Funktion) etwas speziell für dich zugeschnittenes aufruft:
template<typename T> void print(const T& data) { cout<<data; } template<> void print(const double& data) { cout<<setprecision(2)<<scientific<<data; }
-
Mati schrieb:
Hallo,
ich kenne mich mit Templates (noch) überhaupt nicht aus:...
Nur mal so ins Blaue geschossen: Weißt Du, dass templates zur Compilezeit umgesetzt werden ? Das ist etwas Anderes als "Polymorphie durch Vererbung", "RTTI" (RunTimeTypeInformation), typeid(), ....
Der Vorteil ist eben, dass Du "Spezialisierungen" schreiben kannst - also festlegen, wie sich Dein template für bestimmte Typen verhalten soll - und der Compiler für Dich überprüft, ob alles passt. Da bedeutet, Du stellst es nicht erst zur Laufzeit fest, sondern schon vorher.
Gleichzeitig ist es aber dann aber eben auch zur Laufzeit bereits festgelegt und nicht mehr änderbar.....
Konkretes Beispiel:
//fremdlib.h void mach_was_mit_char(char c); void mach_was_mit_long(long l); void mach_was_mit_int(int i);(fände ich zwar schlecht ein solches Design, aber hier mal als Beispiel genommen)
Dein Zeug:
//meinZeug.h template <typename T> struct meinZeug { T x; void mach_was(); // generelle Funktion }; // Spezialisierungen template <> void meinZeug<char>::mach_was() { mach_was_mit_char(x); } template <> void meinZeug<long>::mach_was() { mach_was_mit_long(x); } template <> void meinZeug<int>::mach_was() { mach_was_mit_int(x); }Genutzt wird's so:
int main() { meinZeug<char> c; c.machwas(); // funktioniert ! Ruft meinZeug<char>::mach_was() -> mach_was_mit_char() auf meinZeug<int> i; i.mach_was(); // funktioniert ! Ruft meinZeug<int>::mach_was() -> mach_was_mit_int() auf meinZeug<double> d; // ist erlaubt !! Solange nicht mach_was() aufgerufen wird meinZeug<string> s; s.mach_was(); // FEHLER -> meinZeug<string>::mach_was() wird nicht gefunden ...Ergo: Du brauchst gar nicht zu prüfen/wissen, "welchen Typ mein template hat", sondern sagst, wie es sich für die von Dir gewünschten Typen verhalten soll und der Compiler wird Dir schon sagen, wenn ein "ungewünschter Typ" verwendet wurde.
Gruß,
Simon2.
-
Mati schrieb:
Hallo,
ich kenne mich mit Templates (noch) überhaupt nicht aus:
da ich eine externe Library Funktion aufrufe muss ich wissen welcher Typ in meinem Template liegt um abhängig davon eine andere Funktion aufzurufen.
Kann ich irgendwie überprüfen ob in meinem Template z.B ein double liegt oder
auch z.B eine eigens definierte structure?Danke euch
-
KasF schrieb:
...
http://c-plusplus.net/forum/viewtopic-var-p-is-1323449.htmlIst der hier nicht ein wenig oversized ?
Ich glaube, der Link führt zu einer Diskussion von Problemen, die Mati noch gar nicht hat. Es geht im (wenn ich ihn recht verstanden habe) um das "Herausfinden eines konkreten Typs" und weniger um "Typeigenschaften".Nichtsdestotrotz ein interessanter Thread.
Gruß,
Simon2.
-
Simon2 schrieb:
KasF schrieb:
...
http://c-plusplus.net/forum/viewtopic-var-p-is-1323449.htmlIst der hier nicht ein wenig oversized ?
Ich glaube, der Link führt zu einer Diskussion von Problemen, die Mati noch gar nicht hat. Es geht im (wenn ich ihn recht verstanden habe) um das "Herausfinden eines konkreten Typs" und weniger um "Typeigenschaften".Mati schrieb:
Kann ich irgendwie überprüfen ob in meinem Template z.B ein double liegt oder
auch z.B eine eigens definierte structure?Für sein double reicht doch ein einfaches:
template<class T> struct IsDouble { enum { result = false }; }; template<> struct IsDouble<double> { enum { result = true }; }; template<class T> void myfunc(t val) { if(isDouble<T>::result) { } else ... }Für sein eigenes struct ein:
struct MyStructType { }; struct MyStruct { typename MyStructType type; }; template<class T> void myfunc(T val) { if(typeId(typename T::type) == typeID(MyStructType) ) { } else ... } //oder um typeId zu vermeiden entsprechend überladen und anhand des Types die //richtige Funktion auswählen lassen.Was ist daran oversized ?
-
Hi KasF,
ich meinte nicht unbedingt, dass die dort vorgestellten Ansätze oversized sind, sondern der Thread an sich.
Die von Dir angegebene "Lösung" ist IMO allerdings trotzdem "oversized", weil ich glaube, dass Mati ein typisches "Anfängerproblem" hier hat: Er möchte Problem A lösen, stellt sich Lösung X vor und hat bei der Umsetzung Problem B.
Nun fragt er nach einer Lösung für B, dabei gibt es eine viel bessere Lösung für A.Ist lustigerweise ja eigentlich der typische Werdegang bei Threads mit dem Titel "Wie bekomme ich den Typ raus ?"
In den allerseltensten Fällen ist eine Typbestimmung wirklich die geeigente Lösung...Gruß,
Simon2.
-
Ja schon möglich. Warten wir eben ab was Mati genau will.

-
KasF schrieb:
Ja schon möglich. Warten wir eben ab was Mati genau will.

Naja, er schrieb halt:
Mati schrieb:
...
da ich eine externe Library Funktion aufrufe muss ich wissen welcher Typ in meinem Template liegt um abhängig davon eine andere Funktion aufzurufen....... und da scheint mir eine Spezialisierung das bessere Mittel zu sein.
Gruß,
Simon2.
-
Danke euch für eure rege Hilfe!
Also vielleicht sollte ich genauer werden:
struct complex{ int r; ind i; }; lib_fkt1(double* arr); lib_fkt2(complex arr2) //Und jetzt habe ich ein template array //welches je nach input entweder aus nur double werten besteht oder eben //aus complex structs-elementen. //Und da die lib-funktionen jetzt eben je nach input anders aufgerufen werden //müssen dachte ich ich teste auf den typ um dann mit if / else zu verzweigen.
-
Dein Template Array befindet sich vermutlich in einer Funktion oder in einer Klasse.
Das ganze zu spezialisieren würde dazu führen das man den Code doppelt schreiben müsste, wenn man den Code nicht gut in verschiedene Teilebereiche ausgelagert haben sollte.Ich würde in diesem Fall sowas vorziehen:
lib_fkt(double* arr) { lib_fkt1(arr); } lib_fkt(complex* arr) { lib_fkt2(arr); } //.... T array[20]; lib_fkt(array);Edit: Achja Simon hattest recht

-
Mati schrieb:
Danke euch für eure rege Hilfe!
Also vielleicht sollte ich genauer werden:
struct complex{ int r; ind i; }; lib_fkt1(double* arr); lib_fkt2(complex arr2) //Und jetzt habe ich ein template array //welches je nach input entweder aus nur double werten besteht oder eben //aus complex structs-elementen. //Und da die lib-funktionen jetzt eben je nach input anders aufgerufen werden //müssen dachte ich ich teste auf den typ um dann mit if / else zu verzweigen.(BTW: lib_fkt1/2 sollten auch return types haben
)
(BTW2: ich gehe mal davon aus, dass bei lib_fkt2(complex) ein '*' fehlt)Da kannst Du doch prima mein voriges Beispiel drauf anwenden:
template <typename T> struct meinArray { T arr[10]; void lib_fkt(); }; template <> void meinArray<double>lib_fkt() { lib_fkt1(arr); } template <> void meinArray<complex>lib_fkt() { lib_fkt2(arr); }Wenn die lib overloading nutzen würde (sprich: lib_fkt1/2 denselben Namen hätten), könnte man sich das Ganze sparen:
void lib_fkt(double* arr); void lib_fkt(complex* arr); template <typename T> struct meinArray { T arr[10]; }; int main() { meinArray<double> d; lib_fkt(d.arr); meinArray<complex> c; lib_fkt(c.arr); ...Gruß,
Simon2.
P.S.: KasFs Variante, die unterschiede in eigenen Overloads zu verstecken, ist aber auch gut.
-
@Simon2: man kann sich die Overloads auch selbst basteln, dann kann man sich die Template-Spezialisierungs-Dings auch sparen

void lib_fun1(lala* l); void lib_fun2(int* i); inline void lib_fun(lala* l) { return lib_fun1(l); } inline void lib_fun(int* i) { return lib_fun2(i); } // und nu einfach lib_fun(T*) verwenden...
-
hustbaer schrieb:
@Simon2: man kann sich die Overloads auch selbst basteln, ...
Meinst Du so wie KasF es oben schon gezeigt hat ?

Meine "Spezialisierungsvariante" habe ich noch gezeigt, weil diese Technik sie vorhier angesprochen wurde und ich davon ausging, dass Mati evtl. noch komplexere Dinge in seiner/m Klasse/ntemplate abbilden will als nur das Array.Außerdem ist Spezialisierung eine schöne Technik, die man ruhig mal gesehen haben darf, wenn man mit templates anfängt und rumprobiert.
Gruß,
Simon2.