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?
Conclusion: All other things being equal, your code will run faster if you use initialization lists rather than assignment.
The initializer list is used to directly initialize data members of a class. An initializer list starts after the constructor name and its parameters.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With