[英]Fold expression vs compile recursion
在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
多個重載,而使用 fold 表達式需要單個函數printer
。
與c++11
風格相比,使用折疊表達式在性能方面有優勢嗎? 或者可以假設編譯器內聯了printer_cpp11
所有重載,從而創建了具有等效性能的代碼?
由於內聯,兩個版本都會導致相同的代碼生成,因此運行時性能完全相同: https : //gcc.godbolt.org/z/VIHTvZ (清除流混亂的代碼)。
然而,折疊表達式的編譯時間和內存使用預計比遞歸實例化要好得多,因此,折疊表達式通常是首選。 更不用說它們還提供了更清晰、更易於推理的代碼。
只是為了添加到@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 上編譯時間可能更好。
編譯器將為每個具有不同參數的調用創建一個新的打印機實例,並在函數中展開operator<<調用:
你也可以在這里看到發生了什么: https : //cppinsights.io/
但最終 - 測量將揭示它是否會帶來性能提升。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.