Существуют ли точки последовательности в фигурных списках инициализаторов, когда они применяются к конструкторам?
Согласно стандартному документу n4296 C ++:
[dcl.init.list] (8.5.4.4) (pg223-224)
В пределах списка инициализатора списка фигурных скобок предложения инициализатора, включая любые, которые являются результатом расширений пакета (14.5.3), оцениваются в порядке, в котором они появляются. То есть каждое вычисление значения и побочный эффект, связанный с данным предложением инициализатора, упорядочивается перед каждым вычислением значения и побочным эффектом, связанным с любым предложением инициализатора, которое следует за ним в списке через запятую списка инициализатора.[Примечание: этот порядок оценки выполняется независимо от семантики инициализации; например, он применяется, когда элементы списка инициализатора интерпретируются как аргументы вызова конструктора, хотя обычно нет никаких ограничений последовательности аргументов вызова. —Конечная записка]
(акцент мой)
Примечание было добавлено здесь:http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1030
Это читает мне, что следующий код:
#include <iostream>
struct MyType {
MyType(int i, int j, int k, int l)
: sum(i + j + k + l)
{
}
int sum;
};
int main()
{
int i = 0;
std::cout << MyType{ ++i, ++i, ++i, ++i }.sum << '\n';
}
Должно быть напечатано «10».
Это мое рассуждение:
MyType инициализируется через список фигурных скобокБрекеты-init-списки оцениваются в порядкедаже когда этоинтерпретируется как аргументы вызова конструктораэто означает, что он должен оцениваться как MyType (1,2,3,4)То есть приведенный выше код должен вести себя точно так же, как этот код:
#include <initializer_list>
#include <iostream>
int main()
{
int i = 0;
std::initializer_list<int> il{++i, ++i, ++i, ++i};
std::cout << *il.begin() + *(il.begin() + 1) + *(il.begin() + 2) + *(il.begin() + 3) << '\n';
}
Но это не так. Первый пример печатает «16», а второй пример печатает «10»
Буквально каждый компилятор от каждого поставщика, которому я могу достать отпечатки «16»,по-видимому игнорируя эту часть стандарта и не вставляя точки последовательности.
Что мне здесь не хватает?
Примечание: следующее, кажется, связано с этим вопросом:
(Оптимизация?) Ошибка, связанная с GCC std :: threadhttps://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253