2

我们c++17有折叠表达式,它可以极大地简化可以使用编译器递归和 SFINAE 或重载来实现的代码。例如,在下面的代码中

#include <iostream>
#include <utility>

template<typename ...Args>
void printer(Args&&... args) {
  (std::cout << ... << args) << '\n';
}

void printer_cpp11() { }

template <typename First, typename ...Args>
void printer_cpp11(First&& first, Args&&... args)
{
  std::cout << first;
  printer_cpp11(std::forward<Args>(args)...);
}

int main()
{
  printer(3, 4, "hello");

  std::cout << std::endl;

  printer_cpp11(3, 4, "hello");

  return 0;
}

c++17函数printer(取自cpp 参考c++11)的工作与其版本完全相同printer_cpp11

在编译时,会生成函数的几个重载,而使用折叠表达式需要printer_cpp11一个函数。printer

c++11在使用 fold 表达式而不是-style时在性能方面有优势吗?或者可以假设编译器内联 的所有重载printer_cpp11,从而创建具有同等性能的代码?

4

3 回答 3

1

只是为了添加到@SergeyA的答案,您可以通过执行类似...的操作来减轻c++11版本中对递归和空函数的需求。

template <typename ...Args>
void printer_cpp11_norecursion( Args&&... args)
{
  using do_ = int[];
  do_{0,
    (std::cout << args,0)...
  };
}

这应该生成与其他两个版本( https://gcc.godbolt.org/z/hyAyiz )相同的结果,在 c++11 上编译时间可能更好。

于 2019-04-16T21:45:56.997 回答
1

由于内联,两个版本都将导致相同的代码生成,因此运行时性能完全相同:https ://gcc.godbolt.org/z/VIHTvZ (代码已清除流杂乱)。

然而,折叠表达式的编译时间和内存使用预计比递归实例好得多,因此,折叠表达式通常是首选。更不用说它们还提供了更清晰、更容易推理的代码。

于 2019-04-16T14:26:53.513 回答
0

编译器将为每个具有不同参数的调用创建一个新的打印机实例,并且在函数中将展开operator<<调用:

https://godbolt.org/z/Zz9Ik9

您还可以在这里查看发生了什么:https ://cppinsights.io/

但最终 - 测量将揭示它是否会导致性能提升。

于 2019-04-16T10:27:19.770 回答