C ++ 20 genehmigt! Was Sie erwartet und was Sie für Entwickler in C ++ 23 vorbereiten müssen

Neulich fand in Prag eine Sitzung des internationalen Normungsausschusses C ++ statt. Und-und-und-und ...



C ++ 20 ist fertig! Es bleibt ein Stempel von ISO zu setzen, aber dies ist ein rein formaler Schritt, mit dem es keine Probleme geben sollte.

Herzlichen Glückwunsch an alle zu dieser wundervollen Veranstaltung! Konzepte, Coroutinen, Module, Bereiche, std :: format, constexpr neue und constexpr Algorithmen + Vektor + String, Datum / Uhrzeit, Jthread, Span, Bit_cast und viele andere kleine und große Innovationen.

Was sie im letzten Moment hinzugefügt und behoben haben, was sie zu brechen vorgeschlagen haben und was jeder in C ++ 23 sehen möchte - über all das unter dem Schnitt.

Tricks von C nach C ++ 20


In letzter Zeit hat es Tradition, unerfahrene Entwickler mit undefiniertem Verhalten (UB) in C ++ zu erschrecken. Es ist Zeit, es zu ändern!

Hier ist ein solcher Code beispielsweise für C absolut gültig:

struct X { int a, b; };

X *make_x() {
  X *p = (X*)malloc(sizeof(struct X));
  p->a = 1;
  p->b = 2;
  return p;
}

Aber in C ++ gab es große Probleme damit. C arbeitet mit Bytes und C ++ arbeitet mit Objekten. Das Objekt hat jedoch eine Lebensdauer, und vor C ++ 20 wurde der Beginn des Lebens des Objekts ab dem Aufruf new berücksichtigt.

Das Komitee ist ernsthaft besorgt über die Arbeit auf niedriger Ebene mit Bytes und einfachen Strukturen. Sie haben Verbesserungen eingeführt, die besagen, dass ein bestimmter Satz von Funktionen (memcpy, memmove, malloc, align_alloc, calloc, realloc, bit_cast) die Lebensdauer des Objekts beginnt. Jetzt funktionieren die meisten C-Tricks auf niedriger Ebene garantiert in C ++.

bool ist in C ++ 20 zuverlässiger geworden


Ratet mal, was der Fehler ist:

template <typename T, size_t N>
auto count_unique(const std::array<T, N>& v) {
    return std::unordered_set<T>{v.begin(), v.end()}.size();
}

Antworten
T bool v.begin() v.end() (, libc++ libstdc++) — count_unique 1.

- , std::unordered_set<bool>{v.begin(), v.end()} bool std::unordered_set<bool>{true, true}.

Transformationen in bool werden jetzt als verengende Transformationen betrachtet. Dies ermöglichte es uns, Probleme in vielen Codebasen zu finden (weitere Beispiele im Satz P1957 selbst ).

C ++ 20-Konzepte schneller gemacht


Bis vor kurzem konnte man ein Konzept wie dieses schreiben:

template <class T>
concept Reservable = requires(T v) {
    v.reserve(int{});
};

Und seien Sie überrascht, dass es unterschiedliche Ergebnisse liefert:

struct Test;

static_assert(!Reservable<Test>);

struct Test {
    void reserve(int);
};

static_assert(Reservable<Test>);

Beim letzten Mal haben wir einen Kommentar aus dem Land gesendet: „Machen Sie es unmöglich, unvollständige Typen in Konzepten zu verwenden, da sonst mehrere ODR-Verstöße auftreten.“ Unser Kommentar wurde abgelehnt, aber mit dem Vorschlag P2104 haben wir jetzt teilweise das gewünschte Ergebnis erzielt.

Als Bonus erhalten wir eine schnellere Kompilierung, da Compiler nun berechtigt sind, die Ergebnisse der Anwendung von Konzepten auf Typen zwischenzuspeichern.

Kleinere Änderungen in C ++ 20


  • Ranges hat die Ssize-Methode.
  • Die interne Verknüpfung von Entitäten ist beim Instanziieren von Entitäten zur Verknüpfung von Modulen nicht mehr sichtbar (der Compiler teilt Ihnen mit, was in der Kompilierungsphase falsch ist).
  • Wir haben die Regeln für die Module so geändert, dass jedes Tool leichter mit ihnen arbeiten kann.

