Die Sprache C++ beinhaltet das Konzept der Templates. Ein Template ist die Beschreibung einer Klasse oder Funktion, die als Modell für eine Familie von abgeleiteten Klassen oder Funktionen dient. So kann man z.B. ein Template für eine Stack
-Klasse schreiben und als Integer-Stack, Float-Stack oder einen Stack für einen beliebigen benutzerdefinierten Typ verwenden. Im Quellcode könnten diese dann beispielsweise Stack<int>
, Stack<float>
und Stack<X>
genannt werden. Aus der einmaligen Beschreibung eines Templates für einen Stack im Quellcode kann der Compiler Instanzen des Templates für jeden benötigten Typ generieren.
Die jeweilige Instanz eines Klassen-Templates wird immer dann erzeugt, wenn sie während der Übersetzung benötigt wird.
Demgegenüber werden die Instanzen von Funktions-Templates sowie von Elementfunktionen oder statische Datenelemente eines Klassen-Templates (im Folgenden Template-Einheiten genannt) nicht notwendigerweise sofort erzeugt. Die wichtigsten Gründe hierfür sind:
Bei Template-Einheiten mit externer Linkage (Funktionen und statische Datenelemente) ist es wichtig, programmweit nur eine einzige Kopie der instanziierten Template-Einheit zu haben.
Gemäß des C++ Standard ist es erlaubt, eine Spezialisierung für eine Template-Einheit zu schreiben. Das heißt, der Programmierer kann für einen bestimmten Datentyp eine spezielle Implementierung anbieten, die an Stelle der generierten Instanz benutzt wird. Da der Compiler beim Übersetzen einer Referenz auf eine Template-Einheit im C++V3 Modus nicht wissen kann, ob es Spezialisierungen dieser Template-Einheit in einer anderen Übersetzungseinheit gibt, darf er nicht sofort die Instanz generieren.
Template-Funktionen, die nicht referenziert werden, sollen gemäß des C++ Standard nicht übersetzt und auf Fehler überprüft werden. Deshalb sollte die Referenz auf ein Klassen-Template nicht bewirken, dass automatisch alle Elementfunktionen dieser Klasse instanziiert werden.
Bestimmte Template-Einheiten wie z.B. Inline-Funktionen werden immer instanziiert, wenn sie benutzt werden.
Die oben aufgeführten Anforderungen machen deutlich, dass der Compiler, wenn er für die gesamte Instanziierung verantwortlich ist („automatische“ Instanziierung), diese nur programmweit sinnvoll durchführen kann. Das heißt, er kann die Instanziierung von Template-Einheiten erst dann durchführen, wenn ihm der Quellcode sämtlicher Übersetzungseinheiten des Programms bekannt ist.
Mit dem C/C++-Compiler steht ein Instanziierungs-Mechanismus zur Verfügung, bei dem die automatische Instanziierung zum Binde-Zeitpunkt, und zwar mithilfe eines „Prälinkers“ durchgeführt wird. Nähere Einzelheiten siehe Abschnitt „Automatische Instanziierung“.
Für die explizite Kontrolle der Instanziierung durch den Programmierer stehen durch Optionen wählbare Instanziierungsmodi sowie #pragma
-Anweisungen zur Verfügung:
Die Optionen zur Auswahl der Instanziierungsmodi lauten
MODIFY-SOURCE-PROP INSTANTIATION=*NONE / *AUTO / *LOCAL / *ALL (siehe "MODIFY-SOURCE-PROPERTIES").Die Instanziierung einzelner Templates oder auch einer Gruppe von Templates kann mit den Pragmas
instantiate
,do_not_instantiate
undcan_instantiate
gesteuert werden (siehe "Pragmas zur Steuerung der Template-Instanziierung").
Wichtige Hinweise
Die bei diesem Compiler voreingestellte Methode zur Template-Instanziierung (automatische Instanziierung durch den Prälinker und implizites Inkludieren) ist auch die von uns empfohlene Methode. Von der Möglichkeit, über Optionen steuerbar, von diesem voreingestellten Verfahren abzuweichen, sollte nur in Ausnahmefällen Gebrauch gemacht werden und nur bei genauester Kenntnis der gesamten Applikation einschließlich aller definierten und benutzten Templates.
Implizites Inkludieren: Das implizite Inkludieren darf nicht ausgeschaltet werden (mit IMPLICIT-INCLUDE=*NO), wenn Templates aus der C++ V3-Bibliothek (SYSLNK.CRTE.STDCPP) benutzt werden, da in diesem Fall Definitionen nicht gefunden werden.
Instanziierungsmodi !=
INSTANTIATION=*AUTO: Hier besteht die Gefahr, dass unbefriedigte Externverweise (*NONE), Duplikate (*ALL) oder ggf. Ablauffehler (*LOCAL) auftreten können.