zurück zum Artikel

C++26 wird der nächste große C++-Standard​

Rainer Grimm

(Bild: SergioVas/Shutterstock)

C++26 verbessert C++ erheblich und wird wohl ähnlich bahnbrechend sein wie C++98, C++11 und C++20.​ Zeit für einen Rückblick auf die vergangenen C++-Standards.

Um die Bedeutung von C++26 zu zeigen, stelle ich zunächst die C++-Standards in einen historischen Kontext. Das verdeutlicht diesen nächsten Schritt in der Entwicklung von C++.

Modernes C++ – Rainer Grimm

Rainer Grimm ist seit vielen Jahren als Softwarearchitekt, Team- und Schulungsleiter tätig. Er schreibt gerne Artikel zu den Programmiersprachen C++, Python und Haskell, spricht aber auch gerne und häufig auf Fachkonferenzen. Auf seinem Blog Modernes C++ beschäftigt er sich intensiv mit seiner Leidenschaft C++.

C++ ist mehr als 40 Jahre alt. Wie hat sich die Sprache in den letzten Jahren entwickelt? Hier ist eine vereinfachte Antwort, die mit C++26 endet.

Ende der 80er Jahre schrieben Bjarne Stroustrup und Margaret A. Ellis ihr berühmtes Buch „Annotated C++ Reference Manual [1](ARM)“. Dieses Buch diente zwei Zwecken. Erstens gab es viele unabhängige C++-Implementierungen. Das Buch definierte daher die Funktionalität von C++. Zweitens war ARM die Grundlage für den ersten C++-Standard: C++98 (ISO/IEC 14882). C++98 hatte einige wesentliche Features: Templates, die Standard Template Library (STL) mit ihren Containern und Algorithmen, Strings und IO-Streams.

Mit C++03 (14882:2003) erhielt C++98 eine technische Korrektur, die so klein war, dass sie nicht auf meiner Zeitachse erscheint. In der Community wird C++03, das C++98 enthält, als Legacy-C++ bezeichnet.

Im Jahr 2005 geschah etwas Aufregendes: Der sogenannte technische Bericht 1 (TR1) wurde veröffentlicht. TR1 war ein großer Schritt in Richtung C++11 und damit in Richtung Modern C++. TR1 (TR 19768) basiert auf dem Boost-Projekt [2], das von Mitgliedern des C++-Standardisierungsausschusses gegründet wurde. TR1 verfügt über 13 Bibliotheken, die Teil des nächsten C++-Standards werden sollten. Dazu gehören die Bibliothek für reguläre Ausdrücke, die Zufallszahlenbibliothek, Smart Pointers wie std::shared_ptr und Hashtabellen. Nur die sogenannten speziellen mathematischen Funktionen mussten bis C++17 warten.

C++11

C++11 ist der nächste C++-Standard, aber wir nennen ihn Modern C++. Dieser Name umfasst auch C++14 und C++17. C++11 hat viele Features, die die Art und Weise, wie wir C++ programmieren, grundlegend verändert haben. Zum Beispiel brachte C++11 die Komponenten des TR1, aber auch Move-Semantik, Perfect Forwarding, Variadic Templates oder constexpr. Aber das ist noch nicht alles. Mit C++11 haben wir ein Speichermodell als grundlegende Threading-Basis und eine Threading-API erhalten. Mehr steht in meinen allgemeinen Artikeln zum Speichermodell [3]und Multithreading [4].

C++14 ist ein kleiner C++-Standard. Er brachte Read-Writer-Locks, generalisierte Lambdas und generalisierte constexpr-Funktionen.

C++17 ist weder groß noch klein. Es hat zwei herausragende Features: die parallele STL und das standardisierte Dateisystem. Etwa 80 STL-Algorithmen können mithilfe einer sogenannten Execution Policy ausgeführt werden. Das bedeutet, dass ein Aufruf std::sort(std::execute::par, vec.begin(), vec.end()) ein Hinweis für die C++-Implementierung ist, den Container vec parallel zu sortieren. Zusätzlich kann man angeben, dass die Sortierung sequenziell (std::execution::seq) oder vektorisiert (std::execution::par_unseq) erfolgen soll. Wie bei C++11 war boost auch bei C++17 sehr einflussreich. Wir haben das Dateisystem von boost und die drei neuen Datentypen std::optional, std::variant und std::any übernommen.

Hier sind meine Artikel zu C++17. [5]

C++20 hat die Art und Weise, wie wir C++ programmieren, genauso grundlegend verändert wie C++11. Dies gilt insbesondere für die vier großen Bereiche: Ranges, Coroutinen, Concepts und Module.