Und lassen Sie uns alles in C ++ 23 oder C ++ 26 brechen?


Eine längere Debatte hat einen Vorschlag für eine Application Binary Interface (ABI, nicht mit der API verwechseln) ausgelöst . Interessante Fragen wurden aufgeworfen:

1. Wir können ABI in C ++ 23 vollständig ändern und einen Leistungszuwachs von 5-10% erzielen.


Darüber hinaus müssen alle alten C ++ - Bibliotheken neu erstellt werden, da sie keine Verknüpfung zu Bibliotheken mit dem neuen ABI herstellen können. Sie können keine Bibliotheken verwenden, die mit früheren Versionen von C ++ in einem C ++ 23-Projekt erstellt wurden.

Natürlich wird es immer alte kommerzielle Software geben, die niemand wieder zusammenbauen wird, aber die die Standardbibliothek in Mitleidenschaft zieht (ja, Videospiele, ich spreche von Ihnen!).

Mit einem geringen Stimmenspielraum entschied ABI, C ++ 23 nicht einzubrechen.

2. Geben wir den Benutzern die Garantie, dass wir versuchen, den ABI nicht zu beschädigen oder zu ändern.


Und dann beschlossen sie, keine Garantie zu geben. Verschiedene Anbieter haben unterschiedliche Pläne für ihre Plattformen, und manchmal können sie es sich leisten, den ABI zu brechen, oft ohne den Benutzern Schaden zuzufügen.

Und lassen Sie uns überall hinzufügen, außer?


Historisch gesehen werden in den Standardfunktionen mit Vorbedingungen keine Ausnahmen als noexcept markiert, auch wenn sie niemals Ausnahmen auslösen. Hier zum Beispiel Operator -> haben std :: optional:

constexpr const T* operator->() const;
constexpr T* operator->();
    Requires: *this contains a value.
    Returns: val.
    Throws: Nothing.

Er wirft nichts, aber anstatt nichts zu sagen, heißt es in Worten: "Wirft: Nichts", weil es eine Voraussetzung gibt "* dies enthält einen Wert".

Benutzer mit noexcept werden klarer. Eine gute Idee in P1656 !



Nein!

Es gibt eine ganze Untergruppe SG21: Verträge, die einen gemeinsamen Mechanismus zur Überprüfung von Verträgen (Vor- und Nachbedingungen) vorsieht. Vertragshandler können eine Ausnahme auslösen. Wenn eine Ausnahme von der Funktion noexcept ausgelöst wird, lautet sie std :: terminate und die Anwendung stürzt ab. Wenn Sie eine spezielle Krücke einfügen, die für Vertragsausnahmen aus einer Noexcept-Funktion herausfliegen kann ... dann bricht ohnehin alles zusammen, Typmerkmale werden durch das Vorhandensein von Noexcept geleitet, und sie beginnen, Sie anzulügen. Eine mit noexcept gekennzeichnete Funktion löst eine Ausnahme aus.

Dies ist jedoch nicht das größte Problem. Es gibt Gabeln von Standardbibliotheken, die in einigen Fällen bereits jetzt explizit Vorbedingungsprüfungen einfügen. Haben Sie beispielsweise ein kritisches Projekt, dessen Verfügbarkeit maximiert werden sollte? Sie verwenden eine ähnliche Verzweigung, und wenn jemand plötzlich std :: vector :: back () für einen leeren Vektor aufruft, wird eine Ausnahme ausgelöst, die im Code höher verarbeitet wird, und es wird ein Fallback verwendet. Mit Änderungen von P1656 kann eine solche Bibliothek nicht mehr als Standard betrachtet werden.

Und das sind nicht alle Probleme! .. Das zusätzliche Noexcept für die Standardbibliothek wird nicht nur positive Auswirkungen in Form einer Verringerung der Größe von Binärdateien oder einer höheren Leistung haben, sondern auch den Code von mindestens zwei Unternehmen beschädigen und nicht nur einen der Wege zerstören Verwendung von Verträgen ... so wurde auch der Vorschlag in zwei Untergruppen genehmigt.

Verdienste von RG21


Wie immer haben wir in verschiedenen Untergruppen gearbeitet, Erfahrungen mit der Implementierung ausgetauscht und Vorschläge vorgelegt, deren Autoren nicht kommen konnten.

