VS2015编译器反转参数包扩展。
我有以下代码:
NSLog
当我在XCode(clang-700.1.81)中运行此代码时,我得到了这个结果:
#include <iostream>
#include <vector>
template <typename... T>
void f_Swallow(T &&...)
{
}
template <typename... T>
std::vector<int> f(T ...arg)
{
std::vector<int> result;
f_Swallow
(
[&]()
{
result.push_back(arg);
return true;
}
()...
) ;
return result;
}
using namespace std;
int main()
{
auto vec = f(1,2,3,4);
for (size_t i = 0; i < vec.size(); ++i)
cout << vec[i] << endl;
}
但VS2015中运行的相同代码会产生此输出:
1
2
3
4
为什么参数包根据编译器的不同而不同地扩展?有没有办法在不检查平台和编译器版本的情况下修复它? 标准不保证扩展订单的任何内容吗?
答案 0 :(得分:46)
不是参数包扩展的顺序不同,它是函数参数评估的顺序。
f_Swallow
(
[&]()
{
result.push_back(arg);
return true;
}
()...
) ;
为简洁起见,我们只需将该lambda命名为funcN
,其中N
为参数编号。给定四个参数,参数包将由任何符合标准的编译器扩展为:
f_Swallow(func1(), func2(), func3, func4()) ;
在C ++中未指定函数参数的评估顺序。编译器可以按顺序(如您的Clang版本),以相反的顺序(如您的MSVC版本)或按照其喜欢的任何顺序对它们进行评估。您不能指望评估订单。
要获得所需内容,可以将表达式放入指定评估顺序的上下文中。例如:
template <typename... T>
std::vector<int> f(T ...arg)
{
std::vector<int> result;
(void)std::initializer_list<int> { (result.push_back(arg), 0)... };
return result;
}
在C ++ 17中,您将能够使用fold expressions执行以下操作:
template <typename... T>
std::vector<int> f(T ...arg)
{
std::vector<int> result;
(result.push_back(arg), ...);
return result;
}
答案 1 :(得分:11)
我认为它也可以这样写:
template <typename... T>
std::vector<int> f(T ...arg)
{
std::vector<int> result{ arg... };
return result;
}
无需创建虚拟std :: initializer_list