Скажем, я хочу сослаться на члена initializer_list
что я уже определил. Могу ли я это сделать?
Этот код компилируется и дает ожидаемое: «13 55» в Visual Studio и НКУ, Я просто хотел бы знать, что это законно:
const int foo[2] = {13, foo[0] + 42};
Итак, что мы имеем здесь, это совокупная инициализация, описанная в разделе 8.5.1
проекта стандарта C ++, в котором говорится:
Агрегат — это массив или класс […]
а также:
Когда агрегат инициализируется списком инициализаторов, как указано
в 8.5.4 элементы списка инициализатора принимаются как
инициализаторы для элементов агрегата, в возрастающем индексе
или заказ участника. Каждый член инициализируется копией из
соответствующее предложение инициализатора […]
Хотя кажется разумным, что побочные эффекты от инициализации каждого члена агрегата должны быть упорядочены до следующего, поскольку каждый элемент в списке инициализатора является полным выражением. Стандарт на самом деле не гарантирует этого, мы можем видеть это из отчет о дефекте 1343 который говорит:
Текущая формулировка не указывает на то, что инициализация неклассного объекта является полным выражением, но предположительно должна это делать.
а также отмечает:
Агрегированная инициализация также может включать более одного полного выражения, поэтому приведенное выше ограничение на «инициализацию объекта не класса» является неправильным.
и мы можем видеть из связанной тема обсуждения Ричард Смит говорит:
[intro.execution] p10: «Полное выражение — это выражение, которое не является
подвыражение другого выражения. […] Если языковая конструкция
определяется для создания неявного вызова функции, использование
Языковая конструкция считается выражением для целей
этого определения. «Так как braced-init-list не является выражением, и в этом случае оно
[intro.execution] p14: «Каждое значение вычисления и побочный эффект
не приводит к вызову функции, 5 и s.i являются отдельными
с полными выражениями. Затем:
ассоциируется с полным выражением перед каждым значением
вычисления и побочный эффект, связанный со следующим полным выражением
быть оцененным. «Так что единственный вопрос, это побочный эффект инициализации s.i
«связано» с оценкой полного выражения «5»? Я думаю
единственное разумное предположение состоит в том, что это так: если 5 инициализируют
член класса, вызов конструктора, очевидно, будет частью
полное выражение по определению в [intro.execution] p10, так что
Естественно предположить, что то же самое верно для скалярных типов.Тем не менее, я не думаю, что стандарт на самом деле прямо говорит об этом
в любом месте.
Так что в настоящее время это не определено стандартом и на него нельзя положиться, хотя я был бы удивлен, если бы реализация не отнеслась к нему так, как вы ожидаете.
Для простого случая, подобного этому, что-то похожее на это кажется лучшей альтернативой:
constexpr int value = 13 ;
const int foo[2] = {value, value+42};
предложение P0507R0: основная проблема 1343: последовательность инициализации, не относящейся к классу уточняет точку полного выражения Вот но не отвечает на вопрос о том, включен ли побочный эффект инициализации в оценку полного выражения. Так что это не меняет того, что это не указано.
Соответствующие изменения для этого вопроса находятся в [Intro.execution]:
Составное выражение определяется следующим образом:
(9.1) — Составным выражением выражения является это выражение.
(9.2) — Составные выражения списка скобок-init-списка или (возможно, заключенного в скобки) выражения-списка являются
составные выражения элементов соответствующего списка.(9.3) — Составные выражения инициализатора фигурной скобки или равенства в выражении form = initializer являются
составные выражения инициализатора-предложения.
[ Пример:struct A { int x; }; struct B { int y; struct A a; }; B b = { 5, { 1+1 } };
составляющие выражения инициализатора, используемые для инициализации b, равны 5 и 1 + 1. — конец примера]
а также [Intro.execution] р12:
Полное выражение
(12.1) — неоцененный операнд (пункт 8),
(12.2) — константа-выражение (8.20),
(12,3) — init-декларатор (пункт 11) или mem-инициализатор (15.6.2), включая составные выражения
инициализатор,(12.4) — вызов деструктора, сгенерированного в конце времени жизни объекта, отличного от временного
объект (15.2) или(12.5) — выражение, которое не является подвыражением другого выражения и которое не является частью
полное выражение.
Так что в этом случае оба 13
а также foo[0] + 42
являются составное выражение которые являются частью полное выражение. Это перерыв в анализ здесь который утверждал, что каждый из них будет своим собственным полным выражением.
Назначенное предложение об инициализации: P0329 содержит следующее дополнение, которое, кажется, делает это хорошо определенным:
Добавить новый абзац в 11.6.1 [dcl.init.aggr]:
Инициализация элементов агрегата оценивается в порядке элементов. То есть,
Все вычисления значений и побочные эффекты, связанные с данным элементом, упорядочены перед таковыми любого элемента, который следует за ним по порядку.
Мы можем видеть, что это отражено в последний проект стандарта.
Других решений пока нет …