[英]Fold expression vs compile recursion
In c++17
we have fold expression which can greatly simplify code that could otherwise be implemented using compiler-recursion and SFINAE or overloading.在
c++17
我们有折叠表达式,它可以大大简化可以使用编译器递归和 SFINAE 或重载实现的代码。 For example, in the following code例如,在下面的代码中
#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;
}
the c++17
function printer
(taken from cpp reference ) does exactly the same job as its c++11
version printer_cpp11
. c++17
函数printer
(取自cpp 参考)与它的c++11
版本printer_cpp11
执行完全相同的工作。
At compile-time, several overloads of the function printer_cpp11
are generated, whereas a single function printer
is needed using fold expression.在编译时,会生成函数
printer_cpp11
多个重载,而使用 fold 表达式需要单个函数printer
。
Is there an advantage in terms of performance in using fold expressions over the c++11
-style?与
c++11
风格相比,使用折叠表达式在性能方面有优势吗? Or can one assume that the compiler inlines all the overloads of printer_cpp11
, creating code with equivalent performance?或者可以假设编译器内联了
printer_cpp11
所有重载,从而创建了具有等效性能的代码?
Both versions would lead to the same codegen due to inlining, so run-time performance is exactly the same: https://gcc.godbolt.org/z/VIHTvZ (code cleaned of streams clutter).由于内联,两个版本都会导致相同的代码生成,因此运行时性能完全相同: https : //gcc.godbolt.org/z/VIHTvZ (清除流混乱的代码)。
However, compilation times and memory usage are expected to be way better with fold expressions than with recursive instantiations, and because of that, fold expression are generally preferred.然而,折叠表达式的编译时间和内存使用预计比递归实例化要好得多,因此,折叠表达式通常是首选。 Not to mention they are also provide for cleaner and easier to reason about code.
更不用说它们还提供了更清晰、更易于推理的代码。
Just to add to @SergeyA's answer you can alleviate the need for the recursion and the empty function in the c++11 version by doing something like...只是为了添加到@SergeyA 的答案中,您可以通过执行以下操作来减轻对递归和 c++11 版本中的空函数的需求...
template <typename ...Args>
void printer_cpp11_norecursion( Args&&... args)
{
using do_ = int[];
do_{0,
(std::cout << args,0)...
};
}
Which should generate the same results as both of the other versions ( https://gcc.godbolt.org/z/hyAyiz ) with possibly better compile times on c++11.这应该产生与其他两个版本( https://gcc.godbolt.org/z/hyAyiz )相同的结果,在 c++11 上编译时间可能更好。
The compiler will create a new instance of printer for each call with different arguments and in the function will unfold the operator<< calls:编译器将为每个具有不同参数的调用创建一个新的打印机实例,并在函数中展开operator<<调用:
https://godbolt.org/z/Zz9Ik9 https://godbolt.org/z/Zz9Ik9
You can also see what happens here: https://cppinsights.io/你也可以在这里看到发生了什么: https : //cppinsights.io/
But ultimately - measuring will reveal if it leads to a performance gain.但最终 - 测量将揭示它是否会带来性能提升。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.