22
votes

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?

1
This is a GCC bug. Clang gets it correct.Xeo
What are you expecting us to aswer? "Yes it is a bug because of the quote you are giving". Hasn't this been said twice today? Both in the question by @Dietmar and in the question Dietmar references, quotes and examples were given that state that the order is left to right.Johannes Schaub - litb
@JohannesSchaub-litb: I'm just making sure that is a bug in the compiler and that there is absolutely nothing wrong with my test code.Nawaz
I'd also check back before going through the bug reporting procedure at gcc.Jonas Schäfer

1 Answers

11
votes

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.

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