2016-02-09 79 views
1

模板重新聲明中的模板參數太多

:-)嗨

我有以下代碼:我們的目標是返回一個函數,其它函數的總和,大致。並瞭解可變參數模板。

#include <iostream> 

template <typename F> 
struct FSum { 
    FSum(F f) : f_(f) {} ; 
    int operator()() { 
     return f_() ; 
    } 
    F f_ ; 
} ; 
template <typename F1, typename F2, typename... Frest> 
struct FSum { 
    FSum(F1 f1, F2 f2, Frest... frest) { 
     f_ = f1 ; 
     frest_ = FSum<F2, Frest...>(f2, frest...) ; 
    } 
    int operator()() { 
     return f_() + frest_() ; 
    } 
    F1 f_ ; 
    FSum<F2, Frest...> frest_ ; 
} ; 

struct F1 { 
    int operator()() { return 1 ; } ; 
} ; 
struct F2 { 
    int operator()() { return 2 ; } ; 
} ; 
struct F3 { 
    int operator()() { return 3 ; } ; 
} ; 

int main() { 
    F1 f1 ; 
    F2 f2 ; 
    F3 f3 ; 
    FSum<F1, F2, F3> fsum = FSum<F1, F2, F3>(f1, f2, f3) ; 
    std::cout << fsum() << std::endl ; 
} 

,但我得到了以下錯誤消息從鐺(G ++也給出了一個錯誤):

test_variadic.cpp:14:1: error: too many template parameters in template redeclaration template ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

而且還有我不明白。我雖然編譯器會根據模板參數的數量選擇類。由於第一個具有一個,另一個具有兩個或更多個。

有什麼想法?

非常感謝:-)

回答

1

您不能有2種不同的模板參數。您試圖將類用作函數(可以在其中共享多個定義/名稱),但類和結構不以這種方式工作。您需要重命名這些結構中的一個或將它們合併爲一個結構。

+0

好的,這是有道理的,謝謝:-) – leo

2

編譯器抱怨是因爲你重新聲明瞭兩次相同的模板結構,而你需要的是部分模板專精。請參閱下面示例中的語法。

至於獲取可變參數模板做你想要的邏輯,它有助於從遞歸的角度來考慮它。下面的代碼做你想要的:

#include <iostream> 

using namespace std; 

// stops "recursion" when it is called with no parameters 
template <typename... Frest> struct FSum { 
    int operator()() { 
     return 0; 
    } 
}; 

// Partial Specialization of FSum above 
// called when there is at least one template parameter 
template <typename F, typename... Frest> 
struct FSum<F, Frest...> { 

    // "recursion" in the construction of frest_ 
    FSum(F f, Frest... frest) : f_(f), frest_(frest...) {} 

    // "recursion" in the calling of frest() 
    int operator()() { 
     return f_() + frest_(); 
    } 

    F f_; 
    FSum<Frest...> frest_; 
}; 


struct F1 { 
    int operator()() { return 1; } 
}; 

struct F2 { 
    int operator()() { return 2; } 
}; 

struct F3 { 
    int operator()() { return 3; } 
}; 

int main() { 
    F1 f1; 
    F2 f2; 
    F3 f3; 
    FSum<F1, F2, F3> fsum(f1, f2, f3); 
    cout << fsum() << endl; 
} 

請注意,我使用單詞「遞歸」,但據我所知,沒有遞歸。相反,在編譯時會產生一系列函數調用。

+0

只需要注意,也會有一個運行時嵌套的「遞歸」式調用堆棧,並支付定期運行時遞歸的所有成本!作爲回報f_()+ frest_(); frest_()將調用FSum operator()的嵌套調用,該調用將調用另一個FSum operator()的已分離版本等,直到它達到遞歸基礎。我不知道編譯器是否能夠將此調用堆棧推廣到操作符()評估的平坦序列。 – barney

+0

你對@barney。 「函數調用序列」的運行時間成本等於運行時遞歸。 –