In manchen Fällen, z.B. wenn die automatische Instanziierung nicht sinnvoll einsetzbar ist, bietet sich für den Programmierer die Möglichkeit, die explizite (manuelle) Instanziierung zu verwenden, um die Sourcen entsprechend zu erweitern.
Um diesen Vorgang zu erleichtern, kann eine ETR-Datei (ETR - Explicit Template Request) erstellt werden, die die Instanziierungs-Anweisungen für die verwendeten Templates enthält, die in eine Source übernommen werden können.
Die Optionen zur Erstellung dieser ETR-Datei werden mit dem Operanden GENERATE-ETR-FILE der SDF-Anweisung MODIFY-DIAGNOSTIC-PROPERTIES (siehe "MODIFY-DIAGNOSTIC-PROPERTIES") festgelegt.
Wesentlich sind die Angaben *ALL..., bei der alle relevanten Informationen, und *ASSIGNED..., bei der nur ein Teil dieser Informationen ausgegeben wird.
Die Templates, die bei der ETR-Analyse berücksichtigt werden, können in folgende Klassen eingeteilt werden:
Templates, die in der Übersetzungseinheit explizit instanziiert wurden. Diese werden bei „ALL“ ausgegeben.
Templates, die vom Prälinker der Übersetzungseinheit zugeordnet und dann darin instanziiert wurden. Die Ausgabe ist sowohl mit „ALL“ als auch mit „ASSIGNED“ möglich.
Templates, die in der Übersetzungseinheit verwendet wurden und die hier auch instanziiert werden können. Sie werden mit „ALL“ ausgegeben.
Templates, die in der Übersetzungseinheit verwendet wurden, hier aber nicht instanziiert werden können. Auch diese werden bei „ALL“ ausgegeben.
Der Inhalt einer ETR-Datei hat folgende Form:
In einer Kopfzeile wird durch Kommentare darauf hingewiesen, dass es sich um eine generierte Datei handelt.
Für jedes Template werden drei logische Zeilen erzeugt (vgl. Beispiel):
eine Kommentarzeile mit dem Text ’The following template was’
eine Kommentarzeile, die die Art der Instanz gemäß der obigen Klassifizierung angibt (z.B ’explicitly instantiated’)
eine Zeile, die die explizite Instanziierung für diese Instanz beschreibt. Diese enthält den externen Namen der Instanz. Dieser Name entspricht dem Eintrag in der ii-Datei (siehe Abschnitt „Das Tool II-UPDATE“) und kann auch dem Binder-Listing bzw. der Binder-Fehlerliste entnommen werden
Hinweise
Sind die oben angegebenen Zeilen zu lang, so werden sie mit dem in C++ üblichen„Backslash newline“ umgebrochen.
Die Reihenfolge der ausgegebenen Templates ist nicht definiert. Nach einer Recompilierung oder einer Änderung der Source kann die Reihenfolge anders sein.
Die logische Zeile drei ist besonders interessant für die Übernahme in eine Source.
Kommentare sind grundsätzlich in Englisch.
Für die Nutzung der ETR-Datei erscheinen folgende zwei Szenarien sinnvoll:
Der Compiler wird während der Entwicklung mit der Option INSTANTIATION=*AUTO der SDF-Anweisung MODIFY-SOURCE-PROPERTIES und der Option GENERATE-ETR-FILE=*ASSIGNED der SDF-Anweisung MODIFY-DIAGNOSTIC-PROPERTIES aufgerufen.
Die in den ETR-Dateien ausgegebenen Instanziierungs-Anweisungen werden in die zugehörigen Sourcen mit aufgenommen. Der Produktivbetrieb wird dann mit der Option INSTANTIATION=*NONE bzw. *AUTO in der SDF-Anweisung MODIFY-SOURCE-PROPERTIES beim nächsten Compile-Aufruf vorgenommen.
Der Vorteil dieser Variante liegt in der deutlich reduzierten Zeit für das Prälinken im Produktivbetrieb.Der Compiler wird während der Entwicklung mit der Option INSTANTIATION=*NONE und der Option GENERATE-ETR-FILE=*ALL-INSTANTIATIONS (SDF-Anweisungen wie oben) aufgerufen.
Nach dem Binden prüft der Entwickler jeden ungelösten Externverweis, ob dies ein Template ist und wenn ja, wo es instanziiert werden kann. Hilfreich dabei sind die ausgegebenen externen Namen. Anschließend wählt der Entwickler eine Source für die Instanziierung aus und nimmt die Instanziierungs-Anweisungen dort auf. Außerdem müssen noch die richtigen Header-Files inkludiert werden.
In dieser Variante ist viel manuelle Arbeit erforderlich. Der Aufruf des Prälinkers kann allerdings dabei entfallen.
Dieses Vorgehen erlaubt eine genaue Kontrolle über die Platzierung der Instanzen (wichtig z. B. bei Komponenten mit hohen Performance-Ansprüchen).
Beispiel 1
für eine ETR-Datei, die beim Übersetzen zweier Dateien x.c und y.c entsteht:
Beim Übersetzen wurden folgende Anweisungen verwendet:
//MOD-DIAG GEN-ETR=ALL
//COMPILE (*LIB(OLIB,X.C), *LIB(OLIB,Y.C)), MODULE-OUTPUT=*SOURCE-LOCATION
Source x.c:
template <class T> void f(T) {} template <class T> void g(T); template void f(long); void foo() { f(5); f(’a’); g(5); }
Source y.c:
template <class T> void f(T) {} void bar() { f(5); }
ETR-File x.etr (steht in Bibliothek OLIB als Element vom Typ S):
// This file is generated and will be changed when the module is compiled // The following template was // explicitly instantiated #pragma instantiate_mangled_id __1f__tm__2_l__FZ1Z_v&_ // The following template was // used in this module and can be instantiated here #pragma instantiate_mangled_id __1f__tm__2_i__FZ1Z_v&_ // The following template was // used in this module and can be instantiated here #pragma instantiate_mangled_id __1f__tm__2_c__FZ1Z_v&_ // The following template was // used in this module #pragma instantiate_mangled_id __1g__tm__2_i__FZ1Z_v&_
ETR-File y.etr (steht in Bibliothek OLIB als Element vom Typ S):
// This file is generated and will be changed when the module is compiled // The following template was // used in this module and can be instantiated here #pragma instantiate_mangled_id __1f__tm__2_i__FZ1Z_v&_
Der Benutzer kann nun entscheiden, in welcher Source er explizite Instanziierungen vornimmt (diese Entscheidung muss immer getroffen werden für Einträge mit „used in this module and can be instantiated here“), siehe Beispiel 2.
Danach muss nicht mehr mit der automatischen Template-Instanziierung weitergearbeitet werden.
Beispiel 2
Gegeben seien zwei Dateien x.c und y.c in der Bibliothek test.
Source x.c
template <class T> void f(T){} template <class T> void g(T); template void f(long); void foo() { f(5); f(’a’); g(5); }
Source y.c:
template <class T> void f(T) {} void bar() { f(5); }
Diese Programme werden mit folgenden Anweisungen erstmal übersetzt und das Prälinken durchgeführt:
//mod-source-prop instantiation=*auto //mod-diagnostic-prop generate-etr-file=*assigned-instantiations //compile *lib-elem(test, X.C), module-output=*source-location //compile *lib-elem(test, Y.C), module-output=*source-location //mod-bind-prop start-llm-creation=*yes //mod-bind-prop include=*lib-elem(test,X) //mod-bind-prop include=*lib-elem(test,Y) //bind action=*prelink
Danach existiert in der Bibliothek test folgende Datei x.etr:
// This file is generated and will be changed when the module is compiled // The following template was // instantiated automatically by the compiler #pragma instantiate_mangled_id __1f__tm__2_i__FZ1Z_v&_ // The following template was // instantiated automatically by the compiler #pragma instantiate_mangled_id __1f__tm__2_c__FZ1Z_v&_
Die wichtigen Zeilen werden dann in die Datei x.c aufgenommen, wodurch folgende Datei x1.c entsteht:
template <class T> void f(T){} template <class T> void g(T); template void f(long); void foo() { f(5); f(’a’); g(5); } #pragma instantiate_mangled_id __1f__tm__2_i__FZ1Z_v&_ #pragma instantiate_mangled_id __1f__tm__2_c__FZ1Z_v&_
Im Anschluss kann die Produktion mit folgenden Kommandos durchgeführt werden:
//mod-source-prop instantiation=*none //mod-diagnostic-prop generate-etr-file=*no //compile *lib-elem(test,X1.C), module-output=*source-location //compile *lib-elem(test,Y.C), module-output=*source-location
Beispiel 3
Folgendes Beispiel zeigt die vier Klassen von Templates, die ausgegeben werden können. Die Annahmen sind wie im Beispiel 1.
Es werden folgende Kommandos eingegeben:
//mod-source-prop instantiation=*auto //mod-diagnostic-prop generate-etr-file=*no //compile *lib-elem(test,Y.C), module-output=*source-location //mod-bind-prop start-llm-creation=*yes //mod-bind-prop include=*lib-elem(test,y) //bind action=*prelink (dadurch wird f(int) y zugeordnet) //mod-diagnostic-prop generate-etr-file=*all-instantiations //compile *lib-elem(test,X.C), module-output=*source-location //mod-bind-prop start-llm-creation=*yes //mod-bind-prop include=*lib-elem(test,X) //mod-bind-prop include=*lib-elem(test,Y) //bind action=*prelink
Daraufhin entsteht in der Bibliothek test folgende ETR-Datei x.etr:
// This file is generated and will be changed when the module is compiled // The following template was // explicitly instantiated #pragma instantiate_mangled_id __1f__tm__2_l__FZ1Z_v&_ // The following template was // used in this module and can be instantiated here #pragma instantiate_mangled_id __1f__tm__2_i__FZ1Z_v&_ // The following template was // instantiated automatically by the compiler #pragma instantiate_mangled_id __1f__tm__2_c__FZ1Z_v&_ // The following template was // used in this module #pragma instantiate_mangled_id __1g__tm__2_i__FZ1Z_v&_