在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
-style相比,使用折叠表达式在性能上是否有优势?或者可以假设编译器插入了printer_cpp11
的所有重载,从而创建了具有同等性能的代码?
发布于 2019-04-16 06:26:53
由于内联,这两个版本都会产生相同的代码,因此运行时性能完全相同:https://gcc.godbolt.org/z/VIHTvZ (清理流杂乱的代码)。
然而,编译时间和内存使用预计要比递归实例化要好得多,因此,折叠表达式通常是首选的。更不用说,它们还提供了更清晰、更易于推理的代码。
发布于 2019-04-16 13:45:56
只需添加到@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-16 02:27:19
编译器将为每个具有不同参数的调用创建一个新的打印机实例,并在该函数中展开operator<<调用:
您还可以看到这里发生了什么:https://cppinsights.io/
但是最终--测量将揭示它是否会带来性能的提高。
https://stackoverflow.com/questions/55705215
复制相似问题