namespace cpp

C++ lernen, kennen, anwenden

Benutzer-Werkzeuge

Webseiten-Werkzeuge


kennen:schablonen

Schablonen

There's more to templates than is shown here.
— Scott D. Meyers [Effective C++, item 49]

Schablonen (engl. template) lassen Typen oder ganzzahlige Konstanten bis zur Nutzung der Schablone offen. Sowohl Funktionen als auch Klassen können als Schablonen definiert werden.

Funktionsschablonen

Definition

Funktionsschablonen sind nur bis auf die in der Schablonenparameterliste angegebenen Typen oder Konstanten festgelegt. Frei wählbare Typnamen werden in der Schablonenparameterliste durch class oder typename markiert.

Syntax:

template < Schablonenparameterliste >
Funktionsdefinition
template <class T, int faktor>
T vielfaches(T x)
{
  return faktor*x;
}
 
template <class T>
T minimum(const T& x, const T& y)
{
  return x<y ? x : y;
}

Aufruf

Beim Übersetzen des Funktionsaufrufs wird bestimmt, welcher konkrete Typ oder welcher Konstantenwert in die Schablone eingesetzt wird. Der Quelltext der Schablone muss hier bekannt sein, da jetzt eine konkrete Funktion aus der Schablone erzeugt wird.

Syntax:

Funktionsname< Schablonenargumentliste > ( Funktionsargumentliste )
float  x = vielfaches<float,3>(5);  // 15
int    i = minimum(3, 5);
double d = minimum(2.718, 3.14);
float  f = minimum<float>(2.718, 3); 

Die Typangabe <float> beim letzten Funktionsaufuf erzwingt die Nutzung einer bestimmten Funktion. Ohne diese Angabe wäre keine eindeutige Typzuordnung möglich. Ist der konkrete Typ aus den Funktionsparametern eindeutig ableitbar, brauchen beim Aufruf keine Schablonenargumente angegeben werden.

Eine gleichnamige Funktion mit konkreten Parametertypen (Spezialisierung) hat Vorrang vor der Schablone.

Parameter packs

C++11 erlaubt die Angabe einer unbestimmten Anzahl von Schablonenparametern (parameter pack) mittels einer Ellipse .... Diese können durch Rekursion aufgelöst werden:

void writeln()
{
  std::cout << '\n';
}
 
template<typename T, typename... Types>
void writeln(T t, Types... args)
{
  std::cout << t;
  writeln(args...)
}

So lässt sich eine Funktion mit variabler Anzahl von Parametern nutzen:

  writeln();
  writeln("Hallo");
  writeln("C++", 17);

Faltausdrücke

Ab C++17 löst ein Faltausdruck dies eleganter:

template<typename... Types>
void writeln(Types... args)
{
  (std::cout << ... << args) << '\n';
}

Links-/Rechts-Faltungen können ein- oder zweistellig sein:

einstellig zweistellig wird aufgelöst als
Links-Faltung (... op args) (init op ... op args) (([init op arg1]) op arg2) op arg3
Rechts-Faltung (args op ... ) (args op ... op init) arg1 op (arg2 op (arg3 [op init]))

Klassenschablonen

Definition

Klassenentwürfe, die sich nur durch Konstanten oder Datentypen von Attributen, Methodenparametern oder Rückgabewerten unterscheiden, können als Schablonen definiert werden. Typnamen werden in der Schablonenparameterliste durch class oder typename markiert.

Syntax:

template < Schablonenparameterliste >
Klassendefinition
template <class T, int size>
class Stack
{
public:
  Stack();
  void push(const T& x);
  T pop();
  bool is_empty() const;
  bool is_full()  const;
private:
  T data[size];
  int anzahl;
};

Methoden

Außerhalb der Klassenschablone definierte Methoden werden wie ihre Klasse mit template<Schablonenparameterliste> eingeleitet. Hinter dem Klassennamen sind in spitzen Klammern die Namen aus der Schablonenparameterliste aufzuführen.

template <class T, int size>
int Stack<T, size>::is_full() const
{
  return anzahl==size;
}

Spezialisierungen erlauben Sonderverhalten für bestimmte konkrete Klassen.

template <>
int Stack<char, 40>::is_full() const
{
  if (anzahl != size) return false;
  std::cerr << '\a'; 
  return true;
}

Konkretisierung

Klassenschablonen werden durch typedef-Anweisungen, using-Anweisungen oder Variablen-Vereinbarungen konkretisiert. Der Quelltext der Schablonenmethoden muss bei der Konkretisierung offenliegen. Hinter dem Klassennamen sind konkrete Typen bzw. Konstanten als Schablonenargumente in spitzen Klammern anzugeben.

Syntax:

Klassenname< Schablonenargumentliste >
// typedef Stack<int, 100> IntegerStack; // C++98
using IntegerStack = Stack<int, 100>; 
Stack<double, 1000> s;
kennen/schablonen.txt · Zuletzt geändert: 2019-01-13 14:16 von rrichter