Die Ranges-Bibliothek ermöglicht es, Algorithmen direkt auf dem Container auszudrücken, den Algorithmus mit dem Pipe-Symbol zusammenzusetzen und sie auf unendliche Datenströme anzuwenden.

Dank Coroutinen könnte die asynchrone Programmierung in C++ zum Mainstream werden. Coroutinen bilden die Grundlage für kooperative Tasks, Ereignisschleifen, unendliche Datenströme oder Pipelines.

Concepts werden die Art und Weise verändern, wie wir Templates programmieren. Sie sind semantische Kategorien für gültige Template-Argumente. Sie ermöglichen es, die eigene Absicht direkt im Datentyp des Systems auszudrücken. Wenn etwas schiefgeht, erhält man eine prägnante Fehlermeldung.

Module werden die Einschränkungen von Header-Dateien überwinden. Sie versprechen viel. Zum Beispiel wird der Präprozessor überflüssig. Letztendlich werden wir auch schnellere Build-Zeiten und eine einfachere Möglichkeit haben, Pakete zu erstellen.

Details zu den einzelnen Neuerungen finden sich in meinen Artikeln zu Ranges [6], Coroutinen [7], Concepts [8], Module [9]und C++20 [10].

Derzeit (August 2024) ist C++23 technisch fertig und steht zur endgültigen Abstimmung an.

C++23 bietet mit Deducing this ein kleines, aber sehr wirkungsvolles Feature der Kernsprache. Deducing this ermöglicht es, ähnlich wie bei Python, den implizit übergebenen this-Zeiger in einer Member-Funktionsdefinition explizit zu machen. Dank Deducing werden einige komplexe Techniken in C++, wie CRTP oder das Overload-Pattern, zum Kinderspiel.

Die C++23-Bibliothek wird viele wirkungsvolle Ergänzungen erhalten. Man kann die Standardbibliothek direkt mit import std; importieren oder den C++20-Formatierungsstring in std::print und std::println anwenden. Zusätzlich werden wir aus Gründen der Performanz flache assoziative Container wie std::flat_map erhalten. Der neue Datentyp std::expected verfügt bereits über eine zusammensetzbare Schnittstelle und kann einen erwarteten oder unerwarteten Wert für die Fehlerbehandlung speichern. Dank std::mdspan erhalten wir eine mehrdimensionale Spanne. Und schließlich ist std::generator die erste konkrete Coroutine zur Erzeugung eines Zahlenstroms. std::generator ist Teil der ranges-Bibliothek, die in C++23 ebenfalls verbessert wird.

Mehr dazu steht in meinen Artikeln zu C++23. [11]

Die Arbeit an C++26 begann im zweiten Quartal 2023 und wird im ersten Quartal 2025 mit dem Feature Freeze abgeschlossen sein. Im August 2024 wird C++26 mindestens drei große Features enthalten: Reflection, Contracts und std::execution.

Reflection ist die Fähigkeit eines Programms, seine Struktur und sein Verhalten zu untersuchen, zu analysieren und zu ändern. Dadurch wird die Compilezeit-Programmierung in C++ wesentlich leistungsfähiger.

Ein Contract legt Schnittstellen für Softwarekomponenten präzise und überprüfbar fest. Diese Softwarekomponenten sind Funktionen, die Vorbedingungen, Nachbedingungen und Invarianten erfüllen.

std::execution, früher bekannt als Executor oder Sender/Empfänger, bietet „a Standard C++ framework for managing asynchronous execution on generic execution resources". (P2300R10)

Im nächsten Artikel werde ich einen Überblick über die Features von C++26 geben.

(rme [12])


URL dieses Artikels:
https://www.heise.de/-9837334

Links in diesem Artikel:
[1] https://www.stroustrup.com/arm.html
[2] https://www.boost.org/
[3] https://www.grimm-jaud.de/index.php/category/speichermodell
[4] https://www.grimm-jaud.de/index.php/category/multithreading
[5] https://www.grimm-jaud.de/index.php/category/c-17
[6] https://www.grimm-jaud.de/index.php/tag/ranges-bibliothek
[7] https://www.grimm-jaud.de/index.php/tag/coroutinen
[8] https://www.grimm-jaud.de/index.php/tag/concepts
[9] https://www.grimm-jaud.de/index.php/tag/module
[10] https://www.grimm-jaud.de/index.php/tag/concepts
[11] https://www.grimm-jaud.de/index.php/category/cpp23
[12] mailto:rme@ix.de