Vorlagen (C++)Templates (C++)

Vorlagen sind die Grundlage für die allgemeine Programmierung in C++.Templates are the basis for generic programming in C++. Als stark typisierte Sprache erfordert C++, dass alle Variablen einen bestimmten Typ haben, entweder explizit vom Programmierer deklariert oder vom Compiler abgeleitet werden.As a strongly-typed language, C++ requires all variables to have a specific type, either explicitly declared by the programmer or deduced by the compiler. Viele Datenstrukturen und Algorithmen sehen jedoch gleich aus, unabhängig davon, auf welchem Typ sie arbeiten.However, many data structures and algorithms look the same no matter what type they are operating on. Mithilfe von Vorlagen können Sie die Vorgänge einer Klasse oder Funktion definieren und dem Benutzer die konkreten Typen angeben, an denen diese Vorgänge ausgeführt werden sollen.Templates enable you to define the operations of a class or function, and let the user specify what concrete types those operations should work on.

Definieren und Verwenden von VorlagenDefining and using templates

Eine Vorlage ist ein Konstrukt, das einen normalen Typ oder eine normale Funktion zur Kompilierungszeit generiert, basierend auf Argumenten, die der Benutzer für die Vorlagenparameter bereitstellt.A template is a construct that generates an ordinary type or function at compile time based on arguments the user supplies for the template parameters. Sie können z. B. eine Funktionsvorlage wie folgt definieren:For example, you can define a function template like this:

template <typename T>
T minimum(const T& lhs, const T& rhs)
{
    return lhs < rhs ? lhs : rhs;
}

Der obige Code beschreibt eine Vorlage für eine generische Funktion mit einem einzelnen Typparameter T, dessen Rückgabewert und Aufrufparameter (lhs und rhs) alle von diesem Typ sind.The above code describes a template for a generic function with a single type parameter T, whose return value and call parameters (lhs and rhs) are all of this type. Sie können einen Typparameter ganz nach Bewilliken benennen, aber konventionell werden am häufigsten einzelne Großbuchstaben verwendet.You can name a type parameter anything you like, but by convention single upper case letters are most commonly used. T ist ein Vorlagenparameter; Das Typename-Schlüsselwort besagt, dass dieser Parameter ein Platzhalter für einen Typ ist.T is a template parameter; the typename keyword says that this parameter is a placeholder for a type. Wenn die Funktion aufgerufen wird, ersetzt T der Compiler jede Instanz von durch das Argument des konkreten Typs, das entweder vom Benutzer angegeben oder vom Compiler abgeleitet wird.When the function is called, the compiler will replace every instance of T with the concrete type argument that is either specified by the user or deduced by the compiler. Der Prozess, bei dem der Compiler eine Klasse oder Funktion aus einer Vorlage generiert, wird als Vorlageninstanziierungbezeichnet. minimum<int> ist eine Instanziierung minimum<T>der Vorlage .The process in which the compiler generates a class or function from a template is referred to as template instantiation; minimum<int> is an instantiation of the template minimum<T>.

An anderer Stelle kann ein Benutzer eine Instanz der Vorlage deklarieren, die für int spezialisiert ist. Angenommen, get_a() und get_b() sind Funktionen, die eine int zurückgeben:Elsewhere, a user can declare an instance of the template that is specialized for int. Assume that get_a() and get_b() are functions that return an int:

int a = get_a();
int b = get_b();
int i = minimum<int>(a, b);

Da es sich jedoch um eine Funktionsvorlage handelt und T der Compiler den Typ der Argumente a und bableiten kann, können Sie sie wie eine gewöhnliche Funktion aufrufen:However, because this is a function template and the compiler can deduce the type of T from the arguments a and b, you can call it just like an ordinary function:

int i = minimum(a, b);

Wenn der Compiler auf diese letzte Anweisung trifft, generiert er eine neue Funktion, in der jedes Vorkommen von T in der Vorlage durch intersetzt wird:When the compiler encounters that last statement, it generates a new function in which every occurrence of T in the template is replaced with int:

