Namensräume
Varianten
Aktionen

Klassenschablone

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Klassenschablone
Funktionsschablone
Sonstiges
 
 
 
 

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

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