Order of evaluation of elements in list-initialization

c++, c++11, gcc, initializer-list, operator-precedence

Solution

Answering my own question. Deleting the question would not be a good idea, as someone might have the same question in the future.

Yes. It is a bug in the GCC compiler.

- Bug 51253 - [C++11][DR 1030] Evaluation order (sequenced-before relation) among initializer-clauses in braced-init-list

taken from @Johannes Schaub's comment to the question.

Problem

In the other topic, @Dietmar gave this solution: ``` template <typename... T> std::tuple<T...> parse(std::istream& in) { return std::tuple<T...>{ T(in)... }; } ``` stating that, The use of brace initialization works because the order of evaluation of the arguments in a brace initializer list is the order in which they appear. (emphasize mine) The relevant text from the C++ Standard (n3485) is, Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (14.5.3), are evaluated in the order in which they appear. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list. [ Note: This evaluation ordering holds regardless of the semantics of the initialization; for example, it applies when the elements of the initializer-list are interpreted as arguments of a constructor call, even though ordinarily there are no sequencing constraints on the arguments of a call. —end note ] So I tried to test this with the following code: ``` 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); } ``` Expected output: ``` A1::data = A1 A2::data = A2 ``` Actual Output: ``` A1::data = A2 A2::data = A1 ``` Did I do anything wrong in my test code? I changed my code to this: ``` 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 ``` Same output as before. I tested my code with `MinGW (GCC) 4.7.0` and `4.7.2`. Even ideone gives this output. Is it a bug in the compiler?

Original source

Related problems