Spezialisierte Templates - Theorie
-
Hallo,
Erst einmal: das ist eine rein theoretische Frage zum Compiler. Es handelt sich nicht um ein Codeproblem sondern um ein Verständnisproblem. Ich denke, das ist trotzdem das richtige Forum.
Ich lese gerade den "Stroustrup" und speziell das Kapitel über Template-Spezialisierung.
Ganz kurz zusammengefasst: Es geht darum, dass es unter Umständen sehr ineffizient sein kann, allzu generelle Templates zu verwenden, weil z.B. alle Zeiger sich ein Template teilen könnten.
Das kann man optimieren, indem man das Template für Zeiger spezialisiert. Also:template <class T> class Foo { public: T bar(T n) { return n; } }; template <> class Foo<void*> { // Spezialisierung für void* public: void* bar(void* n); }; template <class T> class Foo<T*> : private Foo<void*> { // Spezialisierung für T* public: T* bar(T* n) { return static_cast<T*>(Foo<void*>::bar(n)); } };
Mal davon abgesehen, dass der Linker damit Probleme hat (was ich verstehe -- 'Base::bar' ist schließlich nicht statisch definiert worden), hätte ich zu diesem Code eine Frage:
Ist es nicht Aufgabe des Compilers, solch eine Optimierung vorzunehmen? Wieso sollte sich der Programmierer damit auseinandersetzen? Ich meine, das ist ja eine ziemlich automatisierte Aktion, ein Compiler sollte doch eigentlich keine Probleme damit haben, für alle Zeigertypen ein und dasselbe Template zu verwenden, wieso muss man ihm das explizit (durch Spezialisierung) sagen?
-
Ob es eine Aufgabe des Compilers ist, kann ich nicht sagen. Vielleicht machen das manche compiler, manche nicht. Das Verwenden von generischen void* ist eine gute idee.
Das mit dem Linker kapier ich nicht - das ist kein statischer Aufruf, sondern du gibst explizit an, welche Funktion du aufrufen willst. So ginge es auch:return static_cast<T*>(static_cast<Foo<void*>*>(this)->bar(n));
So kann man mitunter viel spahren, da der compiler ja die templates ersetzen muss.
-
Ein cast auf void* zerstoert jede Typensicherheit...
Wuerde ich wenn's nicht wirklich sein muss mit sicherheit nicht einsetzen
-
ness schrieb:
Das mit dem Linker kapier ich nicht - das ist kein statischer Aufruf, sondern du gibst explizit an, welche Funktion du aufrufen willst.
Ähm, logisch. Danke für Deine Antwort.
SnorreDev schrieb:
Ein cast auf void* zerstoert jede Typensicherheit...
Die ist doch aber durch die Benutzung von 'Foo<T*>' gegeben. Nach außen hin verwendet man ja dann nur diesen Wrapper.