Der Standard C++26 wurde genehmigt

Das ISO-Ausschuss für die Standardisierung der Programmiersprache C++ hat die finale Version der Spezifikation, die den internationalen Standard „C++26“ bildet, verabschiedet. Die in der Spezifikation aufgeführten Funktionen werden teilweise bereits von den Compilern GCC, Clang und Microsoft Visual C++ unterstützt. Die die C++26 Standardbibliotheken unterstützenden Implementierungen sind im Rahmen des Boost-Projekts realisiert worden.

In den nächsten zwei Monaten wird die verabschiedete Spezifikation in der Phase der Dokumentenvorbereitung zur Veröffentlichung sein, in der ortografische Fehler und Tippfehler redigiert werden. Anfang November wird die resultierende Dokumentenversion zur Veröffentlichung formal unter dem Namen ISO/IEC 14882:2026 an die ISO gesendet.

Die Hauptmerkmale von C++26:

  • Implementierung von Vertragsprogrammierungselementen (Contracts), die es ermöglichen, formale Schnittstellenspezifikationen mit drei neuen Operatoren zu definieren: pre (Vorbedingungen), post (Nachbedingungen) und contract_assert (Behauptungsprüfung). Der Operator "pre" definiert die Bedingungen, die vor dem Aufruf erfüllt sein müssen (Eingabewertprüfung); "post" — die Bedingungen, die nach der Ausführung eingehalten werden müssen (Ausgabewertanforderungen); contract_assert — die Bedingungen für das Auftreten von Ausnahmen. Diese Funktionalität wird in GCC 16 verfügbar sein. int f(const int x) pre (x != 1) // Anforderungen an die Eingaben post (r : r == x && r != 2) // Anforderungen an das Ergebnis; r — das Ergebnis { contract_assert (x != 3); return x; }
  • Unterstützung für Reflexion (Reflection) wurde hinzugefügt, die es ermöglicht, Programmelemente zur Compile-Zeit zu verfolgen und zu modifizieren. Neue Operatoren «^^» zur Gewinnung von Metainformationen zur grammatikalischen Struktur und «[:…:]» für die Durchführung rückwärtiger Transformationen wurden hinzugefügt. Zur Transformation und Verarbeitung der während der Inspektion gewonnenen Informationen wird die Bibliothek std::meta angeboten, und Funktionen wie Berechnungen mit Konstanten sind verfügbar. Die Unterstützung für Reflexion 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 gleich static_assert(^^i != std::meta::reflect_constant(42)); // unterscheidet sich von dem Wert 42
  • Der Operator „template for“ wurde hinzugefügt, um über Elemente wie parameterähnliche Tupelobjekte und Reflexionsergebnisse (Meta-Objekte) während des Kompilierungsprozesses in Form einer herkömmlichen Schleife zu iterieren. Bei der Ausführung von „template for“ wird der Schleifenrumpf für jedes Element aufgedeckt und jede Iteration wird in einem separaten Gültigkeitsbereich verarbeitet, in dem die in der Schleife änderbare 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 aufgelöst 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 std::execution-Framework wurde hinzugefügt, um asynchrone und parallele Codeausführung zu ermöglichen. Es werden Objekte bereitgestellt: scheduler, der den Ausführungsplaner (Thread, Thread-Pool, GPU, Ereignisschleife) definiert, sender, der die auszuführende Aufgabe bestimmt, 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 std::simd-Bibliothek wurde hinzugefügt, um die Parallelisierung von Datenoperationen mithilfe von SIMD-Befehlssätzen wie AVX-512 und NEON mit dem Standardtypensystem von C++ zu ermöglichen. 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 eines variablen Vektors (Arrays) std::inplace_vector wurde vorgeschlagen, der im Stack angeordnet ist und dessen Größe zur Kompilierungszeit festgelegt wird. Die API ähnelt std::vector, jedoch werden die Elemente des Arrays 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, um in den Code binärer Ressourcen eingebettet zu werden. const unsigned char icon_display_data[] = { #embed „art.png“ };
  • Die Unterstützung für die Generierung und Verarbeitung von Ausnahmen zur Compile-Zeit bei Fehlern im Kontext von constexpr wurde 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 ungeordneten Speicher zu speichern und die durch gelöschte Elemente freigewordene Speicherwiederverwendung zu gewährleisten. Die Struktur ist für Workloads mit hoher Intensität beim Hinzufügen und Entfernen von Elementen in beliebiger Reihenfolge optimiert. Im Gegensatz zu Arrays führt das Entfernen eines Elements in std::hive nicht zu einer Verschiebung anderer Elemente, sondern kennzeichnet das gelöschte Element als leer, wobei die freigewordene Position beim Hinzufügen eines neuen Elements wieder aufgefüllt wird.
  • Die Bibliothek std::linalg mit einer API für lineare Algebra, basierend auf BLAS, wurde hinzugefügt.
  • Die Unterstützung des Hazard Pointer-Synchronisierungsmechanismus wurde hinzugefügt, der es ermöglicht, die Freigabe von Speicher für Objekte, mit denen in anderen Threads weitergearbeitet wird, ohne die Verwendung von Sperren zu verhindern. Beim Löschen eines Objekts wird dieses nur als gelöscht markiert, der von ihm beanspruchte Speicher wird jedoch erst freigegeben, wenn alle Threads den während der Arbeit mit dem Objekt gesetzten Hazard-Pointer entfernt haben.
  • Die Unterstützung des RCU (Read-Copy Update)-Synchronisierungsmechanismus wurde hinzugefügt — bei Schreibvorgängen wird eine neue Instanz des Objekts erstellt, während die Lesevorgänge nicht blockiert werden und mit der alten Instanz weiterarbeiten. Nach Abschluss der Änderungen wird die neue Instanz aktiv, und die neuen Lesevorgänge erfolgen nun damit, während die alte Instanz nach Abschluss der Lesevorgänge durch deren Threads gelöscht wird.
  • Änderungen zur Verbesserung der Sicherheit der Standardbibliothek wurden vorgenommen, darunter Prüfungen auf zulässige Werte und Pufferüberläufe. Zum Beispiel wird beim Zugriff auf das Element „constexpr reference operator[](size_type idx) const;“ eine Bedingungsprüfung „idx < size()“ hinzugefügt.
  • Die Verwendung des Schlüssels "constexpr" mit einer Variante des Operators "new" (Placement New) wurde ermöglicht, um ein Objekt während der Kompilierung im Voraus zuzuweisender Speicher zu platzieren.
  • Die Unterstützung für strukturierte Bindungen (structured binding) im Kontext von "constexpr" wurde 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;
  • Der strukturierte Bindungen wurde die Möglichkeit hinzugefügt, die Syntax "..." zur Angabe von Packungen (pack) zu verwenden, die die verbleibende Anzahl von Elementen aus der zuweisbaren Sequenz erfassen. auto [x,y,z] = f(); // in die Variablen x, y, z werden drei Elemente gespeichert, die von f() zurückgegeben wurden. auto […xs] = f(); // in das Paket xs werden alle Elemente gespeichert, die von f() zurückgegeben wurden. auto [x, …rest] = f(); // In x wird das erste Element und in rest die übrigen gespeichert. auto [x, y, …rest] = f(); // In x wird das erste Element, in y das zweite und in rest das dritte gespeichert. auto [x, …rest, z] = f(); // in x das erste, in rest das zweite und in z das dritte.
  • Die Unterstützung für die "triviale Relokation" von Typen (Trivial Relocatability) wurde hinzugefügt, was es ermöglicht, Bewegungen von Objekten eines bestimmten Typs durch deren Klonen im Speicher zu optimieren, ohne Konstruktoren oder Destruktoren aufzurufen. Für Klassen wurden die Eigenschaften memberwise_trivially_relocatable und memberwise_replaceable implementiert, und für die niedrigstufige Relokation eines oder mehrerer Objekte wurden die Funktionen trivially_relocate_at und trivially_relocate hinzugefügt.
  • Die Unterstützung für das Anheften der Funktion main() an das globale Modul und die Definition der Funktion main() in benannten Modulen wurde realisiert.
  • Der variadic Operator „friend“ („friend Ts…“) wurde hinzugefügt.
  • Attribute für strukturierte Bindungen wurden implementiert;
  • Die Syntax ‚= delete(„Grund“)‘ wurde hinzugefügt.
  • Die Sonderzeichen „@“, „$“ und „`“ wurden in das Basis-Zeichenset aufgenommen.
  • Die Möglichkeit, strukturierte Bindungen (structured binding) als Bedingung in if- und switch-Anweisungen zu verwenden, wurde bereitgestellt.
  • Es wurde die Möglichkeit eingeführt, mehrere Platzhaltervariablen mit dem Namen „_“ in einem Sichtbereich zu verwenden, zum Beispiel sind jetzt folgende Konstruktionen korrekt: struct S { int _, _; }; void func() { int _, _; } void other() { int _; // zuvor wurde eine Warnung im Modus -Wunused ausgegeben }
  • Es wurde die Nutzung von Zeichenfolgenliteralen in Kontexten ermöglicht, in denen sie nicht zur Initialisierung von Zeichenarrays verwendet werden und nicht in den endgültigen Code eingehen, sondern nur während der Kompilierung für diagnostische Meldungen und Preprozessierung verwendet werden, beispielsweise als Parameter von Direktiven und Attributen wie _Pragma, asm, extern, static_assert, [[deprecated]] und [[nodiscard]].
  • Eingebaute Funktionen wurden hinzugefügt: „__builtin_is_within_lifetime“ zur Überprüfung der Aktivität einer Alternative in unions (vereinigungen) und „__builtin_is_virtual_base_of“ zur Überprüfung, ob die Basisklasse virtuell ist.
  • Triviale endlose Schleifen ohne undefiniertes Verhalten wurden implementiert.
  • Ein Fehlerausgabe wird beim Entfernen eines Verweises auf einen unvollständigen Typ bereitgestellt.
  • 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 nicht gestattet.
  • Die impliziten Umwandlungen von Aufzählungswerten in arithmetischen Berechnungen sind in die Kategorie veraltet verschoben worden. 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 Vorlagklasse is_trivial wurde als veraltet erklärt.

    Quelle: opennet.ru
Купить надежный хостинг для сайтов с защитой от DDoS, VPS VDS серверы 🔥 Купить надежный хостинг для сайтов с защитой от DDoS, VPS VDS серверы | ProHoster