Namespaces
Variants

Member templates

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
Miscellaneous

Template-Deklarationen ( class , function , und variables (seit C++14) ) können innerhalb einer Member-Spezifikation jeder Klasse, Struktur oder Union erscheinen, die keine lokalen Klassen sind.

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
struct Printer
{
    // generischer Funktor
    std::ostream& os;
    Printer(std::ostream& os) : os(os) {}
    template<typename T>
    void operator()(const T& obj) { os << obj << ' '; } // Member-Template
};
int main()
{
    std::vector<int> v{1,2,3};
    std::for_each(v.begin(), v.end(), Printer(std::cout));
    std::string s{"abc"};
    std::ranges::for_each(s, Printer(std::cout));
}

Ausgabe:

1 2 3 a b c

Partielle Spezialisierungen von Member-Templates können sowohl im Klassenbereich als auch im umschließenden Namensraumbereich erscheinen. Explizite Spezialisierungen können in jedem Bereich erscheinen, in dem das primäre Template erscheinen kann.

struct A
{
    template<class T> struct B;        // primäres Mitgliedstemplate
    template<class T> struct B<T*> {}; // OK: partielle Spezialisierung
//  template<> struct B<int*> {};      // OK via CWG 727: vollständige Spezialisierung
};
template<> struct A::B<int*> {};       // OK
template<class T> struct A::B<T&> {};  // OK

Wenn die Deklaration der einschließenden Klasse selbst eine Klassentemplate ist, nimmt eine Membertemplate, die außerhalb des Klassenkörpers definiert wird, zwei Sätze von Template-Parametern: einen für die einschließende Klasse und einen weiteren für sich selbst:

template<typename T1>
struct string
{
    // Mitgliedsvorlagenfunktion
    template<typename T2>
    int compare(const T2&);
    // Konstruktoren können ebenfalls Vorlagen sein
    template<typename T2>
    string(const std::basic_string<T2>& s) { /*...*/ }
};
// Außerhalb der Klassendefinition von string<T1>::compare<T2>
template<typename T1> // für die umschließende Klassenvorlage
template<typename T2> // für die Mitgliedsvorlage
int string<T1>::compare(const T2& s) { /* ... */ }

Inhaltsverzeichnis

Memberfunktionsvorlagen

Destruktoren und Copy-Konstruktoren können keine Templates sein. Falls ein Template-Konstruktor deklariert wird, der mit der Typsignatur eines Copy-Konstruktors instanziiert werden könnte, wird stattdessen der implizit deklarierte Copy-Konstruktor verwendet.

Eine Member-Funktionsvorlage kann nicht virtuell sein, und eine Member-Funktionsvorlage in einer abgeleiteten Klasse kann keine virtuelle Member-Funktion aus der Basisklasse überschreiben.

class Base
{
    virtual void f(int);
};
struct Derived : Base
{
    // diese Member-Template überschreibt Base::f nicht
    template<class T> void f(T);
    // nicht-template Member-Überschreibung kann das Template aufrufen:
    void f(int i) override
    {
         f<>(i);
    }
};

Eine Nicht-Template-Memberfunktion und eine Template-Memberfunktion mit demselben Namen können deklariert werden. Im Konfliktfall (wenn eine Template-Spezialisierung exakt mit der Signatur der Nicht-Template-Funktion übereinstimmt), bezieht sich die Verwendung dieses Namens und Typs auf die Nicht-Template-Member, es sei denn, eine explizite Template-Argumentliste wird angegeben.

template<typename T>
struct A
{
    void f(int); // Nicht-Template-Member
    template<typename T2>
    void f(T2); // Member-Template
};
// Template-Member-Definition
template<typename T>
template<typename T2>
void A<T>::f(T2)
{
    // Code-Auschnitt
}
int main()
{
    A<char> ac;
    ac.f('c'); // ruft Template-Funktion A<char>::f<char>(char) auf
    ac.f(1);   // ruft Nicht-Template-Funktion A<char>::f(int) auf
    ac.f<>(1); // ruft Template-Funktion A<char>::f<int>(int) auf
}


Eine außerhalb der Klasse definierte Definition einer Member-Funktionsvorlage muss äquivalent zur Deklaration innerhalb der Klasse sein (siehe function template overloading für die Definition von Äquivalenz), andernfalls wird sie als Überladung betrachtet.

struct X
{
    template<class T> T good(T n);
    template<class T> T bad(T n);
};
template<class T> struct identity { using type = T; };
// OK: äquivalente Deklaration
template<class V>
V X::good(V n) { return n; }
// Fehler: nicht äquivalent zu einer der Deklarationen innerhalb von X
template<class T>
T X::bad(typename identity<T>::type n) { return n; }

Konvertierungsfunktionsvorlagen

Eine benutzerdefinierte Konvertierungsfunktion kann eine Template sein.

struct A
{
    template<typename T>
    operator T*(); // Konvertierung zu Zeiger auf beliebigen Typ
};
// Definition außerhalb der Klasse
template<typename T>
A::operator T*() { return nullptr; }
// Explizite Spezialisierung für char*
template<>
A::operator char*() { return nullptr; }
// Explizite Instanziierung
template A::operator void*();
int main()
{
    A a;
    int* ip = a.operator int*(); // Expliziter Aufruf von A::operator int*()
}

Während der Überlagerungsauflösung werden Spezialisierungen von Konvertierungsfunktionsvorlagen nicht durch Namenssuche gefunden. Stattdessen werden alle sichtbaren Konvertierungsfunktionsvorlagen berücksichtigt, und jede durch Template-Argumentableitung erzeugte Spezialisierung (die spezielle Regeln für Konvertierungsfunktionsvorlagen hat) wird verwendet, als wäre sie durch Namenssuche gefunden worden.

Using-Deklarationen in abgeleiteten Klassen können nicht auf Spezialisierungen von Template-Konvertierungsfunktionen aus Basisklassen verweisen.

Eine benutzerdefinierte Konvertierungsfunktionsvorlage kann keinen abgeleiteten Rückgabetyp haben:

struct S
{
    operator auto() const { return 10; } // OK
    template<class T> operator auto() const { return 42; } // error
};
(seit C++14)

Member-Variablen-Templates

Eine Variablen-Template-Deklaration kann im Klassenbereich erscheinen, in diesem Fall deklariert sie ein statisches Datenelement-Template. Siehe Variablen-Templates für Details.

(seit C++14)

Fehlerberichte

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

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
CWG 1878 C++14 operator auto war technisch erlaubt operator auto verboten