int minimum(const int& lhs, const int& rhs)
{
    return lhs < rhs ? lhs : rhs;
}

Die Regeln für die Art und Weise, wie der Compiler den Typabzug in Funktionsvorlagen ausführt, basieren auf den Regeln für normale Funktionen.The rules for how the compiler performs type deduction in function templates are based on the rules for ordinary functions. Weitere Informationen finden Sie unter Überladen der Auflösung von Funktionsvorlagenaufrufen.For more information, see Overload Resolution of Function Template Calls.

TypparameterType parameters

Beachten minimum Sie in der obigen Vorlage, dass der Typparameter T in keiner Weise qualifiziert ist, bis er in den Funktionsaufrufparametern verwendet wird, wo die const- und Reference-Qualifizierer hinzugefügt werden.In the minimum template above, note that the type parameter T is not qualified in any way until it is used in the function call parameters, where the const and reference qualifiers are added.

Es gibt keine praktische Begrenzung für die Anzahl der Typparameter.There is no practical limit to the number of type parameters. Trennen Sie mehrere Parameter durch Kommas:Separate multiple parameters by commas:

template <typename T, typename U, typename V> class Foo{};

Die Schlüsselwortklasse entspricht in diesem Kontext dem Typnamen.The keyword class is equivalent to typename in this context. Sie können das vorherige Beispiel wie:You can express the previous example as:

template <class T, class U, class V> class Foo{};

Sie können den Auslassungsoperator (...) verwenden, um eine Vorlage zu definieren, die eine beliebige Anzahl von Null- oder mehr Typparametern verwendet:You can use the ellipsis operator (...) to define a template that takes an arbitrary number of zero or more type parameters:

template<typename... Arguments> class vtclass;

vtclass< > vtinstance1;
vtclass<int> vtinstance2;
vtclass<float, bool> vtinstance3;

Jeder integrierte oder benutzerdefinierte Typ kann als Typargument verwendet werden.Any built-in or user-defined type can be used as a type argument. Sie können z. B. std::vector in der Standardbibliothek verwenden, um Variablen vom MyClassTyp int, double, std::string, , const MyClass*, MyClass&, usw. zu speichern.For example, you can use std::vector in the Standard Library to store variables of type int, double, std::string, MyClass, const MyClass*, MyClass&, and so on. Die primäre Einschränkung bei der Verwendung von Vorlagen besteht darin, dass ein Typargument alle Vorgänge unterstützen muss, die auf die Typparameter angewendet werden.The primary restriction when using templates is that a type argument must support any operations that are applied to the type parameters. Wenn wir z. minimum MyClass B. die Verwendung wie in diesem Beispiel aufrufen:For example, if we call minimum using MyClass as in this example:

class MyClass
{
public:
    int num;
    std::wstring description;
};

int main()
{
    MyClass mc1 {1, L"hello"};
    MyClass mc2 {2, L"goodbye"};
    auto result = minimum(mc1, mc2); // Error! C2678
}

Ein Compilerfehler wird MyClass generiert, da er keine < Überladung für den Operator bietet.A compiler error will be generated because MyClass does not provide an overload for the < operator.

Es ist nicht erforderlich, dass die Typargumente für eine bestimmte Vorlage alle zur gleichen Objekthierarchie gehören, obwohl Sie eine Vorlage definieren können, die eine solche Einschränkung erzwingt.There is no inherent requirement that the type arguments for any particular template all belong to the same object hierarchy, although you can define a template that enforces such a restriction. Sie können objektorientierte Techniken mit Vorlagen kombinieren. Sie können z. B. einen<Abgeleiteten* in einem Vektor Basis->* speichern.You can combine object-oriented techniques with templates; for example, you can store a Derived* in a vector<Base*>. Beachten Sie, dass die Argumente Zeiger sein müssenNote that the arguments must be pointers

