Bugs C ++ 20. Ergebnisse des Treffens in Belfast

Neulich fand in Belfast eine Sitzung des Komitees für Standardisierung der Programmiersprache C ++ statt. Rund 400 Kommentare zu C ++ 20 kamen von den Ländervertretern in das Komitee, und die Hälfte von ihnen schaffte es, sich damit auseinanderzusetzen.

Unter dem Schnitt warten Sie auf die Ergebnisse der Diskussionen über russische Kommentare (ja, IHRE Kommentare zu C ++ 20), einige Kommentare aus anderen Ländern und natürlich auf das geeignete neue C ++ 23 (Executors!).

Alle Probleme mit C ++, die auf der Website stdcpp.ru , im Chat @ProCxx , bei der Arbeit in Yandex.Taxi oder persönlich auf Konferenzen erwähnt wurden, haben wir in Form von Kommentaren zu C ++ 20 formalisiert. Und was kam daraus ...

std :: atomic <int> a {}; und std :: atomic <int> b;


Es mag seltsam erscheinen, aber die Variablen a und b werden nicht auf 0 initialisiert. Um eine atomare Variable auf Null zu initialisieren, musste std :: atomic <int> mit {0} geschrieben werden.

Dieses Verhalten ist völlig offensichtlich und viele Entwickler haben sich selbst verbrannt. Das Komitee akzeptierte unsere Bemerkung zum Standard, und in C ++ 20 initialisieren die Standardkonstruktoren für std :: atomic_flag und std :: atomic die Variablen in clear state bzw. T ().

std :: launder


Ab C ++ 17 hat der Standard eine beängstigende Funktion std :: launder. Die Mitglieder des Komitees waren der Meinung, dass Standardbibliotheksentwickler und normale Benutzer herausfinden würden, wie sie damit umgehen sollen.

In der Praxis hat sich herausgestellt, dass diese Funktion in einigen Fällen nicht verwendet werden kann. Es ist äußerst unübersehbar, dass dies grundsätzlich erforderlich ist:

struct C { const int c; }; std::vector<C> v = {C{1}}; v.pop_back(); v.push_back(C{2}); assert(v.back().c == 2); // ]:-> 

Wenn Sie den Buchstaben des Standards genau befolgen, können die Eigenschaften des Compilers und der Mondphase je nach Implementierung der Standardbibliothek bestehen oder scheitern.

Bei der Erörterung des Problems stellte sich heraus, dass die Optimierung, zu deren Zweck der Standard ein derart seltsames Verhalten beschrieb, nur in einem der Compiler implementiert war und keine spürbare Leistungssteigerung brachte.

Ab C ++ 20 können Sie also Strukturen mit Links und konstanten Feldern sicher in std :: optional, std :: variante, std :: vector, std :: deque usw. speichern. Jetzt wendet die Platzierung new automatisch einen Teil der std-Logik an: : waschen.

* dies in Konstruktoren


Dies ist einer der Kommentare, bei denen ein Fehler auf uns wartete:

 struct C { C(C&& other) noexcept : initial_(other.initial_) , secondary_(other.initial_) // O_O {} int initial_; int secondary_; }; 

Gemäß den aktuellen Regeln hat der Compiler in der Zeile mit O_O das Recht anzunehmen, dass & other == this und dementsprechend eine Zeile darüber den Wert von other.initial_ neu geschrieben und neu gelesen werden muss.

Mit anderen Worten, der Compiler hat das Recht anzunehmen, dass eine noch nicht erstellte Klasse mit dem Parameter versehen ist, aus dem das Objekt erstellt wird, und aus diesem Grund nicht optimalen Code generieren kann.

Einige Compiler (z. B. GCC) glauben, dass Benutzer keine solche Schande schreiben, und glauben, dass Aliasing nicht möglich ist.

Das Komitee lehnte unsere Bemerkung "Nehmen wir an, dass Aliasing nicht möglich ist" ab. Wie sich herausstellte, haben einige Codebasen beängstigende Hacks, bei denen & andere == und die Leute sind noch nicht bereit, sich von ihnen zu verabschieden.

Operator <=> und eingebettete Programmierung


Damit der Raumschiffoperator funktioniert, benötigen Sie die Header-Datei <compare>. Es befand sich jedoch nicht in der Liste der Header-Dateien, die auf einer Plattform verfügbar sind (auf den sogenannten freistehenden Implementierungen der Standardbibliothek, die auf einem beliebigen Bügeleisen verwendet werden können).

Jetzt steht es auf der Liste :)

Der rest


Nach unseren anderen Kommentaren wurde das Urteil „Not in C ++ 20“ erlassen:
* Wir wollten, dass __func__ in constexpr verwendet wird.
* Wir wollten, dass das Konzept nicht den unvollständigen Typ verwendet, da sonst mehrere ODR-Verstöße auftreten. Die Bemerkung hatte jedoch einen unerwartet positiven Effekt: Compiler geben jetzt eine Warnung aus, wenn Sie die unvollständige Eingabe von erforderlich verwenden.
* Wir wollten den Zuweisungsoperator für std :: string korrigieren, damit ein solches Durcheinander nicht auftritt:

 basic_string::operator=(charT c): double d = 3.14; std::string s; s = d; // Compiles 

Das Komitee schlug vor, ein separates Papier zu schreiben und dieses nach C ++ 20 zu korrigieren.
* Wir wollten die Zuweisung temporärer Zeilen in std :: string_view beenden:
 std::string foo(); std::string_view sv; sv = foo(); // Compiles... dangling reference 

Das Ergebnis ist das gleiche wie in der vorherigen Bemerkung: Das Komitee schlug vor, ein separates Papier zu schreiben und dieses nach C ++ 20 zu korrigieren.
* Wir haben darum gebeten, dass der folgende Code kompiliert wird:

 #include <type_traits> template <typename... Xs> auto f (Xs...) -> std::invoke_result_t<Xs...>; 

Uns wurde gesagt, dass alles kompliziert ist, es gibt praktisch keine Chance, C ++ 20 zu reparieren.

Kommentare aus anderen Ländern


Wichtige Änderungen: Hinzufügen von Konstruktoren für std :: span aus Typen, die das Konzept von range :: contiguous_range erfüllen. So kann Span jetzt implizit aus std :: vector und std :: string erstellt werden. Wir haben auch den Konstruktor std :: string_view aus zwei Iteratoren hinzugefügt, die das Konzept von range :: contiguous_iterator erfüllen.

Unterhaltsame Änderungen erwarteten <Vergleichen>. In den letzten drei Jahren hat sich der Betreiber <=> stark verändert. Er ist nicht mehr an Vergleichen für Gleichheit beteiligt, und dementsprechend wird ein Drittel des Inhalts von <Vergleichen> nicht mehr benötigt. Mehrere Länder haben dies bemerkt - sie haben den Standard reduziert.

Eine große Veränderung hat sich in nicht typisierte Template-Parameter eingeschlichen. In C ++ 20 können fast alle Klassen (siehe S1907) mit einem Constexpr-Destruktor und öffentlichen Elementen als Vorlagenparameter übergeben werden, auch wenn die Klasse Gleitkommatypen oder Links enthält.

Wir haben auch die fehlende Konstante zu verschiedenen Teilen des Standards hinzugefügt und die Namen und die Reihenfolge der Argumente einiger neuer Funktionen in C ++ 20 geändert. Es gibt auch zahlreiche Änderungen für Konzepte und Bereiche, Abkürzungen des Standardtexts und andere Kleinigkeiten.

Zahlen TS


ZaMaZaN4iK und ich konnten das Komitee mit dem C ++ Numerics Work In Progress-Dokument aufrühren. Jetzt gibt es napoleonische Pläne für C ++ 23, um Benutzern eine Reihe neuer Arten von Zahlen (wide_integer, integer, rational) sowie zusätzliche Low-Level-Methoden für die Arbeit mit Überläufen und praktischen Aliasen bereitzustellen.

Mir wurde gesagt, ich solle eine Präsentation für das nächste Treffen mit einer Einführung in die Ideen für das gesamte Komitee vorbereiten.

Vollstrecker


Executors ist eine der Prioritäten von C ++ 23. Sie sind für die reaktive Programmierung, für die asynchrone Programmierung (Netzwerk, Datenträger, Prozesse ...) erforderlich, bilden die Grundlage für die Coroutine-Planung und sollten eine einzige Schnittstelle für Bibliotheken von Drittanbietern bieten.

Gleichzeitig sollten Executoren die Algorithmen für ihre interne Implementierung optimieren. Zum Beispiel für Code:

 template <std::input_range Range> void MySort(Range& data) { namespace stdr = std::ranges; std::sort(GetGlobalExecutor(), stdr::begin(data), stdr::end(data), 42); } 

Die GetGlobalExecutor () -Funktion kann Folgendes zurückgeben:
* Single-Threaded-Executor - Er sollte die übliche std :: sort in seinem Thread ausführen.
* Multithread-Executor - sollte eine parallele Sortierung durchführen;
* GPU-Executor - Er muss die Daten in den Speicher der Grafikkarte verschieben, dort sortieren und die Daten zurückgeben.
* NUMA-Testamentsvollstrecker - ...
* ...

Um solche Funktionen zu implementieren, müssen Sie bisher beängstigende Anpassungspunktobjekte (CPO) erstellen und jeden Algorithmus in diese umwandeln. Dem Ausschuss hat es nicht gefallen ...

Zumindest haben sie das P0443 - die Basisschnittstelle - vorab genehmigt . Alle nachfolgenden Sätze für Testamentsvollstrecker müssen in Form von Patches für P0443 geschrieben werden.

Anstelle von Summen


Jetzt sind wir durch nur eine Ausschusssitzung von C ++ 20 getrennt. Nur noch ein bisschen übrig ...

Nun, jeder, der live mit Vertretern des Komitees plaudern möchte - schauen Sie sich die Mitaps und C ++ Konferenzen an (*) :
* Corehard in Minsk
* C ++ Sibirien 2020
* C ++ Russland 2020
* St. Petersburg C ++ Benutzergruppe
* C ++ Meetup 2019 in Moskau

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

Source: https://habr.com/ru/post/de474716/


All Articles