Klassenschablone
Ein Klassentemplate definiert eine Familie von Klassen.
Inhalt |
[bearbeiten] 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) | (in C++11 entfernt) | |||||||
[bearbeiten] Erklärung
| class-declaration | - | eine Klassendeklaration. Der deklarierte Klassenname wird zu einem Template-Namen. |
| parameter-liste | - | eine nicht-leere, durch Kommas getrennte Liste der Template-Parameter, wobei jeder davon entweder ein Nicht-Typ-Parameter, ein Typ-Parameter, ein Template-Parameter oder ein Parameter-Pack aus einem beliebigen dieser ist. |
| constraint | - | ein Constraint-Ausdruck, der die vom Klassentemplate akzeptierten Template-Parameter einschränkt |
export war ein optionaler Modifikator, der das Template als exportiert deklarierte (wenn er mit einem Klassentemplate verwendet wurde, deklarierte er auch 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 überein. |
(bis C++11) |
[bearbeiten] Klassentemplate-Instanziierung
Ein Klassentemplate ist für sich allein kein Typ, kein Objekt und keine andere Entität. Aus einer Quelldatei, die nur Template-Definitionen enthält, wird kein Code generiert. Damit irgendein Code erscheint, muss ein Template instanziiert werden: die Template-Argumente müssen bereitgestellt werden, damit der Compiler eine tatsächliche Klasse (oder aus einem Funktionstemplat ein tatsächliches Funktion) generieren kann.
[bearbeiten] 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, des Structs oder Unions, auf die sie sich bezieht. Sie kann an jeder Stelle im Programm nach der Template-Definition erscheinen und ist für eine gegebene argument-list nur einmal im gesamten Programm zulässig, ohne Meldung erforderlich.
|
Eine explizite Instanziierungsdeklaration (ein extern template) überspringt den Schritt der impliziten Instanziierung: Der Code, der sonst eine implizite Instanziierung verursachen würde, verwendet stattdessen die explizite Instanziierungsdefinition, die anderswo bereitgestellt wird (was zu Link-Fehlern führt, wenn keine solche Instanziierung existiert). Dies kann verwendet werden, um Kompilierungszeiten zu reduzieren, indem eine Template-Instanziierung in allen bis auf einer der Quellcodedateien, die sie verwenden, explizit deklariert und in der verbleibenden Datei explizit definiert wird. |
(seit C++11) |
Klassen, Funktionen, Variablen(seit C++14) und Member-Template-Spezialisierungen können aus ihren Templates explizit instanziiert werden. Member-Funktionen, Member-Klassen und statische Datenmember von Klassentemplates können aus ihren Member-Definitionen explizit instanziiert werden.
Explizite Instanziierung kann nur im umschließenden Namespace des Templates erscheinen, es sei denn, sie verwendet qualified-id
namespace N { template<class T> class Y // template definition { void mf() {} }; } // template class Y<int>; // error: class template Y not visible in the global namespace using N::Y; // template class Y<int>; // error: explicit instantiation outside // of the namespace of the template template class N::Y<char*>; // OK: explicit instantiation template void N::Y<double>::mf(); // OK: explicit instantiation
Explizite Instanziierung hat keine Auswirkung, wenn eine explizite Spezialisierung für dieselbe Menge von Template-Argumenten zuvor aufgetreten ist.
Nur die Deklaration muss sichtbar sein, wenn eine Funktionstemplate, eine Variable vom Typ Template(seit C++14), eine Member-Funktion oder ein statischer Datenmember eines Klassentemplates oder eine Member-Funktions-Template explizit instanziiert wird. Die vollständige Definition muss vor der expliziten Instanziierung eines Klassentemplates, einer Member-Klasse eines Klassentemplates oder eines Member-Klassen-Templates erscheinen, es sei denn, eine explizite Spezialisierung mit denselben Template-Argumenten ist zuvor aufgetreten.
Wenn eine Funktionstemplate, eine Variable vom Typ Template(seit C++14), eine Member-Funktions-Template oder eine Member-Funktion oder ein statischer Datenmember eines Klassentemplates mit einer expliziten Instanziierungsdefinition explizit instanziiert wird, muss die Template-Definition in derselben Übersetzungseinheit vorhanden sein.
Wenn eine explizite Instanziierung einen Klassentemplate-Spezialisierung benennt, dient sie als explizite Instanziierung desselben Typs (Deklaration oder Definition) jeder ihrer nicht geerbten, nicht-Template-Member, die in der Übersetzungseinheit nicht zuvor explizit spezialisiert wurden. Wenn diese explizite Instanziierung eine Definition ist, ist sie auch eine explizite Instanziierungsdefinition nur für die Member, die bis zu diesem Zeitpunkt definiert wurden.
Explizite Instanziierungsdefinitionen ignorieren Zugriffsmodifizierer: Parametertypen und Rückgabetypen können privat sein.
[bearbeiten] 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 spezifische 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 Member des Klassentemplates: Wenn der Member nicht im Programm verwendet wird, wird er nicht instanziiert und erfordert keine Definition.
template<class T> struct Z // template definition { void f() {} void g(); // never defined }; template struct Z<double>; // explicit instantiation of Z<double> Z<int> a; // implicit instantiation of Z<int> Z<char>* p; // nothing is instantiated here p->f(); // implicit instantiation of Z<char> and Z<char>::f() occurs here. // Z<char>::g() is never needed and never instantiated: // it does not have to be defined
Wenn ein Klassentemplate an der Stelle der Instanziierung deklariert, aber nicht definiert wurde, ergibt die Instanziierung einen unvollständigen Klassentyp
template<class T> class X; // declaration, not definition X<char> ch; // error: incomplete type X<char>
| Lokale Klassen und alle Templates, die in ihren Membern verwendet werden, werden als Teil der Instanziierung der Entität instanziiert, innerhalb derer die lokale Klasse oder Enumeration deklariert ist. | (seit C++17) |
[bearbeiten] Schlüsselwörter
export(bis C++11)extern(seit C++11)
[bearbeiten] Siehe auch
- Template-Parameter und -Argumente ermöglichen die Parametrisierung von Templates
- Funktionstemplatedeklaration deklariert ein Funktionstemplate
- Template-Spezialisierung definiert ein bestehendes Template für einen bestimmten Typ
- Parameter-Packs ermöglichen die Verwendung von Typenlisten in Templates (seit C++11)