Das ISO-Ausschuss fĂŒr die Standardisierung der Programmiersprache C++ hat die endgĂŒltige Version der Spezifikation genehmigt, die den internationalen Standard âC++26â bildet. Die in der Spezifikation vorgestellten Funktionen werden teilweise bereits in den Compilern GCC, Clang und Microsoft Visual C++ unterstĂŒtzt. Die unterstĂŒtzenden Standardbibliotheken fĂŒr C++26 wurden im Rahmen des Boost-Projekts implementiert.
In den nĂ€chsten zwei Monaten wird die genehmigte Spezifikation in der Phase der Dokumentenvorbereitung zur Veröffentlichung sein, in der redaktionelle Arbeiten zur Korrektur von Rechtschreibfehlern und Tippfehlern durchgefĂŒhrt werden. Anfang November wird die endgĂŒltige Version des Dokuments an ISO zur Veröffentlichung unter dem formalen Namen ISO/IEC 14882:2026 gesendet.
Hauptmerkmale von C++26:
- Elemente der Vertragsprogrammierung (Contracts) wurden implementiert, die es ermöglichen, formale Spezifikationen fĂŒr Schnittstellen mit drei neuen Operatoren zu definieren: pre (PrĂ€bedingung), post (Nachbedingung) und contract_assert (AssertionsprĂŒfung). Der Operator âpreâ definiert die Vorbedingungen, die vor dem Aufruf erfĂŒllt sein mĂŒssen (Eingabedaten ĂŒberprĂŒfen); âpostâ â die Bedingungen, die nach der AusfĂŒhrung eingehalten werden mĂŒssen (Ausgabedatenanforderungen); contract_assert â Bedingungen fĂŒr das Auftreten von Ausnahmen. Diese Möglichkeit wird in GCC 16 verfĂŒgbar sein. int f(const int x) pre (x != 1) // Anforderungen an die Eingabedaten post (r : r == x && r != 2) // Anforderungen an das Ergebnis; r â der Ergebniswert { contract_assert (x != 3); return x; }
- UnterstĂŒtzung fĂŒr Reflexion (Reflection) wurde hinzugefĂŒgt, die es ermöglicht, Elemente des Programms in der Kompilierungsphase zu verfolgen und zu modifizieren. Es wurden neue Operatoren â^^â zur Erfassung von Metainformationen ĂŒber grammatikalische Konstrukte und â[:âŠ:]â zur DurchfĂŒhrung von RĂŒcktransformierungen hinzugefĂŒgt. FĂŒr die Transformation und Verarbeitung der wĂ€hrend der Inspektion erhaltenen Informationen wird die Bibliothek std::meta vorgeschlagen, und es stehen Funktionen wie Berechnungen mit Konstanten zur VerfĂŒgung. ReflexionsunterstĂŒtzung wird in GCC 16 hinzugefĂŒgt. constexpr int i = 42, j = 42; constexpr std::meta::info r = ^^i, s = ^^i; static_assert(r == r && r == s); static_assert(^^i != ^^j); // 'i' und 'j' haben unterschiedliche Werte. static_assert(constant_of(^^i) == constant_of(^^j)); // 'i' und 'j' sind identisch static_assert(^^i != std::meta::reflect_constant(42)); // unterscheidet sich von dem Wert 42
- Ein Operator âtemplate forâ wurde hinzugefĂŒgt, um Elemente wie Parameterpakete, tuple-Ă€hnliche Objekte und Reflexionsergebnisse (Meta-Objekte) wĂ€hrend der Kompilierung im Stil einer regulĂ€ren Schleife zu iterieren. Bei der AusfĂŒhrung von âtemplate forâ wird der Schleifeninhalt fĂŒr jedes Element entfaltet, und jede Iteration wird in einem separaten Geltungsbereich verarbeitet, in dem die sich im Schleifenverlauf Ă€ndernde Variable eine Konstante ist. Im Kontext der Reflexion kann âtemplate forâ verwendet werden, um die Eigenschaften von Klassen oder Enumerationen zu durchlaufen. Diese Funktion wird in GCC 16 verfĂŒgbar sein. void f() { template for (constexpr int I : std::array{1, 2, 3}) { static_assert(I < 4); } } wird entfaltet zu: void f() { { constexpr auto&& __range = std::array{1, 2, 3}; constexpr auto __begin = __range.begin(); constexpr auto __expansion-size = __range.end() - __begin; // 3 { constexpr int I = *(__begin + 0); static_assert(I < 4); } { constexpr int I = *(__begin + 1); static_assert(I < 4); } { constexpr int I = *(__begin + 2); static_assert(I < 4); } } }
- Das Framework std::execution fĂŒr die asynchrone und parallele AusfĂŒhrung von Code wurde hinzugefĂŒgt. Es werden Objekte scheduler bereitgestellt, die den ArbeitsausfĂŒhrungsplaner (Thread, Threadpool, GPU, Event-Loop) definieren, sender, die die auszufĂŒhrende Arbeit definieren, und receiver, den Ergebnisverarbeiter. using namespace std::execution; scheduler auto sch = thread_pool.scheduler(); sender auto begin = schedule(sch); sender auto hi = then(begin, []{ std::cout << "Hello world! Have an int."; return 13; }); sender auto add_42 = then(hi, [](int arg) { return arg + 42; }); auto [i] = this_thread::sync_wait(add_42).value();
- Die Bibliothek std::simd wurde hinzugefĂŒgt, um die AusfĂŒhrung von Datenoperationen mithilfe von SIMD-BefehlssĂ€tzen wie AVX-512 und NEON zu parallelisieren, unter Verwendung des standardmĂ€Ăigen Typsystems von C++. std::simd a = {1.0f, 2.0f, 3.0f, 4.0f}; std::simd b = {5.0f, 6.0f, 7.0f, 8.0f}; std::simd result = a + b;
- Eine Implementierung des Vektors (Arrays) variabler GröĂe std::inplace_vector wurde vorgeschlagen, der auf dem Stack platziert wird, wobei die GröĂe zur Kompilierungszeit festgelegt wird. Die API Ă€hnelt der von std::vector, aber die Array-Elemente werden nicht im âHeapâ, sondern innerhalb des Objekts gespeichert. inplace_vector a(10); inplace_vector b(std::move(a)); assert(a.size() == 10);
- Die Direktive â#embedâ wurde hinzugefĂŒgt, die dazu dient, binĂ€re Ressourcen in den Code einzubetten. const unsigned char icon_display_data[] = { #embed "art.png" };
- UnterstĂŒtzung fĂŒr die Generierung und Verarbeitung von Ausnahmen wĂ€hrend der Kompilierung bei Fehlern im Kontext von constexpr hinzugefĂŒgt. constexpr std::optional checked_divide(unsigned n, unsigned d) { try { return divide(n, d); } catch (âŠ) { return std::nullopt; } } constexpr date parse_date(std::string_view input) { auto [correct, year, month, day] = ctre::match(input); if (!correct) { throw incorrect_date{input}; } return build_date(year, month, day); }
- Die Datenstruktur std::hive wurde implementiert, um Daten ungeordnet zu speichern und die Wiederverwendung von Speicher zu ermöglichen, der nach dem Löschen von Elementen frei geworden ist. Die Struktur ist fĂŒr hohe HinzufĂŒgungs- und LöschintensitĂ€ten bei beliebiger Reihenfolge optimiert. Im Gegensatz zu Arrays bewirkt das Löschen eines Elements in std::hive keinen Verschub anderer Elemente, sondern fĂŒhrt lediglich dazu, dass das gelöschte Element als leer markiert wird, wobei der freigewordene Platz bei der HinzufĂŒgung eines neuen Elements wieder gefĂŒllt wird.
- Die Bibliothek std::linalg wurde mit einer API fĂŒr lineare Algebra, basierend auf BLAS, hinzugefĂŒgt.
- UnterstĂŒtzung fĂŒr den Hazard-Pointer-Synchronisationsmechanismus hinzugefĂŒgt, der es ermöglicht, ohne Sperren zu verhindern, dass der Speicher fĂŒr Objekte freigegeben wird, mit denen in anderen Threads weiterhin gearbeitet wird. Bei der Löschung eines Objekts wird es lediglich als gelöscht markiert, aber der vom Objekt belegte Speicher wird erst freigegeben, wenn alle Threads den wĂ€hrend der Arbeit mit dem Objekt gesetzten Hazard-Pointer entfernt haben.
- UnterstĂŒtzung fĂŒr den RCU (Read-Copy Update)-Synchronisationsmechanismus hinzugefĂŒgt â bei SchreibvorgĂ€ngen wird eine neue Instanz des Objekts erstellt, wĂ€hrend LesevorgĂ€nge nicht blockiert werden und weiter mit der alten Instanz arbeiten. Nach Abschluss der Ănderungen wird die neue Instanz aktiv, und neue Leseoperationen werden bereits mit ihr durchgefĂŒhrt, wĂ€hrend die alte Instanz nach dem Abschluss aller sie lesenden Threads gelöscht wird.
- Ănderungen zur Verbesserung der Sicherheit der Standardbibliothek vorgenommen, wie z. B. ĂberprĂŒfungen auf gĂŒltige Werte und PufferĂŒberschreitungen. Beispielsweise wird bei dem Zugriff auf das Element "constexpr reference operator[](size_type idx) const;" eine PrĂŒfung hinzugefĂŒgt, ob "idx < size()".
- Die Möglichkeit, das SchlĂŒsselwort "constexpr" mit einer Variante des Operators "new" (Placement new) zu verwenden, um ein Objekt wĂ€hrend der Kompilierung im Voraus zugewiesenen Speicher zu platzieren, wurde bereitgestellt.
- UnterstĂŒtzung fĂŒr strukturierte Bindungen (structured binding) im Kontext von âconstexprâ hinzugefĂŒgt, d.h. Referenzen auf konstante AusdrĂŒcke können jetzt selbst konstante AusdrĂŒcke sein. Die UnterstĂŒtzung wurde fĂŒr Arrays und einfache Strukturen implementiert. constexpr int arr[] = {1, 2}; constexpr auto [x, y] = arr;
- Die strukturierten Bindungen wurden um die Möglichkeit erweitert, die Syntax â...â zur Angabe von Paketen (pack), die die verbleibende Anzahl von Elementen aus der zuweisbaren Sequenz erfassen, zu verwenden. auto [x,y,z] = f(); // in die Variablen x, y, z werden drei Elemente geschrieben, die von f() zurĂŒckgegeben werden. auto [âŠxs] = f(); // im Paket xs werden alle Elemente gespeichert, die von f() zurĂŒckgegeben werden. auto [x, âŠrest] = f(); // In x wird das erste Element gespeichert, wĂ€hrend in rest die ĂŒbrigen gespeichert werden. auto [x, y, âŠrest] = f(); // In x wird das erste Element gespeichert, in y das zweite und in rest das dritte. auto [x, âŠrest, z] = f(); // in x â das erste, in rest â das zweite, in z â das dritte.
- UnterstĂŒtzung fĂŒr die âtriviale Beweglichkeitâ von Typen (Trivial Relocatability) hinzugefĂŒgt, die es ermöglicht, Bewegungen von Objekten eines bestimmten Typs durch deren Klonierung im Speicher ohne Aufruf von Konstruktoren oder Destruktoren zu optimieren. FĂŒr Klassen wurden die Eigenschaften memberwise_trivially_relocatable und memberwise_replaceable implementiert, und fĂŒr die niedrige Stufe der Bewegung eines oder mehrerer Objekte wurden die Funktionen trivially_relocate_at und trivially_relocate hinzugefĂŒgt.
- UnterstĂŒtzung fĂŒr das Anheften der Funktion main() an ein globales Modul und die Definition der Funktion main() in benannten Modulen implementiert.
- Variadischer Operator âfriendâ (âfriend TsâŠâ) hinzugefĂŒgt.
- Attribute fĂŒr strukturierte Bindungen implementiert;
- Syntax â= delete(âGrundâ)â hinzugefĂŒgt.
- Zum Grundzeichensatz wurden â@â, â$â und â`â hinzugefĂŒgt.
- Möglichkeit zur Anwendung strukturierter Bindung (structured binding) als Bedingung in den Operatoren if und switch bereitgestellt.
- Die Möglichkeit zur Verwendung mehrerer Platzhalter-Variablen mit dem Namen â_â in einem Sichtbarkeitsbereich hinzugefĂŒgt, beispielsweise sind jetzt folgende Konstruktionen korrekt: struct S { int _, _; }; void func() { int _, _; } void other() { int _; // vorher wurde eine Warnung im Modus -Wunused ausgegeben }
- Die Möglichkeit zur Verwendung von String-Literalen in einem Kontext wurde bereitgestellt, in dem sie nicht zur Initialisierung von Zeichenarrays verwendet werden und nicht in den resultierenden Code gelangen, sondern nur zur Compile-Zeit fĂŒr Diagnosemeldungen und Preprocessing angewendet werden, beispielsweise als Parameter fĂŒr Direktiven und Attribute wie _Pragma, asm, extern, static_assert, [[deprecated]] und [[nodiscard]].
- Es wurden neue eingebaute Funktionen hinzugefĂŒgt: â__builtin_is_within_lifetimeâ zur ĂberprĂŒfung der AktivitĂ€t eines Alternativwertes in unions und â__builtin_is_virtual_base_ofâ zur ĂberprĂŒfung, ob eine Basisklasse virtuell ist.
- Triviale unendliche Schleifen ohne undefiniertes Verhalten wurden implementiert.
- Es wird ein Fehler ausgegeben, wenn ein Zeiger auf einen unvollstÀndigen Typ gelöscht wird.
- Die Syntax zur Definition variadischer Parameter mit Ellipsen ohne vorhergehendes Komma wurde als veraltet erklĂ€rt (z.B. wenn âvoid e(intâŠ)â anstelle von âvoid e(int, âŠ)â angegeben wird).
- Die Verwendung von Makros zur Deklaration von Modulen ist verboten.
- Die implizite Umwandlung von enumerierten Werten in arithmetischen Berechnungen wurde als veraltet angesehen. int main() { enum E1 { e }; enum E2 { f }; bool b = e <= 3.7; // veraltet int k = f - e; // veraltet int x = +f - e; // OK }
- Die UnterstĂŒtzung fĂŒr den direkten Vergleich von Arrays wurde eingestellt. int arr1[5]; int arr2[5]; bool same = arr1 == arr2;
- Die Vorlage der Klasse is_trivial wurde als veraltet erklÀrt.
Quelle: opennet.ru
