gpt4 book ai didi

c++ - 为什么参数包扩展在不同的 C++ 编译器中的工作方式不同?

转载 作者:IT老高 更新时间:2023-10-28 12:30:57 35 4
gpt4 key购买 nike

参数包扩展被 VS2015 编译器反转。

我有以下代码:

#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;
}

当我在 XCode (clang-700.1.81) 中运行此代码时,我得到以下结果:

1
2
3
4

但在 VS2015 中运行的相同代码会产生以下输出:

4
3
2
1

为什么参数包的扩展因编译器而异?有没有办法在不检查平台和编译器版本的情况下修复它?标准对扩展顺序没有任何保证吗?

最佳答案

不是参数包展开顺序不同,而是函数参数求值顺序不同。

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;
}

关于c++ - 为什么参数包扩展在不同的 C++ 编译器中的工作方式不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35702180/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com