簡體   English   中英

折疊表達式與編譯遞歸

[英]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://godbolt.org/z/Zz9Ik9

你也可以在這里看到發生了什么: https : //cppinsights.io/

但最終 - 測量將揭示它是否會帶來性能提升。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM