Namensräume
Varianten
Aktionen

Member-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
 
 
 
 

Template-Deklarationen (Klassen, Funktions und Variablen(seit C++14)) können innerhalb einer Mitgliedsspezifikation einer beliebigen Klasse, Struktur oder Union erscheinen, die keine lokalen Klassen sind.

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
 
struct Printer
{
    // generic functor
    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 Klassenscope als auch im umschließenden Namespace-Scope erscheinen. Explizite Spezialisierungen können in jedem Scope erscheinen, in dem das primäre Template erscheinen kann.

struct A
{
    template<class T> struct B;        // primary member template
    template<class T> struct B<T*> {}; // OK: partial specialization
//  template<> struct B<int*> {};      // OK via CWG 727: full specialization
};
template<> struct A::B<int*> {};       // OK
template<class T> struct A::B<T&> {};  // OK

Wenn die umschließende Klassendeklaration wiederum ein Klassentemplate ist, muss ein Member-Template, wenn es außerhalb des Klassenkörpers definiert wird, zwei Sätze von Template-Parametern verwenden: einen für die umschließende Klasse und einen für sich selbst.

template<typename T1>
struct string
{
    // member template function
    template<typename T2>
    int compare(const T2&);
    // constructors can be templates too
    template<typename T2>
    string(const std::basic_string<T2>& s) { /*...*/ }
};
// out of class definition of string<T1>::compare<T2> 
template<typename T1> // for the enclosing class template
template<typename T2> // for the member template
int string<T1>::compare(const T2& s) { /* ... */ }

Inhalt

[bearbeiten] Member-Funktions-Templates

Destruktoren und Kopierkonstruktoren können keine Templates sein. Wenn ein Template-Konstruktor deklariert wird, der mit der Typsignatur eines Kopierkonstruktors instanziiert werden könnte, wird stattdessen der implizit deklarierte Kopierkonstruktor verwendet.

Ein Member-Funktions-Template kann nicht virtuell sein, und ein Member-Funktions-Template in einer abgeleiteten Klasse kann keine virtuelle Member-Funktion aus der Basisklasse überschreiben.

class Base
{
    virtual void f(int);
};
 
struct Derived : Base
{
    // this member template does not override Base::f
    template<class T> void f(T);
 
    // non-template member override can call the template:
    void f(int i) override
    {
         f<>(i);
    }
};

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

template<typename T>
struct A
{
    void f(int); // non-template member
 
    template<typename T2>
    void f(T2); // member template
};
 
// template member definition
template<typename T>
template<typename T2>
void A<T>::f(T2)
{
    // some code
}
 
int main()
{
    A<char> ac;
    ac.f('c'); // calls template function A<char>::f<char>(char)
    ac.f(1);   // calls non-template function A<char>::f(int)
    ac.f<>(1); // calls template function A<char>::f<int>(int)
}


Eine Out-of-Class-Definition eines Member-Funktions-Templates muss äquivalent zur Deklaration innerhalb der Klasse sein (siehe Funktions-Template-Überladung 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: equivalent declaration
template<class V>
V X::good(V n) { return n; }
 
// Error: not equivalent to any of the declarations inside X
template<class T>
T X::bad(typename identity<T>::type n) { return n; }

[bearbeiten] Konvertierungsfunktions-Templates

Eine benutzerdefinierte Konvertierungsfunktion kann ein Template sein.

struct A
{
    template<typename T>
    operator T*(); // conversion to pointer to any type
};
 
// out-of-class definition
template<typename T>
A::operator T*() { return nullptr; }
 
// explicit specialization for char*
template<>
A::operator char*() { return nullptr; }
 
// explicit instantiation
template A::operator void*();
 
int main()
{
    A a;
    int* ip = a.operator int*(); // explicit call to A::operator int*()
}

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

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

Ein benutzerdefiniertes Konvertierungsfunktions-Template 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 Klassenscope erscheinen, in diesem Fall deklariert sie ein statisches Datenmember-Template. Details finden Sie unter Variablen-Templates.

(seit C++14)

[bearbeiten] 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 1878 C++14 operator auto war technisch erlaubt operator auto verboten