15 липня '17 P0329R4 було прийнято до складуc ++ 20стандарт: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0329r4.pdf
Це забезпечує обмежену підтримкуc99призначені ініціалізатори. Це обмеження описано у розділі C.1.7 [diff.decl] .4, якщо:
struct A { int x, y; };
struct B { struct A a; };
Наступні призначені ініціалізації, які діють на C, обмежені в C ++:
struct A a = { .y = 1, .x = 2 }
недійсний у C ++, тому що позначки повинні відображатися в порядку декларування членів даних
int arr[3] = { [1] = 5 }
недійсний у C ++, оскільки ініціалізація, визначена масивом, не підтримується
struct B b = {.a.x = 0}
недійсний у C ++, тому що конструктори не можуть бути вкладені
struct A c = {.x = 1, 2}
недійсний у C ++, тому що або всі, або жоден із членів даних повинен бути ініціалізований позначеннями
Для c ++ 17і раніше Boost насправді має підтримку призначених Intializer, і було багато пропозицій щодо підтримки підтримкиc ++стандарт, наприклад: n4172 та пропозиція Дарила Уокера про додавання позначення до ініціалізаторів . Пропозиції цитують виконанняc99Позначені ініціалізатори у Visual C ++, gcc та Clang, які заявляють:
Ми вважаємо, що зміни можна буде відносно просто здійснити
Але стандартний комітет неодноразово відхиляє такі пропозиції , заявляючи:
EWG знайшла різні проблеми із запропонованим підходом, і не вважає, що це можливо намагатися вирішити проблему, оскільки це було перепробовано багато разів і кожен раз, коли воно не вдалося
Коментарі Бена Войта допомогли мені побачити непереборні проблеми з таким підходом; дано:
struct X {
int c;
char a;
float b;
};
У якому порядку будуть закликатися ці функції c99: struct X foo = {.a = (char)f(), .b = g(), .c = h()}
? Дивно, але вc99:
Порядок оцінки підекспресій у будь-якому ініціалізаторі невизначено послідовно [ 1 ]
( Здається, Visual C ++, gcc та Clang мають згоду на поведінку, оскільки всі вони здійснюватимуть дзвінки в цьому порядку :)
h()
f()
g()
Але невизначений характер стандарту означає, що якби ці функції мали будь-яку взаємодію, то стан програми також був би невизначений, і компілятор не попередив би вас : Чи є спосіб попередити про неправильне поведінку призначених ініціалізаторів?
c ++ дійсно має жорсткі вимоги до ініціалізатор-лист 11.6.4 [dcl.init.list] 4:
У списку ініціалізатора списку, встановленого braced-init, засади ініціалізатора, включаючи будь-які, що є результатом розширення пакету (17.5.3), оцінюються в тому порядку, в якому вони з'являються. Тобто, кожне обчислення значення та побічний ефект, пов'язаний із заданим ініціалізаційним пунктом, секвенується перед кожним обчисленням значення та побічним ефектом, пов’язаним із будь-яким ініціалізаторним застереженням, яке слідує за ним у списку відокремлених комами списку ініціалізатора.
Так c ++ підтримка вимагала б, щоб це було виконано в порядку:
f()
g()
h()
Порушення сумісності з попередніми c99реалізації.
Як було обговорено вище, цю проблему обійшли обмеження щодо прийнятих у визначені ініціалізаториc ++ 20. Вони забезпечують стандартизовану поведінку, гарантуючи порядок виконання призначених ініціалізаторів.