Im automatischen Instanziierungsmodus können Instanzen für Template-Einheiten (Funktions-Templates, Elementfunktionen und statische Datenelemente von Klassen-Templates) nur generiert werden, wenn das Objekt folgende Bedingungen erfüllt:
es ist nicht Bestandteil einer
.a
-Bibliothekes enthält eine Referenz auf die Template-Einheit oder das Pragma
can_instantiate
für diese Template-Einheitund es enthält alle für die Instanziierung notwendigen Definitionen.
Eine Bibliothek, die zu ihrer Implementierung Instanzen benötigt, muss entweder diese Instanzen enthalten oder spezielle Include-Dateien mit can_instantiate
-Pragmas bereitstellen. Diese beiden Möglichkeiten werden im Folgenden erläutert.
Die Bibliothek enthält alle benötigten Instanzen
Hierbei ist darauf zu achten, dass bei Verwendung mehrerer Bibliotheken keine Duplikate entstehen.
Um Template-Einheiten in Bibliotheken zu instanziieren, haben Sie folgende Möglichkeiten:
Automatische Instanziierung der Template-Einheiten durch den Prälinker mithilfe der Option
-y
(siehe "Optionen zur Auswahl von Übersetzungsphasen").Achtung
Es besteht die Gefahr, dass bei der Verwendung mehrerer Bibliotheken, die die gleiche Instanz benötigen, Duplikate auftreten, da nicht pro Instanz ein separates Objekt erzeugt wird. Hier kann die Verwendung der Option
-T add_prelink_files
Abhilfe schaffen (siehe "Template-Optionen").Explizite Instanziierung aller Template-Einheiten mit der Instanziierungsanweisung
template
declaration oder mit dem Pragmainstantiate
.Hierbei sollte darauf geachtet werden, dass pro Instanz ein separates Objekt erzeugt wird.
Beispiel
Es seien gegeben:
eine Bibliothek
l.a
mit Referenzen auf die Instanzent_list(Foo1)
undt_list(Foo2),
eine Include-Datei
listFoo.h
mit den Deklarationen vont_list
,Foo1
undFoo2
und eine Quelldatei
listFoo.C
mit den Definitionen vont_list
,Foo1
undFoo2
.
// l.h #ifndef L_H #define L_H #include "listFoo.h" void g(); #endif // l.C (l.o ist ein Element von l.a) #include "l.h" void g() { Foo1 f1; Foo2 f2; //... t_list(f1); t_list(f2); //... } //listFoo.h #ifndef LIST_FOO_H #define LIST_FOO_H template <class T> void t_list (T t); class Foo1 {...}; class Foo2 {...}; #endif //listFoo.C template <class T> class t_list (T t) { ... };
In der Bibliothek
l.a
sind die referenzierten Instanzen jeweils in separaten Objekten enthalten.// lf1.C : lf1.o ist ein Element von l.a // und enthält eine explizite Instanziierung von t_list(Foo1) #include "listFoo.h" template void t_list(Foo1); // lf2.C : lf2.o ist ein Element von l.a // und enthält eine explizite Instanziierung von t_list(Foo2) #include "listFoo.h" #pragma instantiate void t_list(Foo2)
Die Include-Dateien enthalten
can_instantiate
-Pragmas für alle benötigten Instanzen.Beispiel
Es seien gegeben:
eine Bibliothek
l.a
mit einer Referenz auf die Instanzt_list(Foo)
eine Include-Datei
listFoo.h
mit den Deklarationen vont_list
undFoo
und eine Quelldatei
listFoo.C
mit den Definitionen vont_list
undFoo
// l.h #ifndef L_H #define L_H #include "listFoo.h" void g(); #endif // l.C (l.o ist ein Element von l.a) #include "l.h" void g() { Foo f; //... t_list(f); //... } //listFoo.h #ifndef LIST_FOO_H #define LIST_FOO_H template <class T> void t_list (T t); class Foo {...}; #pragma can_instantiate t_list(Foo) #endif //listFoo.C template <class T> void t_list (T t) {...};
Das Objekt
user.o
und die Bibliothekl.a
werden zusammengebunden(CC user.o l.a).
// user.C #include "l.h" int f () { g(); }
user.C
inkludiertl.h
undl.h
inkludiert wiederumlistFoo.h
. Somit enthältuser.C
den Hinweis, dasst_list(Foo)
instanziiert werden kann.Bei der automatischen Instanziierung durch den Prälinker wird nur eine Instanz
t_list(Foo)
generiert.Hinweis
Damit die benötigten Instanzen generiert werden können, muss das Pragmacan_instantiate
in einer Include-Datei der Bibliothek enthalten sein, die dann jeweils von den Benutzerprogrammen inkludiert wird.