加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 使用带有可变参数函数模板的参数的std :: algorithms的大多

发布时间:2020-12-16 10:09:04 所属栏目:百科 来源:网络整理
导读:假设你有一个可变参数函数模板,它接受一个仿函数和一系列齐次类型,并且你想使用std :: accumulate来折叠序列,如下所示: templatetypename BinaryFuncType,typename... ArgTypesdo_something(const BinaryFuncType f,const ArgTypes... objects){ // ... //
假设你有一个可变参数函数模板,它接受一个仿函数和一系列齐次类型,并且你想使用std :: accumulate来折叠序列,如下所示:

template<typename BinaryFuncType,typename... ArgTypes>
do_something(const BinaryFuncType& f,const ArgTypes&... objects)
{
    // ...
    // use std::accumulate to fold 'objects' using 'f'
    // ...
}

是否可以直接将可变参数(对象)传递给范围算法(std :: accumulate),即不会产生将对象(或引用)复制到可迭代容器的成本?

解决方法

显然是的,但是以扭曲的方式.请考虑以下代码:

#include <algorithm>
#include <array>
#include <cstdio>
#include <iterator>

template<typename... Ts>
int sum(Ts... numbers) {
    std::array<int,sizeof...(numbers)> list{{numbers...}};
    return std::accumulate(std::begin(list),std::end(list),0);
}

__attribute__((noinline))
void f(int x,int y,int z) {
  std::printf("sum = %dn",sum(x,y,z));
}

int main(int argc,char* argv[]) {
  int x = std::atoi(argv[1]);
  int y = std::atoi(argv[2]);
  int z = std::atoi(argv[3]);    
  f(x,z);
}

我查看了生成的汇编代码.这是sum()被clang优化的内容,为了清楚起见,我将汇编代码重写为C:

int sum(int x,int z) {
  int tmp = x;
  tmp += y;
  tmp += z;
  return tmp;
}

我可以说生成的汇编代码是最优的!它摆脱了临时的std :: array并在std :: accumulate()中展开了循环.

所以你的问题的答案是:即使你创建了一个临时的可迭代容器,如果编译器足够智能并且你的数字类型足够简单(内置类型或POD),它也可以被优化掉.如果可以优化,则不会为创建临时容器或将元素复制到临时容器中付费.

可悲的是,gcc 4.7.2并不那么灵巧:

int sum(int x,int z) {
  int a[3];
  a[0] = x;
  a[1] = y;
  a[2] = z;
  int tmp = x;
  tmp += y;
  tmp += z;
  return tmp;
}

不幸的是,它没有意识到它可以摆脱临时阵列.我将使用来自trunk的最新gcc进行检查,如果问题仍然存在,请提交错误报告;它似乎是优化器中的一个错误.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读