Подтвердить что ты не робот

Порядок оценки элементов в инициализации списка

В другой теме, @Dietmar дал это решение:

template <typename... T>
std::tuple<T...> parse(std::istream& in) 
{
    return std::tuple<T...>{ T(in)... };
}

указав, что

Использование инициализации скобок работает, потому что порядок оценки аргументов в списке инициализатора скобок - это порядок, в котором они отображаются. (подчеркните мое)

Соответствующий текст из стандарта С++ (n3485) есть,

В списке инициализаторов списка с привязкой к инициализации предложения инициализатора, включая все, что является результатом разложений пакетов (14.5.3), оцениваются в том порядке, в котором они отображаются. То есть, каждое вычисление значения и побочный эффект, связанный с заданным предложением инициализатора, секвенируются перед вычислением каждого значения и побочным эффектом, связанным с любым предложением инициализатора, которое следует за ним в разделенном запятыми списке списка инициализаторов. [Примечание. Это упорядочение оценки выполняется независимо от семантики инициализации; например, он применяется, когда элементы списка инициализатора интерпретируются как аргументы вызова конструктора, хотя обычно нет ограничений последовательности для аргументов вызова. -end note]


Поэтому я попытался проверить это следующим кодом:

template<int N>
struct A 
{ 
    std::string data;
    A(std::istream & stream) { stream >> data; }
    friend std::ostream& operator<<(std::ostream & out, A<N> const & a) 
    {
        return out << "A"<<N<<"::data = " << a.data;
    }
};
typedef A<1> A1;
typedef A<2> A2;

template<typename ...Args>
void test(std::istream & stream)
{
    std::tuple<Args...> args { Args(stream)... };
    std::cout << std::get<0>(args) << std::endl;
    std::cout << std::get<1>(args) << std::endl;
}

int main()
{
    std::stringstream ss("A1 A2");
    test<A1,A2>(ss);
}

Ожидаемый результат:

A1::data = A1
A2::data = A2

Фактический выход:

A1::data = A2
A2::data = A1

Я сделал что-то неправильно в своем тестовом коде? Я изменил код на это:

std::stringstream ss("A1 A2");
std::tuple<A1,A2> args{A1(ss), A2(ss)};
std::cout << std::get<0>(args) << std::endl;
std::cout << std::get<1>(args) << std::endl

Такой же выход, как и раньше. Я проверил свой код с MinGW (GCC) 4.7.0 и 4.7.2. Даже идеон дает этот вывод.

Это ошибка в компиляторе?

4b9b3361

Ответ 1

Отвечая на мой собственный вопрос. Удаление вопроса не будет хорошей идеей, так как у кого-то может быть тот же вопрос в будущем.

Да. Это ошибка в компиляторе GCC.

взято из @Johannes Schaub комментировать вопрос.