Namensräume
Varianten
Aktionen

Templates

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
Sonstiges
 
 

Ein Template ist eine C++-Entität, die eines der folgenden Elemente definiert

(seit C++11)
(seit C++14)
(seit C++20)

Templates werden durch einen oder mehrere Template-Parameter parametrisiert, und zwar drei Arten: Typ-Template-Parameter, Nicht-Typ-Template-Parameter und Template-Template-Parameter.

Wenn Template-Argumente bereitgestellt werden oder, für Funktions- und Klassen(seit C++17)-Templates nur, abgeleitet werden, werden sie für die Template-Parameter substituiert, um eine *Spezialisierung* des Templates zu erhalten, d.h. einen spezifischen Typ oder einen spezifischen Funktions-Lvalue.

Spezialisierungen können auch explizit bereitgestellt werden: Vollständige Spezialisierungen sind für Klassen, Variablen(seit C++14) und Funktionstemplates erlaubt, partielle Spezialisierungen sind nur für Klassentemplates und Variable Templates(seit C++14) erlaubt.

Wenn eine Klassen-Template-Spezialisierung in einem Kontext referenziert wird, der einen vollständigen Objekttyp erfordert, oder wenn eine Funktions-Template-Spezialisierung in einem Kontext referenziert wird, der die Existenz einer Funktionsdefinition erfordert, wird das Template *instanziiert* (der Code dafür wird tatsächlich kompiliert), es sei denn, das Template wurde bereits explizit spezialisiert oder instanziiert. Die Instanziierung eines Klassentemplates instanziiert keine seiner Member-Funktionen, es sei denn, sie werden ebenfalls verwendet. Zur Link-Zeit werden identische Instanziierungen, die von verschiedenen Translation Units generiert wurden, zusammengeführt.

Die Definition eines Klassentemplates muss an der Stelle der impliziten Instanziierung sichtbar sein, weshalb Template-Bibliotheken typischerweise alle Template-Definitionen in Headern bereitstellen (z.B. die meisten Boost-Bibliotheken sind Header-only).

Inhalt

[edit] Syntax

template <parameter-list > requires-clause (optional) declaration (1)
export template <parameter-list > declaration (2) (bis C++11)
template <parameter-list > concept concept-name = constraint-expression ; (3) (seit C++20)
parameter-liste - eine nicht-leere, durch Kommas getrennte Liste der Template-Parameter, von denen jeder entweder ein Nicht-Typ-Parameter, ein Typ-Parameter, ein Template-Parameter, oder ein Parameter-Pack von beliebigen davon(seit C++11) ist.
requires-clause - (seit C++20) eine Requires-Klausel, die die Constraints für die Template-Argumente angibt.
Deklaration - Deklaration eines Klasse (einschließlich struct und union), eines Member-Klasse oder Member-Enumerationstyps, einer Funktion oder Member-Funktion, eines statischen Datenmembers auf Namespace-Ebene, einer Variablen oder eines statischen Datenmembers auf Klassenebene(seit C++14), oder eines Alias-Templates(seit C++11). Es kann auch eine Template-Spezialisierung definieren.
Konzeptname
Constraint-Ausdruck
- siehe Constraints und Konzepte

export war ein optionaler Modifikator, der das Template als *exportiert* deklarierte (wenn mit einem Klassentemplate verwendet, wurden auch alle seine Member exportiert). Dateien, die exportierte Templates instanziierten, mussten ihre Definitionen nicht einschließen: die Deklaration war ausreichend. Implementierungen von export waren selten und stimmten in Details nicht überein.

(bis C++11)

[edit] Template-Identifikatoren

Ein Template-Identifikator hat eine der folgenden Syntaxen

template-name <template-argument-list (optional)> (1)
operatorop <template-argument-list (optional)> (2)
operator "" identifier <template-argument-list (optional)> (3) (seit C++11)
(veraltet)
operator user-defined-string-literal <template-argument-list (optional)> (4) (seit C++11)
1) Ein *einfacher Template-Identifikator*.
2) Ein Operator-Funktions-Template-Identifikator.
3,4) Ein Literal-Operator-Funktions-Template-Identifikator.
template-name - ein Bezeichner, der ein Template benennt
op - ein überladbarer Operator
identifier - ein Bezeichner
user-defined-string-literal - "" gefolgt von einem Bezeichner


Ein einfacher Template-Identifikator, der ein Klassentemplate benennt, benennt eine Klasse.

Ein Template-Identifikator, der ein Alias-Template benennt, benennt einen Typ.

Ein Template-Identifikator, der eine Funktions-Template-Spezialisierung benennt, benennt eine Funktion.

Wenn alle folgenden Bedingungen erfüllt sind, ist ein Template-Identifikator *gültig* 

  • Es gibt höchstens so viele Argumente wie Parameter oder ein Parameter ist ein Template Parameter-Pack(seit C++11).
  • Für jeden nicht-deduzierbaren Nicht-Pack(seit C++11) Parameter, der keinen Standard-Template-Argument hat, gibt es ein Argument.
  • Jedes Template-Argument passt zum entsprechenden Template-Parameter.
  • Die Substitution jedes Template-Arguments in die folgenden Template-Parameter (falls vorhanden) ist erfolgreich.
  • Wenn der Template-Identifikator nicht-abhängig ist, werden die zugehörigen Constraints wie unten angegeben erfüllt.
