Template (Programmierung)

Template (Programmierung)

Templates (engl. für Schablonen), auch Mustervorlagen oder Schablone, sind fortgeschrittene Elemente von Programmiersprachen. Sie sind „Programmgerüste“, die bei Bedarf vom Übersetzer instanziiert und als normale Klassen oder Funktionen zur Verfügung gestellt werden. Templates ermöglichen generische Programmierung und typsichere Container, bei denen vom Klassennutzer die enthaltenen Typen angegeben werden können.

C++ ist ein Beispiel für eine Programmiersprache, die über Template-Sprachelemente verfügt. In der C++-Standardbibliothek werden Templates zur Bereitstellung typsicherer Container, wie z. B. Listen, und zur Implementierung von generischen Algorithmen, wie z. B. Sortierverfahren, verwendet.

D unterstützt Templates in einer zu C++ ähnlichen Form mit einer leicht unterschiedlichen Syntax. Es besteht jedoch keine Möglichkeit, C++-Templates in D oder umgekehrt D-Templates in C++ zu nutzen.

In anderen Programmiersprachen (z. B. Java[1] oder C#[2]) gibt es das Konzept des generischen Typs, welches ein mit Templates verwandtes Konzept ist. Generische Typen stellen jedoch keine Codegeneratoren dar, sondern ermöglichen lediglich typsichere Container.

Inhaltsverzeichnis

Arten von Templates

Es gibt in C++ zwei Arten von Templates: Funktionstemplates und Klassentemplates.

Funktionstemplates

Ein Funktionstemplate (auch fälschlich Templatefunktion genannt) verhält sich wie eine Funktion, die in der Lage ist, Argumente verschiedener Typen entgegenzunehmen oder verschiedene Rückgabetypen zu liefern. Die C++-Standardbibliothek enthält beispielsweise das Funktionstemplate std::max(x, y). Es gibt entweder x oder y zurück, und zwar abhängig davon, welches der beiden Argumente größer ist. Es könnte etwa folgendermaßen definiert sein:

template <typename T>
T max(T x, T y)
{
  T value;
 
  if (x < y)
    value = y;
  else
    value = x;
  //
  return value;
}

Dieses Template kann genauso aufgerufen werden wie eine Funktion:

cout << max(3, 7); // gibt 7 aus

Anhand der Argumente macht der Compiler fest, dass es sich um einen Aufruf an max(int, int) handelt und erzeugt eine Variante der Funktion, bei der der Typ T zu int festgelegt wird.

Der Templateparameter könnte auch explizit angegeben werden:

cout << max<int>(3, 7); // gibt ebenfalls 7 aus

Das Funktionstemplate max() lässt sich für jeden Typ instanziieren, für den der Vergleich x < y eine wohldefinierte Operation darstellt. Bei selbstdefinierten Typen macht man von Operator-Überladung Gebrauch, um die Bedeutung von < für den Typ festzulegen und dadurch die Verwendung von max() für den betreffenden Typ zu ermöglichen.

Im Zusammenspiel mit der C++-Standardbibliothek erschließt sich eine enorme Funktionalität für selbstdefinierte Typen durch Definition einiger Operatoren. Allein durch die Definition eines Vergleichsoperators < (strenge schwache Ordnung) werden die Standardalgorithmen std::sort(), std::stable_sort(), und std::binary_search() für den selbstdefinierten Typ anwendbar.

Klassentemplates

Ein Klassentemplate (auch fälschlich Templateklasse genannt) wendet das gleiche Prinzip auf Klassen an. Klassentemplates werden oft zur Erstellung von generischen Containern verwendet. Beispielsweise verfügt die C++-Standardbibliothek über einen Container, der eine verkettete Liste implementiert. Um eine verkettete Liste von int zu erstellen, schreibt man einfach std::list<int>. Eine verkettete Liste von Objekten des Datentypes std::string wird zu std::list<std::string>. Mit list ist ein Satz von Standardfunktionen definiert, die immer verfügbar sind, egal was man als Argumenttyp in den spitzen Klammern angibt. Die Werte in spitzen Klammern werden Parameter genannt. Wenn ein Klassentemplate mit seinen Parametern dem Compiler übergeben wird, so kann dieser das Template ausprägen. Er erzeugt hierbei zu jedem Parametertyp eine eigene Templateklasse. Diese ist eine gewöhnliche Klasse, wie jede andere auch. Die Begriffe Klassentemplate und Templateklasse sind hier voneinander zu unterscheiden. Wie Objekt und Klasse ist die Templateklasse eine Ausprägung eines Klassentemplates.

Templates sind sowohl für mit class als auch für mit struct und union definierten Klassen anwendbar. Typedefs und Namespaces lassen sich dagegen nicht als Template anlegen.

Vererbung

Klassentemplates können wie normale Klassen in Vererbungshierarchien sowohl als Basis- als auch als abgeleitete Klasse auftreten.

Wird ein Klassentemplate mit verschiedenen Klassenparametern ausgeprägt, so stehen diese grundsätzlich in keiner Vererbungsrelation – auch nicht, wenn die Klassenparameter in einer Vererbungsbeziehung stehen.

Beispiel
class Base {...};
class Derived : public Base { ... };
 
Base* b = new Derived;  // OK. Automatische Typumwandlung, da Basisklasse.
std::vector<Base>* vb = new std::vector<Derived>;  // FEHLER!

Dies darf nicht sein, denn ein std::vector<Base> ist nicht in der Lage, Derived-Objekte zu speichern.

Falls eine Umwandlung von verschiedenen Ausprägungen des gleichen Klassentemplates wie etwa bei boost::smart_ptr sinnvoll ist, muss dafür explizit ein Typkonvertierungsoperator definiert werden.

Spezialisierung

Templates lassen sich spezialisieren, d. h. man kann Klassen- und Funktionstemplates (für bestimmte Datentypen als Template-Argumente) gesondert implementieren. Dies erlaubt eine effizientere Implementierung für bestimmte ausgewählte Datentypen, ohne die Schnittstelle des Templates zu verändern. Davon machen auch viele Implementierungen der C++-Standardbibliothek (beispielsweise die der GCC) Gebrauch.

Spezialisierung bei Klassentemplates

Die Containerklasse std::vector der C++-Standardbibliothek kann für den Elementtyp bool als Bitmap implementiert werden, was hilft Speicherplatz einzusparen. Auch entnimmt das Klassentemplate std::basic_string die Informationen zum Umgang mit den einzelnen Zeichen der Struktur char_traits, die für den Datentyp char und beispielsweise auch wchar_t spezialisiert ist.

Die Deklaration von Spezialisierungen ähnelt der von normalen Templates. Allerdings sind die dem Schlüsselwort template folgenden spitzen Klammern leer, und dem Funktions- bzw. Klassennamen folgen die Templateparameter.

Beispiel
template <>
class vector<bool>
{
  // Implementierung von vector als Bitmap
};

Partielle Spezialisierung

Des Weiteren gibt es auch die so genannte partielle Spezialisierung, die die Behandlung von Spezialfällen innerhalb eines Templates ermöglicht.

Beispiel
template <int zeilen, int spalten>
class Matrix
{
  // Implementierung einer Matrix-Klasse
};
//
template <int zeilen>
class Matrix<zeilen, 1>
{
  // Implementierung einer 1-spaltigen Matrix-Klasse
};

Wichtig zu erwähnen ist, dass beide Klassen komplett voneinander unabhängig sind, d. h. sie erben weder Konstruktoren oder Destruktoren noch Elementfunktionen bzw. Datenelemente voneinander.

Spezialisierung bei Funktionstemplates

Im Unterschied zu Klassentemplates sind Funktionstemplates nicht teilweise sondern nur vollständig spezialisierbar. Allerdings wird von der Spezialisierung von Funktionstemplates allgemein abgeraten, da die Regeln für die Bestimmung der „am besten passenden“ Funktion sonst zu unintuitiven Ergebnissen führen können. [3]

Durch Überladen von Funktionstemplates mit anderen Funktionstemplates kann man in den meisten Fällen das Gleiche erreichen wie durch die (nicht zulässige) teilweise Spezialisierung. Falls diese Technik aus jedwedem Grund im konkreten Fall nicht anwendbar ist – z. B. wenn ein Template von Klassenmethoden spezialisiert werden soll ohne die Klassendefinition zu erweitern – so kann man auch das Problem der Spezialisierung auf ein Template einer Hilfsklasse verlagern:

class Example
{
  private:
    template<typename T>
    struct Frobnicator
    {
      static T do_frobnicate(T param);
    };
 
  public:
    template<typename T>
    T frobnicate(T param);
};
//
template<typename T>
T Example::frobnicate(T param)
{
  // Frobnicator soll die eigentliche Arbeit verrichten
  return Frobnicator<T>::do_frobnicate(param);
}
//
template<typename T>
T Example::Frobnicator<T>::do_frobnicate(T param)
{
  // Standardimplementierung ...
}
//
template<>
int Example::Frobnicator<int>::do_frobnicate(int param)
{
  // ints werden auf andere Weise "frobnifiziert"
  return (param << 3) + (param % 7) - param + foobar;
}

Template Template-Parameter

Als Template Templates werden Konstruktionen bezeichnet, bei denen Templates Templates als Parameter übernehmen. Sie stellen einen weiteren Abstraktionsmechanismus zur Verfügung. Im folgenden Beispiel wird sowohl der Typ als auch der verwendete Container angegeben; letzterer mit Hilfe eines Template Template-Parameters:

template <template <typename, typename> class Container, typename Type>
class Example
{
  Container<Type, std::allocator <Type> > baz;
};

Beispiel zur Verwendung:

Example <std::deque, int> example;

Einzelnachweise

  1. Generics in the Java Programming Language
  2. An Introduction to C# Generics
  3. Herb Sutter: Why Not Specialize Function Templates?. In: C/C++ Users Journal. 7, Nr. 19, Juli 2001 (http://www.gotw.ca/publications/mill17.htm).

Weiterführende Themen

Literatur

  • David Vandervoorde, Nicolai M. Josuttis: C++ Templates. The Complete Guide. Addison-Wesley Professional, 2003, ISBN 0-2017-3484-2.

Wikimedia Foundation.

Игры ⚽ Нужен реферат?

Schlagen Sie auch in anderen Wörterbüchern nach:

  • Template — Templates (der englische Begriff für Schablonen), sind Vorlagen, die mit Inhalt gefüllt werden können. Verwendet wird der Begriff in der elektronischen Datenverarbeitung: für Dokumentvorlagen in Office Applikationen oder im Internet, siehe… …   Deutsch Wikipedia

  • Template Engine — Dieser Artikel wurde aufgrund von inhaltlichen Mängeln auf der Qualitätssicherungsseite der Redaktion Informatik eingetragen. Dies geschieht, um die Qualität der Artikel aus dem Themengebiet Informatik auf ein akzeptables Niveau zu bringen. Hilf… …   Deutsch Wikipedia

  • Generische Programmierung in Java 5.0 — Generische Programmierung wird in Java durch so genannte Generics ermöglicht. Der Begriff steht synonym für „parametrisierte Typen“. Die Idee dahinter ist zusätzliche Variablen für Typen, sog. Typ Variablen, einzuführen. Diese repräsentieren zum… …   Deutsch Wikipedia

  • Matrix Template Library — Betriebssystem Linux, Unix, Mac OS X, Windows Programmier­sprache C++ Kategorie Wissenschaftliche Programmbibliothek Lizenz …   Deutsch Wikipedia

  • C++-Template — Dieser Artikel wurde aufgrund von inhaltlichen Mängeln auf der Qualitätssicherungsseite der Redaktion Informatik eingetragen. Dies geschieht, um die Qualität der Artikel aus dem Themengebiet Informatik auf ein akzeptables Niveau zu bringen. Hilf… …   Deutsch Wikipedia

  • Funktionale Programmierung — ist ein Programmierstil, bei dem Programme ausschließlich aus Funktionen bestehen. Dadurch werden die aus der imperativen Programmierung bekannten Nebenwirkungen vermieden. Die funktionale Programmierung entspringt der akademischen Forschung. In… …   Deutsch Wikipedia

  • Funktionionale Programmierung — Dieser Artikel oder Abschnitt bedarf einer Überarbeitung. Näheres ist auf der Diskussionsseite angegeben. Hilf mit, ihn zu verbessern, und entferne anschließend diese Markierung. Funktionale Programmierung ist ein Programmierparadigma. Programme… …   Deutsch Wikipedia

  • Smarty Template Engine — Smarty Entwickler: Monte Ohrt, Andrei Zmievski Aktuelle Version: 2.6.22 (17. Dezember 2008) Betriebssystem: plattformunabhängig Pr …   Deutsch Wikipedia

  • Generische Programmierung — ist ein Verfahren zur Entwicklung wiederverwendbarer Software Bibliotheken. Dabei werden Funktionen möglichst allgemein entworfen, um für unterschiedliche Datentypen und Datenstrukturen verwendet werden zu können. Die Implementierung erfolgt bei… …   Deutsch Wikipedia

  • Active Template Library — Bei der Active Template Library (ATL) handelt es sich um eine Sammlung von Visual C++ Klassenbibliotheken für Microsoft Windows zur Erstellung und Nutzung von COM Komponenten, einschließlich ActiveX Steuerelementen. Der Namensbestandteil Template …   Deutsch Wikipedia

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”