2013-02-13 87 views
3

爲什麼不編譯此代碼?使用模板參數的靜態成員模板

struct A { 
    template <class T> 
    static T a(int i) { return 2*i; } 
}; 

template <class T> 
struct B { 
    double b; 
    B(): b(T::a<double>(5)) {} 
}; 

template class B<A>; 

編譯器甚至沒有達到模板實例化。我使用的是gcc 4.7.0。

test.cc: In constructor »B<T>::B()«: 
test.cc:9:25: Error: expected »(« before »<« token 
test.cc:9:26: Error: expected primary-expression before »double« 
+1

也許你可以提供編譯器的錯誤信息? – ronag 2013-02-13 14:03:29

+0

對不起,我忘了 – 2013-02-13 14:05:37

回答

6

你錯過了template關鍵字,因爲a是一個從屬名稱(或類似的東西)。

B(): b(T::template a<double>(5)) {} 

(此外,您的最後一行應該是template struct B<A>;。)

對於血淋淋的細節,請參見: Where and why do I have to put the "template" and "typename" keywords?

2

你有方法的名稱前把template

B(): b(T::template a<double>(5)) {} 

這是因爲當解析模板類B時,編譯器不會知道T::a是一種模板化方法(因爲T在此之前未指定,並且T::a完全未知),所以它不知道<double>應該被解析爲模板參數列表。

它也可能意味着並將確實解析爲:T::a小於double大於(0)。當然,double不是表達式,所以這失敗了;從而出現錯誤信息。所以編譯器可能只是假設你希望它是一個模板函數調用。但是你也可以有一個非類型的模板參數,比如說一個int,所以T::a<42>(5)可以被解析爲T::a小於42大於(5),這不是一個模板。但是您希望將其解析爲T::a,然後使用參數42作爲模板參數列表,然後使用參數5調用運算符。

要告訴編譯器它是一個模板函數調用,必須在函數名稱前加template

0

編譯器對T一無所知。因此,每當您編寫T::{something}時,都假定{something}是T的成員變量或方法。如果不是,則必須告訴它它是什麼。您可能知道關鍵字typename,如果您所指的是類型而不是變量,則必須使用該關鍵字。有一個類似的把戲模板成員:

template <class T> 
struct B { 
    double b; 
    B(): b(T::template a<double>(5)) {} 
}; 

現在編譯器知道a是一個模板和什麼來之後是模板參數列表。

相關問題