Und der Gewinner ist: Templates

Modernes C++ Rainer Grimm  –  15 Kommentare

Die Zukunft von C++ spricht Templates und so auch mein Blog Modernes C++. Basierend auf der Umfrage meines letzten Beitrags "Quo Vadis - Modernes C++", erklären meine nächsten wohl 50 - 100 Artikel die Details zu Templates. In diesem Artikel möchte ich einen Ausblick geben.

Lasst mich zunächst ein paar Worte zu der Umfrage schreiben, denn ihr Ergebnis hat mich in zweierlei Hinsicht überrascht.

Die Umfrage

Erstens nahmen nahezu 400 Personen an der Umfrage teil. Das ist eine Zahl, die ich so nicht erwartet hätte. Vielen Dank für die vielen Stimmen.

Zweitens bin ich davon ausgegangen, dass "C++23" die Umfrage gewinnen wird, gefolgt von "Templates" oder "Erweitern und Einbetten von Python mit C/C++". Meine Annahme war so falsch. Ich bin froh, dass ich die Umfrage gemacht habe.

Wenn ich mit dem Themenkomplex "Templates" fertig bin, führe ich die nächste Umfrage durch. Jetzt möchte ich mich aber den Templates widmen.

Templates

Zuallererst: Was sind Templates? Templates (Klassen-Templates oder Funktions-Templates) sind Familien von Klassen oder Funktionen.

Bevor ich meinen Plan vorstelle, möchte ich ein paar Worte loswerden. Falls ich ein Template-bezogenes Feature vergessen habe, an dem ihr interesssiert seid, schreibt mir bitte eine E-Mail an folgende Adresse: Rainer.Grimm@modernescpp.de.

Das sind die zukünftigen Themen mit ein paar erläuternden Worten.

Grundlagen

Natürlich beginnt meine Tour mit den Grundlagen.

  • Die Vorstellung der Instanziierung von Funktions-Templates vermittelt die erste Intuition zu Templates. Dies gilt insbesondere, wenn Funktionsüberladungen oder explizite Template-Argumente angegeben werden.
  • Im Gegensatz zu Funktions-Template kann nur der C++17-Compiler die Template-Argumente für Klassen-Templates bestimmen. Das heißt, vor C++17 mussten Entwickler Template-Argumente wie int in std::vector<int> angeben.
  • Template-Parameter können Typen, Nicht-Typen und Templates selbst sein. Insbesondere können in C++20 Fließkommazahlen als Nicht-Typ Template-Parameter verwendet werden.
  • Der Compiler kann die Template-Argumente automatisch bestimmen. Es macht dabei einen großen Unterschied, ob der Template-Parameter eine Referenz/Zeiger, eine universelle Referenz (&&) oder ein Wert ist. Templates können auch Default-Template-Argumente besitzen.
  • Klassen-Templates erlauben teilweise und vollständige Template-Spezialisierung, Funktions-Templates dagegen nur vollständige Template-Spezialisierung.
Details

Nach den Grundlagen folgen die Details.

  • Im Allgemeinen geschieht die Instanziierung von Templates implizit, sie kann aber auch explizit erfolgen.
  • Ein Variadic-Template ist ein Template, das eine beliebige Anzahl von Parametern haben kann. Damit können Templates eine beliebige Anzahl von Argumenten einer beliebigen Wertkategorie annehmen.
  • Basierend auf Variadic-Templates in C++11 kennt C++17 Fold-Ausdrücke. Sie reduzieren Parameterpakete auf binäre Operatoren.
  • Eine Besonderheit ist die Freundschaft von Templates. Eine Klasse oder Klassen-Template kann jeder Instanz eines Klassen-Templates oder Funktions-Templates allgemeine Freundschaft aussprechen. Die Freundschaft kann auch nur bestimmten Instanzen eine Klassen-Templates oder Funktions-Templates gewährt werden, und auch einem bestimmten Datentyp.
  • Namen können von Template-Parametern abhängig sein. Bei abhängigen Namen benötigt der Compiler Hilfe, um zu entscheiden, ob der Name ein Typ, ein Nichttyp oder ein Template ist. Bei Mehrdeutigkeit geht der Compiler davon aus, dass ein Name ein Nichttyp ist.
Techniken

Es gibt viele interessante Techniken und Feature im Zusammenhang mit Template und der Template Instanziierung.

  • Wenn ein Funktions-Template mit mindestens zwei Template-Parametern zum Einsatz kommt, lässt es sich im Allgemeinen nicht entscheiden, welchen Rückgabetyp das Funktions-Template besitzen soll. Hier leistet der automatische Rückgabetyp wertvolle Hilfe.
  • Template-Metaprogrammierung ist Turing-vollständig. Das bedeutet, dass alles, was berechenbar ist, sich zur Compilezeit berechnen lässt. Template-Metaprogrammierung ist eine rein funktionale Sprache, eingebettet in die imperative Sprache C++. Libraries wie viele der Boost-Bibliotheken setzen intensiv Template-Metaprogrammierung ein.
  • Die Type-Traits Bibliothek stellt angewandte Template-Metaprogrammierung dar. Dank der Type-Traits Bibiliothek sind Typprüfungen, Typvergleiche und Typänderungen zur Compilezeit möglich.
  • constexpr ist die angenehmste Art, zur Compilezeit zu programmieren. Im Gegensatz zum Programmieren im funktionalen Stil mit Template-Metaprogrammierung, erlaubt constexpr das Programmieren im imperativen Stil.
  • constexpr if ermöglicht es, Quellcode bedingt zu kompilieren.
Design

Templates eröffnet C++ neue Möglichkeiten, Software zu entwerfen.

  • Neben dem dynamischen Polymorphismus (Objektorientierung) können wir den statischen Polymorphismus (Templates) einsetzen.
  • CRTP (curiously recurring template pattern) ist eine verblüffende, aber sehr mächtige Technik. Dank ihr können wir die Virtualität von der Runtime auf die Compilezeit verlagern.
  • Expression-Templates erzeugen Strukturen, die für Berechnungen stehen. Sie werden nur bei Bedarf ausgewertet und sparen somit Zeit und Speicher.
  • Es gibt viele Idiome und Pattern im Zusammenhang mit Templates. Zum Beispiel kennen wir Policies und Traits, Tag-Dispatching und Type Erasure.
C++20
  • Der englische Wikipedia-Eintrag beschreibt Concepts folgendermaßen: Concepts are an extension to the templates feature provided by the C++ programming language. Concepts are named Boolean predicates on template parameters, evaluated at compile time. A concept may be associated with a template (class template, function template, or member function of a class template), in which case it serves as a constraint: it limits the set of arguments that are accepted as template parameters

Wie geht's weiter?

In meinem nächsten Artikel werde ich Templates einführen und dabei C++ Insights verwenden.