Schablonen und Typisierung in C++: Von Generics zu Konzepten

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Generics und Typisierung in C++: Warum ist das nicht „nur Schablonen“?



Wenn ein Entwickler von Python oder Java zu C++ wechselt, wird er oft durch das Wort „Schablone“ (template) verunsichert. Im Kopf entstehen Assoziationen mit endlosen spitzen Klammern, unverständlichen Compiler-Fehlern und der Magie von std::vector<int>. Tatsächlich sind Generics in C++ (oder generische Programmierung) ein äußerst mächtiges Werkzeug, das es erlaubt, Code einmal zu schreiben und ihn mit beliebigen Datentypen zu verwenden. Und ja, das ist nicht dasselbe wie Generics in Java oder C#.



In diesem Artikel werden wir untersuchen, wie die Typisierung in C++ durch Schablonen funktioniert, wie sich Klassenschablonen von Funktionsschablonen unterscheiden und warum in C++20 Konzepte hinzugefügt wurden. Es wird viele Beispiele geben – von einfachen bis zu solchen, die im Produktionseinsatz wirklich nützlich sind. Los geht's!



Was sind Generics (Schablonen) in C++?



Ganz einfach ausgedrückt: Schablonen in C++ sind eine Möglichkeit, Code zu schreiben, der mit jedem Datentyp funktioniert, ohne dabei an Leistung zu verlieren. Im Gegensatz zur dynamischen Typisierung von Python, bei der der Typ zur Laufzeit überprüft wird, generiert C++ zur Compile-Zeit eine separate Version einer Funktion oder Klasse für jeden verwendeten Typ. Dies nennt man statische Typisierung mit Parametrisierung.



Syntaxmäßig wird eine Schablone mit dem Schlüsselwort template und spitzen Klammern mit Parametern deklariert:



template <typename T>T max(T a, T b) {    return (a > b) ? a : b;}


Hier ist typename T der Schablonenparameter. Sie können class anstelle von typename verwenden – es gibt keinen Unterschied. Wenn Sie max(3, 7) schreiben, setzt der Compiler automatisch int für T ein und erstellt die Funktion int max(int, int). Wenn Sie max(3.14, 2.71) schreiben, erhalten Sie eine Version für double. Alles einfach und effizient.



Funktionsschablonen: Der erste Schritt zu Generics



Beginnen wir mit etwas Kleinem – Funktionsschablonen in C++. Dies ist eine ideale Möglichkeit, Code-Duplizierung zu vermeiden, wenn die Logik gleich ist, die Typen jedoch unterschiedlich sind.



Beispiel: Eine Funktion, die ein Element auf der Konsole ausgibt (nützlich zum Debuggen):



#include <iostream>#include <string>

template <typename T>void print(const T& value) { std::cout << value << std::endl;}

int main() { print(42); // int print(3.1415); // double print("Hello"); // const char* print(std::string("Generics!")); // std::string return 0;}


Beachten Sie: Wir verwenden const T& – das ist Typisierung in C++ mit Übergabe per konstanter Referenz, um das Kopieren großer Objekte zu vermeiden. Für eingebaute Typen (int, double) ist das nicht kritisch, aber es ist eine gute Angewohnheit.



Was aber, wenn man zwei Argumente unterschiedlichen Typs übergeben muss? Ganz einfach:



template <typename T1, typename T2>auto add(T1 a, T2 b) -> decltype(a + b) {    return a + b;}

// In C++14 und neuer kann man einfach:template <typename T1, typename T2>auto add(T1 a, T2 b) { return a + b;}


Hier leitet auto den Rückgabetyp automatisch ab. Das ist Generics in Aktion – ein Code, unendlich viele Typkombinationen.



Klassenschablonen: Universelle Strukturen bauen



Kommen wir nun zu Klassenschablonen in C++. Sie sind die Grundlage der Standardbibliothek (STL): std::vector<T>, std::map<Key, Value>, std::optional<T> – alle sind durch Schablonen implementiert.



Schreiben wir ein einfaches, aber aussagekräftiges Beispiel – eine schablonisierte Klasse „Paar“ (Analogon zu std::pair):



template <typename First, typename Second>class Pair {private:    First first_;    Second second_;public:                

Blogs

Buchempfehlungen