Thread View: de.comp.lang.c++
4 messages
4 total messages
Started by root
Sun, 03 Mar 1996 08:19
most-faq: template instantiation&compiler specifics
Author: root
Date: Sun, 03 Mar 1996 08:19
Date: Sun, 03 Mar 1996 08:19
95 lines
5333 bytes
5333 bytes
Wenn mich nicht alles taeuscht, ist die Frage nach dem richtigen Umgang mit
template-member-Funktionen (tmf) die am haeufigsten gestellte und nie richtig
beantwortete Frage.
Daher hier, nach Lektuere von
- g++-info:templates,
- SUN C++ 4.0.1 user manual,
- FAQ for g++ and libg++,
- threads in comp.lang.c++(.moderated), comp.std.c++, de.comp.lang.c++,
gnu.lang.help mit subject "... template ...",
meine Version der Frage.
Ursache des Problems ist wohl, dass manche c++-Fans (leider auch die meisten
Compilerhersteller) meinen, der Compiler muesste so schlau sein, nur die tmf
Instanzen zu erzeugen, die tatsaechlich verwendet werden. Dazu gibt es laut
g++-info (bestaetigt durch ein posting eines *borland.com und SUNs C++
4.0.1-Handbuch) zwei Ansaetze:
1. Borland-C++:
Template-Deklaration und -Definition in die header-Datei schreiben, ein
spezieller Linker filtert die entstandenen Redundanzen heraus.
Nachteil:
Damit kann man das Konzept:
- header-Datei = Schnittstellendeklaration,
- Programm-Datei = Programmimplementation,
endgueltig vergessen. Und damit auch die Wartung groesserer Projekte.
2. Cfront (AT&T, mit Einschraenkungen SUN C++):
Irgendwoher "weiss" der Compiler, wo die tmf definiert sind, bestimmt,
welche Instanzen notwendig sind und erzeugt diese.
Leider fehlt bei den meisten Rechnern die Einfuelloeffnung fuer Maggi.
SUN behilft sich mit TemplateDB-Verzeichnissen. Das scheint aber, wenn
ueberhaupt, nur zu funktionieren, wenn
- header und source den gleichen Basisnamen haben und
- alle Quellen im gleichen Verzeichnis stehen.
g++ bietet in der Standardversion eine aehnliche Moeglichkeit durch die
Verwendung von "#pragma interface <FILE>"/"#pragma implementation", mit
der Compiler-Optionen "-fexternal-templates" und dem Eintrag
"template class <Instanzen-Bezeichnung>;" in der tmf-Definitionsdatei.
Nachteil:
Es entsteht ein zusaetzlicher Verwaltungsaufwand, mit dem sich der
Programmentwickler sehr bald selbst beschaeftigen muss. Bei grossen
Projekten wird ein erheblicher Teil der Dateistruktur in die
Programmquellen einfliessen. Dann ist es mit der Modularitaet und
Wiederverwendbarkeit ebenfalls vorbei.
Gemeinsammer Nachteil der beiden Methoden:
sie sind miteinander unvertraeglich.
Ergebnis:
Der Ansatz "der Compiler/Linker erzeugt aus templates genau die benoetigten
Instanzen" ist ebenso schoen wie falsch:
Hoffen: ja, natuerlich; Wissen: nein, leider; Tun: _NEIN_! niemals!
Bleibt als 3. Moeglichkeit die triviale Loesung der "expliziten
Instanzenbildung"
Ansatz:
- Templates sind Werkzeuge, mit denen man durch einmaliges Codieren mehrere
aehnliche Klassen/Funktionen erzeugt.
- Aus einer Quelldatei erzeugte Objektdateien enthalten den Code, der
auf Grund des Inhaltes der Quelldatei, dort eingeschlossener header-
Dateien, sowie der Compiler-Optionen erzeugt wurde.
- Beim Uebersetzen der tmf muss der Compiler wissen, welche Instanzen
erzeugt werden sollen.
- Beim Uebersetzen der Anwendungsprogramme sollte der Compiler wissen,
welche Instanzen zur Verfuegung stehen, d.h. wann er eine Fehlermeldung
ausgeben muss.
Vorteil:
- Selbst MS-Programmierer muessten in der Lage sein, das zu implementieren.
- Waere dies die allgemein empfohlene, standardmaessig implementierte Art,
wuerde die Zahl der postings vom Typ "HELP: LINKER ERROR: UNDEFINED"
drastisch reduziert.
- Der Uebergang zwischen "eigenen" templates und templates fuer/in
libraries ist zwanglos moeglich.
- Die aus C uebernommenen Ansaetze, die Modularisierung in die
Dateistruktur abzubilden, bleiben erhalten.
Realisierung:
1. g++:
Mit Eintrag "template class <Instanzen-Bezeichnung>;" fuer jede gewuenschte
Instanz in der Datei mit den Definitionen der tmf erzwingt man die
Erzeugung der entsprechenden Memberfunktionen. Die Compiler-Option
"-fno-implicit-templates" sorgt dafuer, dass diese global verwendet werden.
Nachteil (soweit ich es bisher ausprobiert habe):
- Bei Verwendung von "-fno-implicit-templates" werden auch inline
template-Funktionen nicht mehr automatisch expandiert.
- Schade, aber nicht wirklich stoerend: "template class ..." muss in
der Quelle, nicht im header stehen (sonst gibt's "multiple
defined"). So merkt erst der Linker, wenn eine Instanz fehlt.
2. SUN C++ 4.0.1:
Mit dem Eintrag "template class ..." kann er nichts anfangen. Bisher weiss
ich nichts Besseres als in der Definitionsdatei der tmf dummy-Programme
anzuhaengen, die jede Memberfunktion einmal afurufen. Das kann ja wohl
nicht wahr sein!
Zusaetzlich scheint man dem Compiler die Option "-pto" geben zu muessen,
damit die tmf-Instanzen global werden. Fuer die Bildung der Modul-
libraries scheint man "CC -xar" (statt "ar") verwenden zu muessen.
MfG, Gerhard.
Re: most-faq: template instantiation&compiler specifics
Author: Jan Willamowius
Date: Sun, 03 Mar 1996 15:18
Date: Sun, 03 Mar 1996 15:18
40 lines
1954 bytes
1954 bytes
root@gt-priv.m.eunet.de (root) writes: >2. Cfront (AT&T, mit Einschraenkungen SUN C++): >[...] > SUN behilft sich mit TemplateDB-Verzeichnissen. Das scheint aber, wenn > ueberhaupt, nur zu funktionieren, wenn > - header und source den gleichen Basisnamen haben und > - alle Quellen im gleichen Verzeichnis stehen. Ich portiere gerade von Watcom nach cfront und kann ein paar Details beitragen: Das Verzeichnis ist kein Problem. Es wird ueberall auf dem Includepfad gesucht. Watcom ist auch durchaus in der Lage die Implementationen zu finden, auch wenn sie nicht den gleichen Basisnamen haben bzw. ueber mehrere Dateien verstreut sind. (Ob man ihm noch auf die Spruenge helfen muss entzieht sich meiner Kenntnis). Cfront kann man mit sog. Map-Dateien in seinen Repository ebenfalls auf die Spruenge helfen wo er die Implementationen finden soll. (Ugly!) Wer neuen Code schreibt tut sich sicherlich einen Gefallen, wenn die Dateinamen gleich sind. Man weiss ja nie mit welchem kranken Compiler er mal uebersetzt werden wird. Die Geschwindigkeit in der cfront die Templates instanziiert ist unglaublich und verschafft regelmaessig Gelegenheit zu einem laengeren Kloenschnack. Es gab hier doch mal eine Diskussion, dass sich der g++ je nach Plattform bzw. Linker (z.B. Linux vs. FreeBSD) auch unterschiedlich verhaelt. Kann jemand das nochmal erklaeren ? Gruss, Jan -- Jan Willamowius, Semperstr. 1, 22303 Hamburg, Germany Tel. 040 / 280 62 09, E-Mail: jan@janhh.shnet.org WWW: "http://swt1.informatik.uni-hamburg.de/~1willamo/"
Re: most-faq: template instantiation&compiler specifics
Author: Dietmar Kuehl
Date: Sun, 03 Mar 1996 21:27
Date: Sun, 03 Mar 1996 21:27
98 lines
5647 bytes
5647 bytes
Hi, root (root@gt-priv.m.eunet.de) wrote: : Wenn mich nicht alles taeuscht, ist die Frage nach dem richtigen Umgang mit : template-member-Funktionen (tmf) die am haeufigsten gestellte und nie richtig : beantwortete Frage. Ich kann nicht nachvollziehen, dass dies die am haeufigsten gestellte Frage ist. Obwohl die Frage in clc++m gelegentlich auftaucht, ist es nicht so dass es uebermaessig viel gefragt wird. Derzeit erscheint mir z.B. eher die Frage nach "renew" (in allen Variationen) deutlich haeufiger zu sein... : Ursache des Problems ist wohl, dass manche c++-Fans (leider auch die meisten : Compilerhersteller) meinen, der Compiler muesste so schlau sein, nur die tmf : Instanzen zu erzeugen, die tatsaechlich verwendet werden. Das liegt vermutlich daran, dass eine Standard konforme C++ Implementation so schlau sein muss (OK, es gibt noch keine Standard, aber diese Forderung wird mit ziemlicher Sicherheit im Standard enthalten sein). Der Grund warum es derzeit keine Compiler gibt, der Templates richtig behandelt liegt z.B. darin, dass die Definition von Templates in ihrer jetztigen Form noch sehr jung ist. Aber ich bin mir absolut sicher, dass sich die Compilerbauer den A**** aufreissen werden, dem Standard zu genuegen und zwar so schnell wie irgend moeglich! Der Markt fuer einen Standard konformen UND funktionsfaehigen C++ Compiler ist gross. Sehr gross. Die Betonung liegt uebrigens durchaus auf "funktionsfaehig" und gemeint ist nicht die Beschreibung, in der der Compiler behauptet, was der Compiler kann! : Dazu gibt es laut : g++-info (bestaetigt durch ein posting eines *borland.com und SUNs C++ : 4.0.1-Handbuch) zwei Ansaetze: : 1. Borland-C++: : Template-Deklaration und -Definition in die header-Datei schreiben, ein : spezieller Linker filtert die entstandenen Redundanzen heraus. : Nachteil: : Damit kann man das Konzept: : - header-Datei = Schnittstellendeklaration, : - Programm-Datei = Programmimplementation, : endgueltig vergessen. Und damit auch die Wartung groesserer Projekte. Zu fordern, dass es so gemacht wird, ist nicht Standard konform. Man kann Deklaration und Definition von Templates trennen. : 2. Cfront (AT&T, mit Einschraenkungen SUN C++): : Irgendwoher "weiss" der Compiler, wo die tmf definiert sind, bestimmt, : welche Instanzen notwendig sind und erzeugt diese. : Leider fehlt bei den meisten Rechnern die Einfuelloeffnung fuer Maggi. : SUN behilft sich mit TemplateDB-Verzeichnissen. Das scheint aber, wenn : ueberhaupt, nur zu funktionieren, wenn : - header und source den gleichen Basisnamen haben und : - alle Quellen im gleichen Verzeichnis stehen. Nein. Das ist nicht unbedingt noetig (zumindest nicht fuer den generellen Ansatz; fuer die Implementation in SUN C++ schon...). Eine Moeglichkeit, es so zu implementieren, dass man es auf beliebige Files verteilen kann, besteht z.B. darin, aus den Files mit den Template Source spezielle Objektfiles zu generieren, die Symbole enthalten, die sagen, welche (Member-) Funktionen und Objekte definiert werden und wo das entsprechende File steht. ggf. kann man auch eine Vorcompilierte Fassung des entsprechenden Files Speichern. : Bleibt als 3. Moeglichkeit die triviale Loesung der "expliziten : Instanzenbildung" Es ist derzeit zwar womoeglich notwendig, dass es so gemacht wird, ist aber keine "Loesung"! Ein solcher Ansatz ist z.B. beim Arbeiten mit STL irgendwo in der Groessenordnung von total unbrauchbar anzusetzen: Ich verwende gelegentlich Klassen, deren Name, wenn ich alle Templates ersetze (der Compiler ist bei Fehlermeldungen so freundlich, mir die Arbeit abzunehmen :-), auf 1KB zugeht. ... und das sind noch nichtmal "echte" Anwendungen! Niemand will sowas schreiben muessen. Ausserdem ist das auch ein Maintainance-Problem: Aendere ich an der einen Stelle einen Typ, aendern sich dutzende von anderen Typen. : - Waere dies die allgemein empfohlene, standardmaessig implementierte Art, : wuerde die Zahl der postings vom Typ "HELP: LINKER ERROR: UNDEFINED" : drastisch reduziert. Ich empfehle, im Gegensatz zu dem Autor des urspruenglichen Artikels, einen hypriden Ansatz, der sich z.B. mit g++ und SUN CC vertraegt: Man schreibt Headerfiles fuer Templates wie die Headerfiles fuer andere Klassen auch und included am Ende, abhaengig von einem Macro (z.B. fuer SUN CC braucht man die Sourcen nicht zu includen), ggf. die Datei, die den selben Basisnamen wie das Headerfile hat, in der die entsprechenden Template Funktionen/Objekte definiert werden. Das funktioniert erstaunlich gut. Auch mit den derzeit verfuegbaren STL aehnlichen Libraries. Einziger Haken: Die Executables werden teilweise elendig gross. : - Die aus C uebernommenen Ansaetze, die Modularisierung in die : Dateistruktur abzubilden, bleiben erhalten. Mit Standard konformen Compilern kommt das wieder... -- dietmar.kuehl@uni-konstanz.de http://www.informatik.uni-konstanz.de/~kuehl I am a realistic optimist - that's why I appear to be slightly pessimistic
Re: most-faq: template instantiation&compiler specifics
Author: Ullrich von Bassewitz
Date: Mon, 04 Mar 1996 20:42
Date: Mon, 04 Mar 1996 20:42
64 lines
3393 bytes
3393 bytes
> 1. Borland-C++:
> Template-Deklaration und -Definition in die header-Datei schreiben, ein
> spezieller Linker filtert die entstandenen Redundanzen heraus.
> Nachteil:
> Damit kann man das Konzept:
> - header-Datei = Schnittstellendeklaration,
> - Programm-Datei = Programmimplementation,
> endgueltig vergessen. Und damit auch die Wartung groesserer Projekte.
Das ist nicht so schlimm, s.u.
Dumm allerdings, wenn man Bibliotheken verkaufen will.
Weiterer Nachteil (zumindest theoretisch): Laengere Uebersetzungszeiten, da
bei jedem #include der ganze Code uebersetzt werden muss. Das laesst sich
durch precompiled Headers weitgehend abfangen. Fazit: In der einfachsten
Variante sehr einfach zu implementieren, wenn man precompiled Headers haben
will sehr aufwendig. Dafuer helfen precompiled Headers aber auch bei
"normalen" Includes.
> 2. Cfront (AT&T, mit Einschraenkungen SUN C++):
Die Frage ist, welchen Vorteil diese Loesung bietet. Mir fallen auf Anhieb
zwar einige kleinere, aber kein entscheidender Vorteil ein. Zudem ist die
Loesung aufwendig in der Implementation.
> Bleibt als 3. Moeglichkeit die triviale Loesung der "expliziten
> Instanzenbildung"
Dieser Weg ist fuer kleine Programme gangbar. Fuer groessere Projekte mit
vielen Bibliotheken ist das praktisch nicht zu machen. Der Grund dafuer
liegt darin, dass man beim Verwenden einer Klasse immer genau wissen
muss, ob sich evtl. irgendwo in der Klassenhierarchie bis hinunter zur
Basisklasse irgendwo ein Template befindet. Oder ob irgendeine Klasse, die
man verwendet, vielleicht ein Objekt einer Template-Klasse oder einen
Abkoemmling davon als (evtl. private) Data-Member hat. Das Verfahren setzt
also eine Detail-Kenntnis der verwendeten Bibliotheken voraus, die weit
ueber das hinausgeht, was man zum normalen "nur Benutzen" der Bibliotheken
wissen muss.
Verschaerfend kommt natuerlich noch der umgekehrte Effekt: Die explizite
Instantiierung darf man nicht mehr als einmal machen, weil man sonst
"multiple defines" bekommt. Das ist enorm umstaendlich, wenn man zu mehrt an
einem Projekt arbeitet.
Ich behelfe mir bei den neueren Versionen von g++ mit dieser Methode - und
es ist jedesmal eine Kugelfuhr, herauszufinden, welches Template der
Compiler denn nun gerne instantiiert haette, und auch keines dabei mehrfach
zu erwischen.
Also ich denke, diese Moeglichkeit ist wesentlich schlechter fuer die
Wartbarkeit groesserer Projekte als die oben angefuehrte Methode, alles in
ein Header File zu packen. Natuerlich ist das auch keine besonders gute
Loesung, aber wenn meine Bibliothek einmal fertig ist, dann tut es immer.
Wenn ich explizite Instantiierung machen muss, dann habe ich - trotz
fertiger Bibliothek - andauernd ein Rumgemache in der Applikation.
Natuerlich nur meine Meinung...
Gruss
Uz
--
Ullrich von Bassewitz uz@ibb.schwaben.com
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads