Class template
Eine Klassenvorlage definiert eine Familie von Klassen.
Inhaltsverzeichnis |
Syntax
template
<
parameter-list
>
class-declaration
|
(1) | ||||||||
template
<
parameter-list
>
requires
constraint
class-declaration
|
(2) | (seit C++20) | |||||||
export
template
<
parameter-list
>
class-declaration
|
(3) | (entfernt in C++11) | |||||||
Erklärung
| class-declaration | - | eine Klassendeklaration . Der deklarierte Klassenname wird zu einem Template-Namen. |
| parameter-list | - | eine nicht-leere, kommagetrennte Liste der Template-Parameter , von denen jeder entweder ein konstanter Parameter , ein Typ-Parameter , ein Template-Parameter oder ein Parameter-Pack von diesen ist. |
| constraint | - | ein Constraint-Ausdruck , der die von diesem Klassentemplate akzeptierten Template-Parameter einschränkt |
export
war ein optionaler Modifikator, der das Template als
exportiert
deklarierte (bei Verwendung mit einem Klassentemplate deklarierte es ebenfalls alle seine Member als exportiert). Dateien, die exportierte Templates instanziierten, mussten deren Definitionen nicht einschließen: die Deklaration war ausreichend. Implementierungen von
export
waren selten und stimmten in Details nicht miteinander überein.
|
(bis C++11) |
Klassen-Template-Instanziierung
Eine Klassenvorlage an sich ist kein Typ, kein Objekt oder eine andere Entität. Aus einer Quelldatei, die nur Vorlagendefinitionen enthält, wird kein Code generiert. Damit Code erzeugt wird, muss eine Vorlage instanziiert werden: Die Vorlagenargumente müssen bereitgestellt werden, damit der Compiler eine tatsächliche Klasse (oder Funktion, aus einer Funktionsvorlage) generieren kann.
Explizite Instanziierung
template
class-key
template-name
<
argument-list
>
;
|
(1) | ||||||||
extern
template
class-key
template-name
<
argument-list
>
;
|
(2) | (seit C++11) | |||||||
| class-key | - |
class
,
struct
oder
union
|
Eine explizite Instanziierungsdefinition erzwingt die Instanziierung der Klasse, Struktur oder Union, auf die sie sich bezieht. Sie kann im Programm überall nach der Template-Definition erscheinen und darf für eine gegebene argument-list nur einmal im gesamten Programm vorkommen, keine Diagnose erforderlich.
|
Eine explizite Instanziierungsdeklaration (eine extern template) überspringt den Schritt der impliziten Instanziierung: Code, der andernfalls eine implizite Instanziierung verursachen würde, verwendet stattdessen die an anderer Stelle bereitgestellte explizite Instanziierungsdefinition (was zu Linker-Fehlern führt, falls keine solche Instanziierung existiert). Dies kann verwendet werden, um Kompilierzeiten zu reduzieren, indem eine Template-Instanziierung explizit in allen bis auf einer der sie verwendenden Quelldateien deklariert und in der verbleibenden Datei explizit definiert wird. |
(since C++11) |
Klassen, Funktionen , Variablen (since C++14) und Spezialisierungen von Member-Templates können explizit aus ihren Templates instanziiert werden. Member-Funktionen, Member-Klassen und statische Datenelemente von Klassentemplates können explizit aus ihren Member-Definitionen instanziiert werden.
Explizite Instanziierung kann nur im umschließenden Namensraum der Vorlage erscheinen, es sei denn, sie verwendet qualifizierte ID:
namespace N { template<class T> class Y // Template-Definition { void mf() {} }; } // template class Y<int>; // Fehler: Klassen-Template Y im globalen Namespace nicht sichtbar using N::Y; // template class Y<int>; // Fehler: Explizite Instanziierung außerhalb // des Namespaces des Templates template class N::Y<char*>; // OK: Explizite Instanziierung template void N::Y<double>::mf(); // OK: Explizite Instanziierung
Explizite Instanziierung hat keine Auswirkung, wenn zuvor eine explizite Spezialisierung für denselben Satz von Template-Argumenten aufgetreten ist.
Bei der expliziten Instanziierung einer Funktionsvorlage , einer Variablenvorlage (seit C++14) , einer Elementfunktion oder statischen Elementvariable einer Klassenvorlage, oder einer Elementfunktionsvorlage muss nur die Deklaration sichtbar sein. Die vollständige Definition muss vor der expliziten Instanziierung einer Klassenvorlage, einer Elementklasse einer Klassenvorlage oder einer Elementklassenvorlage erscheinen, es sei denn, eine explizite Spezialisierung mit denselben Template-Argumenten ist zuvor erschienen.
Wenn eine Funktionsvorlage , Variablenvorlage (since C++14) , Memberfunktionsvorlage oder Memberfunktion oder statisches Datenelement einer Klassenvorlage mit einer expliziten Instanziierungsdefinition explizit instanziiert wird, muss die Vorlagendefinition in derselben Übersetzungseinheit vorhanden sein.
Wenn eine explizite Instanziierung eine Klassentemplatespezialisierung benennt, dient sie als explizite Instanziierung derselben Art (Deklaration oder Definition) für jedes ihrer nicht geerbten Nicht-Template-Member, das zuvor nicht in der Übersetzungseinheit explizit spezialisiert wurde. Wenn diese explizite Instanziierung eine Definition ist, ist sie auch nur für die Member, die zu diesem Zeitpunkt definiert wurden, eine explizite Instanziierungsdefinition.
Explizite Instanziierungsdefinitionen ignorieren Zugriffsspezifizierer von Mitgliedern: Parametertypen und Rückgabetypen können privat sein.
Implizite Instanziierung
Wenn Code in einem Kontext auf ein Template verweist, der einen vollständig definierten Typ erfordert, oder wenn die Vollständigkeit des Typs den Code beeinflusst, und dieser bestimmte Typ nicht explizit instanziiert wurde, tritt eine implizite Instanziierung auf. Zum Beispiel, wenn ein Objekt dieses Typs konstruiert wird, aber nicht, wenn ein Zeiger auf diesen Typ konstruiert wird.
Dies gilt für die Mitglieder des Klassentemplates: Solange das Mitglied nicht im Programm verwendet wird, wird es nicht instanziiert und erfordert keine Definition.
template<class T> struct Z // Template-Definition { void f() {} void g(); // niemals definiert }; template struct Z<double>; // explizite Instanziierung von Z<double> Z<int> a; // implizite Instanziierung von Z<int> Z<char>* p; // hier wird nichts instanziiert p->f(); // implizite Instanziierung von Z<char> und Z<char>::f() erfolgt hier. // Z<char>::g() wird niemals benötigt und niemals instanziiert: // es muss nicht definiert werden
Wenn eine Klassenvorlage deklariert, aber nicht definiert wurde, zum Zeitpunkt der Instanziierung, ergibt die Instanziierung einen unvollständigen Klassentyp:
template<class T> class X; // Deklaration, keine Definition X<char> ch; // Fehler: unvollständiger Typ X<char>
| Lokale Klassen und alle in ihren Mitgliedern verwendeten Templates werden als Teil der Instanziierung der Entität instanziiert, in der die lokale Klasse oder Enumeration deklariert ist. | (seit C++17) |
Schlüsselwörter
export (bis C++11) extern (seit C++11)
Siehe auch
- Template-Parameter und Argumente ermöglichen die Parametrisierung von Templates
- Funktions-Template-Deklaration deklariert ein Funktions-Template
- Template-Spezialisierung definiert ein bestehendes Template für einen spezifischen Typ
- Parameter-Packs ermöglichen die Verwendung von Typenlisten in Templates (seit C++11)