Eine der herausragenden Ideen, die wir präsentieren konnten, war die Idee von Anton Zhilin P2025 Garantierte Kopierentscheidung für benannte Rückgabeobjekte . Die Implementierung ermöglicht das Erstellen von Factory-Funktionen für Objekte ohne Kopieren und Verschieben von Konstruktoren. Tatsächlich handelt es sich um einen destruktiven Schritt, der seit Mitte der 90er Jahre im Standard heimlich existiert und durch individuelle Sprachregeln ausdrücklich verboten wurde.

Wir haben die Idee erfolgreich durch die EWG-I- und EWG-Instanzen gezogen, dank der hervorragenden Ausarbeitung der Idee durch den Autor selbst. Die CWG-Phase blieb bestehen, und nach einigen Besprechungen besteht jede Möglichkeit, die erforderlichen Wörter im Standard und die ersten Implementierungen in Compilern zu sehen.

Zusätzlich zu dieser Idee haben wir die Idee von P1990R0: Add operator [] über LEWG-I zu std :: initializer_list gezogen und ein nützliches Feedback zu P1944R0 erhalten: constexpr <cstring> und <cwchar> . Beide Ideen von Daniil Goncharov haben jede Chance, in C ++ 23 zu sein.

Im Bereich std :: hash erwartete uns ein unerwarteter Fehler. Die Diskussion von p1406r1: Weitere std :: hash-Spezialisierungen hinzufügen verwandelte sich plötzlich in eine Diskussion über entartete Grenzfälle und die Möglichkeiten von entferntem C ++ 2 *. Infolgedessen beschloss der Ausschuss, nichts zu ändern.

Mit SG6 und Numbers sind sie nicht zusammengewachsen. Die Hauptdiskussionen von SG6 kreuzten sich mit Diskussionen von ABI, weshalb sich das Quorum in SG6 nicht angesammelt hat. Aus diesem Grund p1889: C ++ Numerics Work In Progress , P2010: Entfernen Sie iostream-Operatoren aus P1889 undP1890: C ++ Numerics Work In Progress-Probleme wurden nicht behandelt.

C ++ 23 Pläne


Seit Beginn der Entwicklung von C ++ 20 begann das Komitee nach Plan zu handeln. Nämlich, einige wichtige interessante Ideen für den nächsten Standard zu identifizieren, wonach bei allen nachfolgenden Sitzungen Vorschläge zu anderen Themen nicht berücksichtigt werden sollten, wenn nicht alle zu dem Hauptthema erörtert wurden.

Für C ++ 23 wurde ein solcher Plan gerade in Prag genehmigt. Die Hauptprioritäten von C ++ 23:

  1. Corutin-Unterstützung in der Standardbibliothek
  2. Konvertieren Sie die Standardbibliothek in Module
  3. Ausführende
  4. Vernetzung

Im ersten Absatz werden alle von der CppCoro- Bibliothek geleitet . Wenn Sie also bereits C ++ 20-Coroutinen verwenden möchten, sollten Sie zunächst diese Bibliothek verwenden.

Mit den Modulen, dem zweiten Punkt, müssen Sie sich nur hinsetzen und es tun, es werden keine besonderen Schwierigkeiten erwartet.

Aber Executors ist ein Problem. Ihr Design ist nicht offensichtlich, nicht alle Benutzerfälle sind abgedeckt, in ihrer aktuellen Form wurden sie von niemandem verwendet, und das Design ist immer noch nicht genehmigt.

Der Ausschuss stimmte auch zu, Vorschläge in folgenden Bereichen zu priorisieren:

  • Betrachtung
  • Mustervergleich
  • Verträge

Anstelle von Summen


C ++ 20 ist fertig, es ist Zeit, an C ++ 23 zu arbeiten! Die nächste Ausschusssitzung findet im Sommer statt. Wenn Sie also eine gute Vorstellung von dem neuen Standard haben, teilen Sie sie auf stdcpp.ru und im Telegramm-Chat ProCxx mit .

Nun, alle, die live mit Vertretern des Komitees chatten möchten - schauen Sie sich die Meetings und C ++ - Konferenzen an *:


* Life Hack: Sie müssen kein Konferenzticket bezahlen, wenn Sie Redner sind.

All Articles