© deomis/Shutterstock.com
Wozu brauchen wir Concepts in C++ 20?

Spezifikationen für Typen


Auf Deutsch steht das Wort Konzept laut www.wiktionary.org für „formuliertes Gedankengerüst zur Realisierung von etwas“. Im Englischen geht es aber auch etwas profaner und „Concept“ kann auch einfach nur Begriff oder Begrifflichkeit bedeuten, wie zum Beispiel das „Concept of a Team“. Das Wort wurde schon 1998 von Alexander Stepanov beim Entwurf der STL benutzt, um auszudrücken, dass man die Eigenschaften von Typen beschreiben kann, ohne eine (abstrakte) Basisklasse festzulegen.

Ein Beispiel für Typen ohne festgelegte Basisklassen sind Iteratoren. Obwohl es viele unterschiedliche Implementierung dafür geben kann und diese weitgehend gleich verarbeitet werden können, existiert keine gemeinsame Basisklasse. Trotzdem kann man festhalten, dass ein Iterator einen Inkrementoperator und einen Dereferenzierungsoperator benötigt, dass er vergleichbar sein muss und außerdem konstruierbar (copy-constructable), zuweisbar (copy-assignable) und zerstörbar (destructible). Diese Eigenschaften wurden bisher aber nur informell als Dokumentation im Standard festgelegt. Schon seit Längerem hat die C++-Gemeinde deshalb daran gearbeitet, solche Concepts als Programmcode auszudrücken. Mit C++ 20 ist es nun endlich so weit. In diesem Beitrag erhalten Sie die Antworten auf die drei entscheidenden Fragen: Wie kann man Eigenschaften eines Typs spezifizieren, ohne ihn durch Ableitung an eine Basisklasse zu fesseln? Wie kann man diese Einschränkungen dann nutzen? Und warum brauchen wir das überhaupt?

Beginnen wir mit der letzten Frage. Bisher haben Sie gemeinsame Eigenschaften von Typen durch ein Interface bzw. abstrakte Basisklasse definiert. Auf diese Weise lassen sich Methoden und Operatoren eines Typs vorgeben. Über die Konstruktoren legen Sie fest, ob der Typ konstruierbar, kopierbar oder verschiebbar ist. Ob die Instanzen vergleichbar sind, folgt aus den vorgegebenen Operatoren und so weiter und so weiter. Reichen die Möglichkeiten eines gemeinsamen Interfaces trotzdem nicht aus?

Doch, im Grunde schon. Die Schwierigkeit liegt daran, dass eine gemeinsame Basisklasse Typen zu sehr aneinander bindet und eine starke Abhängigkeit bedeutet, die eigentlich gar nicht notwendig ist. Denken Sie zum Beispiel an Iteratoren: Containerklassen aus den unterschiedlichsten Bereichen und Bibliotheken müssten ihre Iteratoren von einer gemeinsamen Basisklasse ableiten und wären sehr empfindlich von einer Änderung derselben abhängig. In diesem speziellen Fall könnte man das Problem noch dadurch lösen, dass man die Iterator-Basisklasse in die Standardbibliothek mit aufnimmt, aber für nichtstandardisierte Concepts ist das offensichtlich nicht der richtige Weg.

Außerdem kann C++ heute schon mit Concepts arbeiten. Denn Iteratoren funktionieren innerhalb von allgemeingültigen Funktionen wie std::find, std::sort, std::fill und vielen anderen. Sie tun das deshalb, weil diese Funktionen Templatefunktionen sind und statt mit strenger Typisierung mit Duck Typing arbeiten. Sie können auf unterschiedlichen Typen operieren, wenn diese spezifische gemeinsame Eigenschaften haben, ohne dass sie ein gemeinsames Interface implementieren müssen. Eine Templatefunktion basiert also auf einem Concept. Und bei dem neuen Sprachmerkmal geht es darum, ein solches Concept nicht nur als Dokumentation bereitzustellen, sondern in Code zu gießen, damit der Compiler es prüfen, auswerten und für die automatische Vervollständigung verwenden kann.

Ein Concept im neuen Sinn ist also eine Spezifikation für Typen, die keine zusätzliche Abhängigkeit herstellt. Nehmen wir als Beispiel etwas Einfacheres als einen Iterator. Nehmen wir Typen, deren Elemente einen Operator > besitzen. Solche Typen nennen wir vergleichbar und sagen, sie erfüllen das Concept Comparable.

Verwendung von Concepts

Wie das Concept definiert wird, folgt etwas weiter unten. Für den Moment nehmen wir an, es gibt schon ein solches Conc...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang