Am 15. Juli 17 wurde P0329R4 in die aufgenommenc ++ 20Standard: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0329r4.pdf
Dies bringt begrenzte Unterstützung fürc99Designated Initializers. Diese Einschränkung wird in C.1.7 [diff.decl] .4 wie folgt beschrieben:
struct A { int x, y; };
struct B { struct A a; };
Die folgenden designierten Initialisierungen, die in C gültig sind, sind in C ++ eingeschränkt:
struct A a = { .y = 1, .x = 2 }
ist in C ++ ungültig, da Bezeichner in der Deklarationsreihenfolge der Datenelemente erscheinen müssen
int arr[3] = { [1] = 5 }
ist in C ++ ungültig, da die vom Array festgelegte Initialisierung nicht unterstützt wird
struct B b = {.a.x = 0}
ist in C ++ ungültig, da Bezeichner nicht verschachtelt werden können
struct A c = {.x = 1, 2}
ist in C ++ ungültig, da entweder alle oder keine der Datenelemente von Bezeichnern initialisiert werden müssen
Zum c ++ 17und früher hat Boost tatsächlich Unterstützung für Designated Intializers und es gab zahlreiche Vorschläge, um die Unterstützung für die hinzuzufügenc ++Standard, zum Beispiel: n4172 und Daryle Walkers Vorschlag, Initialisierern eine Bezeichnung hinzuzufügen . Die Vorschläge zitieren die Umsetzung vonc99Designated Initializers in Visual C ++, gcc und Clang behaupten:
Wir glauben, dass die Änderungen relativ einfach umzusetzen sein werden
Das Standardkomitee lehnt solche Vorschläge jedoch wiederholt ab und erklärt:
Die EWG stellte verschiedene Probleme mit dem vorgeschlagenen Ansatz fest und hielt es nicht für möglich, das Problem zu lösen, da es viele Male versucht wurde und jedes Mal fehlschlug
Die Kommentare von Ben Voigt haben mir geholfen, die unüberwindlichen Probleme mit diesem Ansatz zu erkennen. gegeben:
struct X {
int c;
char a;
float b;
};
In welcher Reihenfolge würden diese Funktionen aufgerufen? c99: struct X foo = {.a = (char)f(), .b = g(), .c = h()}
? Überraschenderweise inc99::
Die Reihenfolge der Auswertung der Unterausdrücke in einem Initialisierer ist unbestimmt geordnet [ 1 ]
(Visual C ++, gcc und Clang scheinen ein vereinbartes Verhalten zu haben, da sie alle die Anrufe in dieser Reihenfolge tätigen werden :)
h()
f()
g()
Die Unbestimmtheit des Standards bedeutet jedoch, dass bei einer Interaktion dieser Funktionen auch der resultierende Programmstatus unbestimmt wäre und der Compiler Sie nicht warnen würde : Gibt es eine Möglichkeit, sich vor schlecht benommenen designierten Initialisierern zu warnen ?
c ++ hat strenge Anforderungen an die Initialisierungsliste 11.6.4 [dcl.init.list] 4:
Innerhalb der Initialisiererliste einer Klammer-Init-Liste werden die Initialisierer-Klauseln, einschließlich aller Klauseln, die sich aus Pack-Erweiterungen (17.5.3) ergeben, in der Reihenfolge ausgewertet, in der sie erscheinen. Das heißt, jede Wertberechnung und jeder Nebeneffekt, die einer bestimmten Initialisierungsklausel zugeordnet sind, wird vor jeder Wertberechnung und jedem Nebeneffekt, der einer Initialisierungsklausel zugeordnet ist, die darauf folgt, in der durch Kommas getrennten Liste der Initialisierungsliste sequenziert.
So c ++ Für den Support wäre dies in der folgenden Reihenfolge erforderlich gewesen:
f()
g()
h()
Kompatibilität mit früheren brechen c99Implementierungen.
Wie oben erläutert, wurde dieses Problem durch die Einschränkungen für Designated Initializers umgangen, die in akzeptiert wurdenc ++ 20. Sie bieten ein standardisiertes Verhalten und garantieren die Ausführungsreihenfolge der Designated Initializers.