2011-06-16 157 views
6

我有一個遞歸模板定義(我剛剛制定了這個術語)。我認爲代碼更好地解釋它。遞歸模板定義

template<typename X> 
class Domain 
{ 
    public: 
     X begin; 
     X end; 

     Domain(
      X _begin, 
      X _end) 
      : begin(_begin) 
      , end(_end) 
     { 
      // ... 
     } 

     bool Contains(
      const X& t) const 
     { 
      // ... 
     } 
}; 

template<typename X, typename Y> 
class IFunction 
{ 
    public: 
     Domain<X> myDomain; 

    public: 
     IFunction(
      const Domain<X>& dom) 
      : myDomain(dom) 
     { 

     } 

     virtual Y 
     Calc(
      const X& IV) const = 0; 

     virtual IFunction<X, Y>* 
     GetDerivative() const = 0; 
}; 

template<typename X, typename Y, int n> 
class NthOrderFunction 
    : public IFunction<X, Y> 
{ 
    public: 
     double coeffs[n+1]; 

    public: 
     NthOrderFunction(
      const Domain<X>& dom, 
      ...) 
      : IFunction(dom) 
     { 

     } 

     virtual Y 
     Calc(
      const X& IV) const 
     { 
      // temporary compile solution 
      return Y(); 
     } 

     virtual IFunction<X, Y>* 
     GetDerivative() const 
     { 
      if (n > 1) 
      { 
       return new NthOrderFunction<X, Y, n-1>(dom, ...); 
      } 
      return new FlatLine<X, Y>(dom); 
     } 
}; 

我拿出了很多繼承和其他關係來保持它的可讀性,簡單性和神祕性。因此,編輯代碼時可能會出現新的錯字,但請忽略它。該代碼已運行良好多年,唯一的問題是我要指出的一個。

我最近添加了一個「GetDerivative」函數,它在NthOrderFunction類中的實現給我帶來了問題。我知道模板類是在編譯之前但在預處理之後定義的。因此,我看不到如何使這個功能有效。每個具有模板參數n的NthOrderFunction都需要帶模板參數n-1的NthOrderFunction。你可以看到這是一個問題。問題是,儘管n永遠不會被使用爲負數,但是我不會做任何編碼,將會說服「模板定義引擎」不會打擾n的實例。

有沒有人有過這個問題?你有什麼解決方案?

+0

這到底是什麼B? – 2011-06-16 11:13:03

+0

對不起,一定是X,會編輯。 – Rene 2011-06-16 11:15:46

+1

你想使用模板元編程來處理多項式嗎?我認爲之前已經完成了:-) – 2011-06-16 11:22:02

回答

2

添加類似:

template<typename X, typename Y> 
class NthOrderFunction<X, Y, 1> 
    : public IFunction<X, Y> 
{ 
    public: 
     double coeffs[n+1]; 

    public: 
     NthOrderFunction(
      const Domain<X>& dom, 
      ...) 
      : IFunction(dom) 
     { 

     } 

     virtual Y 
     Calc(
      const X& IV) const 
     { 
      // temporary compile solution 
      return Y(); 
     } 

     virtual IFunction<X, Y>* 
     GetDerivative() const 
     { 
      return new FlatLine<X, Y>(dom); 
     } 
}; 

,並移除遞歸的情況下在n == 1例。

作爲一個建議,得到一些書或教程或模板metaprogramming。其中一種基本技術是以這種方式在模板中使用遞歸。這嚴格來說不是元編程,它只是遞歸模板。本書/教程將解釋如何使用更高級的技巧,在擴展時可以使用這些技巧。

這個原理的工作原理是,原始代碼仍然會將編譯時間「if」擴展到運行時代碼(這將永遠不會執行)。這段代碼取代了可以編譯出來的一種情況,因此沒有無限遞歸的選擇。

+0

thx!我讀了它,這似乎合乎邏輯。我會試一試。 – Rene 2011-06-16 11:54:35

7

這與模板元編程101示例因子相同,只是內容稍微複雜一些。

template<int N> struct factorial { enum { value = N * factorial<N-1>::value }; }; 

而且您需要相同的解決方案 - 基礎案例的專業化。

template<> struct factorial<1> { enum { value = 1 }; }; 

您的將是部分而不是完整的,但它仍然工作。

+0

thx求救! – Rene 2011-06-16 11:55:14