vector<MyClass*> vec;
   MyDerived d(3, L"back again", time(0));
   vec.push_back(&d);

   // or more realistically:
   vector<shared_ptr<MyClass>> vec2;
   vec2.push_back(make_shared<MyDerived>());

Die grundlegenden std::vector Anforderungen, die und andere T Standardbibliothekscontainer an Elemente von stellen, sind, dass T sie kopierfähig und kopierfähig sind.The basic requirements that std::vector and other standard library containers impose on elements of T is that T be copy-assignable and copy-constructible.

Nicht-Typ-ParameterNon-type parameters

Im Gegensatz zu generischen Typen in anderen Sprachen, wie z. B. C- und Java, unterstützen C++-Vorlagen Nicht-Typparameter, die auch als Wertparameter bezeichnet werden.Unlike generic types in other languages such as C# and Java, C++ templates support non-type parameters, also called value parameters. Sie können z. B. einen konstanten integralen Wert angeben, um die Länge eines Arrays anzugeben, wie in diesem Beispiel, das der std::array-Klasse in der Standardbibliothek ähnelt:For example, you can provide a constant integral value to specify the length of an array, as with this example that is similar to the std::array class in the Standard Library:

template<typename T, size_t L>
class MyArray
{
    T arr[L];
public:
    MyArray() { ... }
};

Beachten Sie die Syntax in der Vorlagendeklaration.Note the syntax in the template declaration. Der size_t Wert wird zur Kompilierungszeit als Vorlagenargument übergeben und muss const oder ein constexpr-Ausdruck sein.The size_t value is passed in as a template argument at compile time and must be const or a constexpr expression. Sie verwenden es wie folgt:You use it like this:

MyArray<MyClass*, 10> arr;

Andere Arten von Werten, einschließlich Zeiger und Verweise, können als Nicht-Typparameter übergeben werden.Other kinds of values including pointers and references can be passed in as non-type parameters. Sie können z. B. einen Zeiger an ein Funktions- oder Funktionsobjekt übergeben, um einen Vorgang innerhalb des Vorlagencodes anzupassen.For example, you can pass in a pointer to a function or function object to customize some operation inside the template code.

Typabzug für Nicht-Typ-VorlagenparameterType deduction for non-type template parameters

In Visual Studio 2017 und höher leitet der Compiler im /std:c++17-Modus den Typ eines Nicht-Typvorlagenarguments ab, das mit autodeklariert wird:In Visual Studio 2017 and later, in /std:c++17 mode the compiler deduces the type of a non-type template argument that is declared with auto:

template <auto x> constexpr auto constant = x;

auto v1 = constant<5>;      // v1 == 5, decltype(v1) is int
auto v2 = constant<true>;   // v2 == true, decltype(v2) is bool
auto v3 = constant<'a'>;    // v3 == 'a', decltype(v3) is char

Vorlagen als VorlagenparameterTemplates as template parameters

Eine Vorlage kann ein Vorlagenparameter sein.A template can be a template parameter. In diesem Beispiel verfügt MyClass2 über zwei Vorlagenparameter: einen Typnamenparameter T und einen Vorlagenparameter Arr:In this example, MyClass2 has two template parameters: a typename parameter T and a template parameter Arr:

template<typename T, template<typename U, int I> class Arr>
class MyClass2
{
    T t; //OK
    Arr<T, 10> a;
    U u; //Error. U not in scope
};

Da der Parameter Arr selbst keinen Text hat, werden seine Parameternamen nicht benötigt.Because the Arr parameter itself has no body, its parameter names are not needed. Tatsächlich ist es ein Fehler, auf den Typnamen oder die Klassenparameternamen von Arrinnerhalb des Textes von MyClass2zu verweisen.In fact, it is an error to refer to Arr's typename or class parameter names from within the body of MyClass2. Aus diesem Grund können die Parameternamen des Typs Von Arrweggelassen werden, wie in diesem Beispiel gezeigt:For this reason, Arr's type parameter names can be omitted, as shown in this example:

