Order of evaluation of elements in list-initialization

生来就可爱ヽ(ⅴ<●) 提交于 2019-11-26 06:44:13

问题


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:


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.



来源:https://stackoverflow.com/questions/14060264/order-of-evaluation-of-elements-in-list-initialization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!