"Code-Bloating" bei Templates vermeiden
-
Gibt es irgendeine Moeglichkeit (konkret fuer GCC 3.x und VC++ 2003), zu vermeiden, dass sich durch Template-Instantiierungen die Groesse des fertigen Programmcodes aufblaeht?
Ich kann mich noch an fruehere Tricks bei IBM Visual Age for C++ erinnern, aber wie macht man das heutzutage? Schaffen die Linker das von alleine?
-
Können schon, aber immer auf Kosten der Bequemlichkeit/Laufzeit. Man könnte z.B. std::sort so implementieren, dass die C-Funktion qsort aufgerufen wird.
-
@Ringding
dann muss ja trotzdem für jeden Typ ein Template instanziiert werden.
-
Schon, zwei sogar. Nämlich die eigentliche Funktion und die Compare-Funktion. Aber beide sind superkurze Einzeiler, die nicht sonderlich viel Code erzeugen.
EDIT:
Können schon, aber immer auf Kosten der Bequemlichkeit/Laufzeit. Man könnte z.B. std::sort so implementieren, dass die C-Funktion qsort aufgerufen wird.
Ganz stimmt das auch wieder nicht. Es wäre damit zwar möglich Vektoren zu sortieren, aber nicht beliebige Iteratoren. Aber das Prinzip sollte klar sein.
-
Das Problem frueher war, dass der Compiler alle Template-Deklarationen in inline-Klassen umgewandelt hat, und da inline-Funktion stets als modul-lokal galten, war in jedem Modul eine Instanz der jeweiligen Template-Klasse, unsichtbar fuer den Linker (da modul-lokal).
Ich habe den Verdacht, dass das immer noch so ist.
Gibt es kein Code-Sharing ueber Modulgrenzen von Instanzen derselben Template-Klasse? (grade wenn kein Optimizer zur Verfuegung steht -- ich wuerde das ja noch verstehen, wenn die Funktionen inline expandiert wuerden, wie Makros)
-
Gibt es kein Code-Sharing ueber Modulgrenzen von Instanzen derselben Template-Klasse?
Doch, das gibt's schon, wenn's genau die gleichen Typen sind.
-
Power Off schrieb:
Das Problem frueher war, dass der Compiler alle Template-Deklarationen in inline-Klassen umgewandelt hat, und da inline-Funktion stets als modul-lokal galten, war in jedem Modul eine Instanz der jeweiligen Template-Klasse, unsichtbar fuer den Linker (da modul-lokal).
Ich habe den Verdacht, dass das immer noch so ist.
Dieses Problem lässt sich ohne viel Aufwand beheben. Der Compiler sorgt dafür, dass jede einzelne Template-Spezialisierung pro ÜE nur einmal instanziiert wird (aka: "memoization"). Instanziiert mehr als eine ÜE dieselbe Spezialisierung, setzt der Linker auf die ODR und schmeißt alle bis auf eine Definition raus. So hast du am Ende genau eine Instanz pro Template-Spezialisierung.
Explizit kann man ein ähnliches Verhalten erzwingen, wenn man Template-Spezialisierung explizit in einer ÜE instanziiert (über eine "explicit instantiation directive").Btw: Die von dir erwähnte Inline-Transformation darf ein Compiler eigentlich nicht machen, da dies zu Semantik-Änderungen führen kann (z.B. bei statischen Objekten innerhalb von Template-Funktionen).
Gibt es irgendeine Moeglichkeit (konkret fuer GCC 3.x und VC++ 2003), zu vermeiden, dass sich durch Template-Instantiierungen die Groesse des fertigen Programmcodes aufblaeht?
Die Geschichte mit dem "mehrere Instanzen der selben Spezialisierung" schaffen umgehen moderne Compiler/Linker von alleine. Nicht umgehen können sie aber Situationen in denen unnötig viele Spezialisierungen instanziiert werden. Z.B. wenn eine große Template-Klasse für zig verschiedene Pointer-Typen instanziiert wird. In diesem Fall helfen partielle Spezialisierungen (in diesem Fall auf Pointer-Typen) und das hoisting-Idiom (in diesem Fall eine gemeinsame Basisklasse die mit void-Pointern arbeitet).
Ein anderes Beispiel für "Instanziierungs-Inflation" ist häufig unelegante Template-Metaprogrammierung. Hier helfen lazy-Techniken wie sie z.B. in boost::mpl angewendet werden (siehe auch "C++ Template Metaprogramming" von Abrahams und Gurtovoy).
-
Danke!!