15 lipca 2017 P0329R4 został przyjęty doc ++ 20standard: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0329r4.pdf
Zapewnia to ograniczone wsparcie dlac99Wyznaczone inicjatory. To ograniczenie opisano poniżej w C.1.7 [diff.decl] .4, biorąc pod uwagę:
struct A { int x, y; };
struct B { struct A a; };
Następujące wyznaczone inicjalizacje, które są ważne w języku C, są ograniczone w języku C ++:
struct A a = { .y = 1, .x = 2 }
jest nieprawidłowy w C ++, ponieważ desygnatory muszą występować w kolejności deklaracji członków danych
int arr[3] = { [1] = 5 }
jest nieprawidłowy w C ++, ponieważ inicjalizacja wyznaczona przez tablicę nie jest obsługiwana
struct B b = {.a.x = 0}
jest nieprawidłowy w C ++, ponieważ desygnatory nie mogą być zagnieżdżane
struct A c = {.x = 1, 2}
jest nieprawidłowy w C ++, ponieważ wszystkie lub żadne elementy członkowskie danych nie muszą być inicjowane przez desygnatory
Dla c ++ 17a wcześniej Boost faktycznie obsługuje Desygnowanych Intializatorów i było wiele propozycji dodania obsługic ++standard, na przykład: n4172 i propozycja Daryle Walkera, aby dodać oznaczenie do inicjatorów . Propozycje dotyczą implementacjic99Wyznaczone inicjatory w Visual C ++, gcc i Clang:
Uważamy, że zmiany będą stosunkowo łatwe do wdrożenia
Ale komisja standaryzacyjna wielokrotnie odrzuca takie propozycje , stwierdzając:
EWG znalazł różne problemy z proponowanym podejściem i nie sądził, że jest to wykonalne, aby spróbować rozwiązać problem, ponieważ było to wielokrotnie próbowane i za każdym razem kończyło się niepowodzeniem
Komentarze Bena Voigta pomogły mi dostrzec nie do przezwyciężenia problemy związane z tym podejściem; dany:
struct X {
int c;
char a;
float b;
};
W jakiej kolejności byłyby wywoływane te funkcje c99: struct X foo = {.a = (char)f(), .b = g(), .c = h()}
? Co zaskakujące, wc99:
Kolejność oceny podwyrażeń w dowolnym inicjatorze jest nieokreślona [ 1 ]
( Wygląda na to, że Visual C ++, gcc i Clang mają uzgodnione zachowanie, ponieważ wszystkie będą wykonywać wywołania w tej kolejności :)
h()
f()
g()
Ale nieokreślony charakter standardu oznacza, że gdyby te funkcje miały jakąkolwiek interakcję, wynikowy stan programu również byłby nieokreślony, a kompilator nie ostrzegłby cię : Czy istnieje sposób, aby ostrzec o niewłaściwym działaniu wyznaczonych inicjatorów?
c ++ nie mają rygorystyczne wymogi inicjalizator-List 11.6.4 [dcl.init.list] 4:
W ramach listy inicjalizacyjnej listy inicjalizacyjnej, klauzule inicjalizujące, w tym wszystkie wynikające z rozszerzeń pakietów (17.5.3), są oceniane w kolejności, w jakiej się pojawiają. Oznacza to, że każde obliczenie wartości i efekt uboczny skojarzony z daną klauzulą inicjalizatora jest sekwencjonowany przed każdym obliczeniem wartości i efektem ubocznym związanym z każdą klauzulą inicjalizatora, która następuje po niej, na liście rozdzielanej przecinkami listy inicjalizatora.
Więc c ++ wsparcie wymagałoby wykonania tego w kolejności:
f()
g()
h()
Łamanie kompatybilności z poprzednimi wersjami c99wdrożenia.
Jak omówiono powyżej, omijano ten problem przez ograniczenia dotyczące wyznaczonych inicjatorów zaakceptowanych w programiec ++ 20. Zapewniają ustandaryzowane zachowanie, gwarantując kolejność wykonywania Wyznaczonych inicjatorów.