列表初始化中元素的求值顺序

23
在这个其他主题中,@Dietmar给出了以下解决方案:
template <typename... T>
std::tuple<T...> parse(std::istream& in) 
{
    return std::tuple<T...>{ T(in)... };
}

声明如下:

使用花括号初始化的原因是,在花括号初始化列表中的参数求值顺序与它们出现的顺序相同。(强调我的)

C++标准(n3485)中相关的文本为:

在大括号初始化列表中,包括任何由pack扩展(14.5.3)导致的初始化程序子句在内的初始化程序列表将按照它们出现的顺序进行评估。也就是说,与给定初始化器子句相关联的每个值计算和副作用都在逗号分隔的初始化列表中后续的任何初始化器子句相关联的每个值计算和副作用之前排序。[注:这种评估顺序不受初始化语义的影响;例如,当将初始化列表的元素解释为构造函数调用的参数时,即使通常对于调用的参数不存在排序约束,它也适用。—结尾注]


所以我尝试使用以下代码进行测试:

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

实际输出:

A1::data = A2
A2::data = A1

我在测试代码中做错了什么吗?我把我的代码改成了这样:
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.04.7.2测试了我的代码。即使是ideone也给出了这个输出结果

这是编译器的一个bug吗?


4
这是GCC的一个错误,Clang则正确。 - Xeo
4
你希望我们回答什么?“是的,这是一个bug,因为你提供了引号。” 这不是今天已经说过两次了吗? 在@Dietmar的问题和Dietmar引用的问题中,都给出了引用和示例,说明顺序是从左到右。 - Johannes Schaub - litb
4
我会尽力为您翻译:@JohannesSchaub-litb: 我只是想确认编译器中是否存在一个错误,以及我的测试代码绝对没有任何问题。 - Nawaz
2
在进行gcc的错误报告程序之前,我也会再次检查。 - Jonas Schäfer
5
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253 - Johannes Schaub - litb
显示剩余2条评论
1个回答

12

2
请注意,微软的Visual Studio 12(2013)也有同样的错误,我刚刚在https://connect.microsoft.com/VisualStudio/feedbackdetail/view/976911/braced-initializer-list-not-evaluated-left-to-right上报告了此问题。 - Oberon
这个问题将在MSVC 2015 Update 2中得到修复(https://blogs.msdn.microsoft.com/vcblog/2016/02/11/compiler-improvements-in-vs-2015-update-2/)。 - Ruslan Garipov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接