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 фактически поддерживают назначенные инициализаторы, и было множество предложений по добавлению поддержки для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:
В списке инициализаторов списка инициализаторов в фигурных скобках предложения инициализатора, включая те, которые являются результатом расширения пакета (17.5.3), оцениваются в том порядке, в котором они появляются. Таким образом, каждое вычисление значения и побочный эффект, связанный с данным предложением инициализатора, упорядочивается перед каждым вычислением значения и побочным эффектом, связанным с любым предложением инициализатора, которое следует за ним в списке разделенных запятыми списка инициализаторов.
Так C ++ служба поддержки потребовала бы, чтобы это было выполнено в следующем порядке:
f()
g()
h()
Нарушение совместимости с предыдущими c99Реализации.
Как обсуждалось выше, эту проблему удалось обойти за счет ограничений на назначенные инициализаторы, принятые вC ++ 20, Они обеспечивают стандартизованное поведение, гарантируя порядок выполнения назначенных инициализаторов.