列表初始化中元素的求值顺序 [英] Order of evaluation of elements in list-initialization
问题描述
在其他主题,@Dietmar给出了此解决方案:
In the other topic, @Dietmar gave this solution:
template <typename... T>
std::tuple<T...> parse(std::istream& in)
{
return std::tuple<T...>{ T(in)... };
}
说明
使用括号初始化工作原理是因为括号初始值列表中的参数求值顺序是它们出现的顺序。 (强调我)
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)
C ++标准(n3485)的相关文本是
The relevant text from the C++ Standard (n3485) is,
在braced-init-list的初始化器列表中,initializer-clause(包括从包扩展(14.5.3)得到的结果)将按照它们的顺序出现。也就是说,与给定初始化子句相关联的每个值计算和副作用在每个值计算和与初始化器列表的逗号分隔列表中的其后的任何初始化子句相关联的副作用之前被排序。
[注:此评估排序保持与初始化的语义无关;例如,当初始化器列表的元素被解释为构造函数调用的参数时,即使通常对调用的参数没有排序约束,它也适用。 -end note]
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 ]
所以我试着用下面的代码测试这个: / p>
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);
}
预期输出:
A1::data = A1
A2::data = A2
b $ b
实际输出:
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
与以前相同的输出。我用 MinGW(GCC)4.7.0
和 4.7.2
测试我的代码。即使是ideone也会输出。
Same output as before. I tested my code with MinGW (GCC) 4.7.0
and 4.7.2
. Even ideone gives this output.
这是编译器中的错误吗? / p>
Is it a bug in the compiler?
推荐答案
回答自己的问题。删除此问题不是一个好主意,因为将来可能有相同的问题。
是的。这是GCC编译器中的一个错误。
Yes. It is a bug in the GCC compiler.
- Bug 51253 - [C ++ 11] [DR 1030] braced-init-list 中的initializer-clause中的评估顺序>
- Bug 51253 - [C++11][DR 1030] Evaluation order (sequenced-before relation) among initializer-clauses in braced-init-list
取自@Johannes Schaub对问题的意见。
taken from @Johannes Schaub's comment to the question.
这篇关于列表初始化中元素的求值顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!