C++ 11初始化器列出了可变参数模板的参数:为什么这不起作用

Pau*_*aul 11 c++ templates variadic-templates c++11

将可变参数模板的参数包含在初始化程序列表中应该确保它们按顺序进行评估,但不会在此处进行:

#include <iostream>
using namespace std;


template<class T> void some_function(T var)
{
   cout << var << endl;
}

struct expand_aux {
    template<typename... Args> expand_aux(Args&&...) { }
};

template<typename... Args> inline void expand(Args&&... args) 
{
   bool b[] = {(some_function(std::forward<Args>(args)),true)...}; // This output is 42, "true", false and is correct
   cout << "other output" << endl;
   expand_aux  temp3 { (some_function(std::forward<Args>(args)),true)...  }; // This output isn't correct, it is false, "true", 42
}

int main()
{
   expand(42, "true", false);

   return 0;
}
Run Code Online (Sandbox Code Playgroud)

怎么会?

And*_*owl 13

这似乎是一个错误.输出应该是您期望的输出.

虽然是一个构造函数调用的参数评估的顺序没有保证一般,有表情的评价在支撑初始化列表中的顺序的保证.

根据C++ 11标准的第8.5.4/4段:

在braced-init-list的initializer-list中,initializer-clauses(包括pack扩展(14.5.3)产生的任何结果)按照它们出现的顺序进行评估.也就是说,与给定初始化子句相关联的每个值计算和副作用在每个值计算和副作用之前与在初始化列表的逗号分隔列表中跟随它之后的任何初始化子句相关联.[注意:无论初始化的语义如何,此评估顺序都保持不变; 例如,当initializer-list的元素被解释为构造函数调用的参数时,它适用,即使通常对调用的参数没有排序约束. - 尾注]

  • 似乎gcc只是将它的正常函数调用参数评估顺序应用于统一初始化调用,这是正常的构造函数调用.但是tbh,即使调用相同的构造函数,`Foo x {a,b};`和`Foo x(a,b);`也不一样. (3认同)