簡體   English   中英

模板作為遞歸函數

[英]template work as recursive function

我找到了這段代碼,想知道我是否應該在我的真實項目中真正實現這樣的功能。

讓我困惑的是

  1. 這將花費更多的編譯時間,但是我不應該為運行時間而花時間去擔心編譯時間。

  2. 如果N真的很大,那該怎么辦呢? 源代碼中是否有文件大小限制?

還是不知道要實施的好東西?

#include <iostream>
using namespace std;

template<int N>
class Factorial {
public:
    static const int value = N * Factorial<N-1>::value;
};
template <>
class Factorial<1> {
public:
    static const int value = 1;
};

int main() {
  Factorial<5L> f;
  cout << "5! = " << f.value << endl;

    }

輸出:

5! = 120

在我處理代碼時,有問題的輕微修改發現

  Factorial<12> f1;  // works  
  Factorial<13> f2;  // doesn't work

錯誤:

undefined reference to `Factorial<13>::value'

像這樣,能不能再上升到12深度嗎?

1的答案是,它取決於模板元編程,本質上涉及在編譯時進行計算之間的權衡,其好處是不必在運行時進行計算。 通常,此技術可能導致難以閱讀和維護代碼。 因此,答案最終取決於您是否需要在較慢的編譯器時間和更難維護的代碼上實現更快的運行時性能。

想要速度嗎? 使用constexpr元編程! 解釋了如何在現代C ++中多次使用constexpr函數來代替模板元編程。 通常,這會導致代碼更具可讀性,甚至可能更快。 將此模板元編程方法與constexpr示例進行比較:

constexpr int factorial( int n )
{
   return ( n == 0 ? 1 : n*factorial(n-1) ) ;
}

它更加簡潔,易讀,並且將在編譯時針對常量表達式的參數執行該操作,盡管正如鏈接的答案所解釋的,該標准實際上並沒有說必須這樣做,但實際上,當前的實現確實可以做到。

還值得注意的是,由於結果將很快溢出value ,因此constexpr的另一個優點是未定義的行為不是有效的常量表達式,並且對於大多數情況,至少gccclang的當前實現至少會將constexpr中的未定義行為轉變為錯誤。案件。 例如:

constexpr int n = factorial(13) ;

對我來說會產生以下錯誤:

error: constexpr variable 'n' must be initialized by a constant expression
constexpr int n = factorial(13) ;
              ^   ~~~~~~~~~~~~~
note: value 6227020800 is outside the range of representable values of type 'int'
return ( n == 0 ? 1 : n*factorial(n-1) ) ;
                       ^

這也是您舉例說明的原因:

Factorial<13> f2;

失敗,因為需要一個常量表達式並且gcc 4.9給出了一個有用的錯誤:

error: overflow in constant expression [-fpermissive]
 static const int value = N * Factorial<N-1>::value;
                  ^

盡管較舊的gcc版本會給您帶來比您看到的有用的錯誤更少的信息。

對於問題2 ,編譯器具有模板遞歸限制,通常可以對其進行配置,但最終您將耗盡系統資源。 例如, gcc的標志為-ftemplate-depth = n

將模板類的最大實例化深度設置為n。 模板實例化深度需要一個限制,以檢測模板類實例化期間的無窮遞歸。 符合ANSI / ISO C ++的程序不得依賴大於17的最大深度(在C ++ 11中更改為1024)。 默認值為900,因為在某些情況下編譯器在達到1024之前可能會耗盡堆棧空間。

就像在您的特定問題中一樣,您將需要擔心有符號整數溢出,這是在系統資源出現問題之前未定義的行為。

暫無
暫無

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

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