template<typename T, template<typename, int> class Arr>
class MyClass2
{
    T t; //OK
    Arr<T, 10> a;
};

StandardvorlagenargumenteDefault template arguments

Klassen- und Funktionsvorlagen können Standardargumente haben.Class and function templates can have default arguments. Wenn eine Vorlage über ein Standardargument verfügt, können Sie es bei der Verwendung nicht angegeben.When a template has a default argument you can leave it unspecified when you use it. Die Std::vector-Vorlage verfügt beispielsweise über ein Standardargument für den Zuweisungsfaktor:For example, the std::vector template has a default argument for the allocator:

template <class T, class Allocator = allocator<T>> class vector;

In den meisten Fällen ist die standardmäßige std::allocator-Klasse akzeptabel, daher verwenden Sie einen Vektor wie folgt:In most cases the default std::allocator class is acceptable, so you use a vector like this:

vector<int> myInts;

Bei Bedarf können Sie jedoch einen benutzerdefinierten Allokator wie folgt angeben:But if necessary you can specify a custom allocator like this:

vector<int, MyAllocator> ints;

Bei mehrfachen Vorlagenargumenten müssen alle Argumente nach dem ersten Standardargument Standardargumente haben.For multiple template arguments, all arguments after the first default argument must have default arguments.

Wenn Sie eine Vorlage verwenden, deren Parameter alle standardmäßig sind, verwenden Sie leere winkele Klammern:When using a template whose parameters are all defaulted, use empty angle brackets:

template<typename A = int, typename B = double>
class Bar
{
    //...
};
...
int main()
{
    Bar<> bar; // use all default type arguments
}

VorlagenspezialisierungTemplate specialization

In einigen Fällen ist es nicht möglich oder wünschenswert, dass eine Vorlage genau denselben Code für einen beliebigen Typ definiert.In some cases, it isn’t possible or desirable for a template to define exactly the same code for any type. Sie können z. B. einen Codepfad definieren, der nur ausgeführt werden soll, wenn es sich bei dem Typargument um einen Zeiger oder um einen std::wstring oder einen Von einer bestimmten Basisklasse abgeleiteten Typ handelt.For example, you might wish to define a code path to be executed only if the type argument is a pointer, or a std::wstring, or a type derived from a particular base class. In solchen Fällen können Sie eine Spezialisierung der Vorlage für diesen bestimmten Typ definieren.In such cases you can define a specialization of the template for that particular type. Wenn ein Benutzer die Vorlage mit diesem Typ instanziiert, verwendet der Compiler die Spezialisierung, um die Klasse zu generieren, und für alle anderen Typen wählt der Compiler die allgemeinere Vorlage aus.When a user instantiates the template with that type, the compiler uses the specialization to generate the class, and for all other types, the compiler chooses the more general template. Spezialisierungen, auf die sich alle Parameter spezialisiert haben, sind komplette Spezialisierungen.Specializations in which all parameters are specialized are complete specializations. Wenn nur einige der Parameter spezialisiert sind, wird es als Partielle Spezialisierungbezeichnet.If only some of the parameters are specialized, it is called a partial specialization.

template <typename K, typename V>
class MyMap{/*...*/};

// partial specialization for string keys
template<typename V>
class MyMap<string, V> {/*...*/};
...
MyMap<int, MyClass> classes; // uses original template
MyMap<string, MyClass> classes2; // uses the partial specialization

Eine Vorlage kann eine beliebige Anzahl von Spezialisierungen aufweisen, solange jeder spezielle Typparameter eindeutig ist.A template can have any number of specializations as long as each specialized type parameter is unique. Nur Klassenvorlagen können teilweise spezialisiert sein.Only class templates may be partially specialized. Alle vollständigen und teilweisen Spezialisierungen einer Vorlage müssen im gleichen Namespace wie die ursprüngliche Vorlage deklariert werden.All complete and partial specializations of a template must be declared in the same namespace as the original template.

Weitere Informationen finden Sie unter Vorlagenspezialisierung.For more information, see Template Specialization.