Namespaces
Variants

Class template

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Class template
Function template
Miscellaneous

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
1) Explizite Instanziierungsdefinition
2) Explizite Instanziierungsdeklaration

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