В другой теме, @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
. Даже идеон дает этот вывод.
Это ошибка в компиляторе?