(seit C++20)

Ein ungültiges einfaches Template-ID ist ein Kompilierungsfehler, es sei denn, es benennt eine Funktions-Template-Spezialisierung (in diesem Fall kann SFINAE angewendet werden).

template<class T, T::type n = 0>
class X;
 
struct S
{
    using type = int;
};
 
using T1 = X<S, int, int>; // error: too many arguments
using T2 = X<>;            // error: no default argument for first template parameter
using T3 = X<1>;           // error: value 1 does not match type-parameter
using T4 = X<int>;         // error: substitution failure for second template parameter
using T5 = X<S>;           // OK

Wenn der template-name eines einfachen Template-IDs ein eingeschränktes Nicht-Funktions-Template oder einen eingeschränkten Template-Template-Parameter benennt, aber kein Member-Template, das ein Mitglied einer unbekannten Spezialisierung ist, und alle Template-Argumente im einfachen Template-ID nicht-abhängig sind, müssen die zugehörigen Constraints des eingeschränkten Templates erfüllt sein.

template<typename T>
concept C1 = sizeof(T) != sizeof(int);
 
template<C1 T>
struct S1 {};
 
template<C1 T>
using Ptr = T*;
 
S1<int>* p;                      // error: constraints not satisfied
Ptr<int> p;                      // error: constraints not satisfied
 
template<typename T>
struct S2 { Ptr<int> x; };       // error, no diagnostic required
 
template<typename T>
struct S3 { Ptr<T> x; };         // OK, satisfaction is not required
 
S3<int> x;                       // error: constraints not satisfied
 
template<template<C1 T> class X>
struct S4
{
    X<int> x;                    // error, no diagnostic required
};
 
template<typename T>
concept C2 = sizeof(T) == 1;
 
template<C2 T> struct S {};
 
template struct S<char[2]>;      // error: constraints not satisfied
template<> struct S<char[2]> {}; // error: constraints not satisfied
(seit C++20)

Wenn alle folgenden Bedingungen erfüllt sind, sind zwei Template-Identifikatoren *gleich* 

  • Ihre template-name oder Operatoren beziehen sich auf dasselbe Template.
  • Ihre entsprechenden Typ-Template-Argumente sind derselbe Typ.
  • Die durch ihre entsprechenden Nicht-Typ-Template-Argumente bestimmten Template-Parameterwerte sind Template-Argument-äquivalent.
  • Ihre entsprechenden Template-Template-Argumente beziehen sich auf dasselbe Template.

Zwei Template-Identifikatoren, die gleich sind, beziehen sich auf dieselbe Variable,(seit C++14) Klasse oder Funktion.

[edit] Templated Entity

Eine *templated entity* (oder in einigen Quellen "temploid") ist jede Entität, die innerhalb einer Template-Definition definiert (oder, für einen Lambda-Ausdruck, erstellt)(seit C++11) wird. Alle folgenden sind templated entities

  • ein Klassen-/Funktions/Variablen(seit C++14)-Template
(seit C++20)
  • ein Mitglied einer templated entity (z.B. eine Nicht-Template-Member-Funktion eines Klassentemplates)
  • ein Aufzähler einer Aufzählung, die eine templated entity ist
  • jede Entität, die innerhalb einer templated entity definiert oder erstellt wird: eine lokale Klasse, eine lokale Variable, eine Freundschaftsfunktion usw.
  • der Closur-Typ eines Lambda-Ausdrucks, der in der Deklaration einer templated entity vorkommt
(seit C++11)

Zum Beispiel in

template<typename T>
struct A
{
    void f() {}
};

ist die Funktion `A::f` kein Funktionstemplates, wird aber trotzdem als templated betrachtet.


Eine *templated function* ist ein Funktionstemplates oder eine Funktion, die templated ist.

Eine *templated class* ist ein Klassentemplate oder eine Klasse, die templated ist.

Eine *templated variable* ist ein Variable Template oder eine Variable, die templated ist.

(seit C++14)

[edit] Schlüsselwörter

template, export

[edit] Fehlerberichte

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 2293 C++98 Die Regeln zur Bestimmung, ob ein Template
Identifikator gültig ist, wurden nicht bereitgestellt
bereitgestellt
CWG 2682 C++98
C++14
Die Definitionen von templated function/template class
(C++98)/templated variable (C++14) fehlten
hinzugefügt
P2308R1 C++98 Zwei Template-Identifikatoren waren unterschiedlich, wenn ihre
entsprechenden Nicht-Typ-Template-Argumente
nicht template-argument-equivalent sind
Sie sind unterschiedlich, wenn ihre entsprechenden
Nicht-Typ-Template-Parameterwerte
nicht template-argument-equivalent sind

[edit] Siehe auch

C-Dokumentation für Generische Auswahl