2011-12-18 164 views
1

關於模板實例化和繼承,我一直面臨着一個很大的挑戰(至少對我而言)。讓我們來看看下面的代碼:C++模板挑戰

class Convertible 
{ 
    public: 

    template<class T> 
    T* AsPtrTo() 
    { 
     return reinterpret_cast<T*>(this); 
    } 
}; 

template<class T> 
class TemplateBase : public Convertible 
{ 
}; 

template<class T> 
class TemplateDerived : public TemplateBase<T> 
{ 
    public: 

    void Method1(TemplateBase<T> t) 
    { 
     t.AsPtrTo<int>(); // <<<<<< ERROR 
    } 
}; 


int main() 
{ 
    TemplateDerived<int> d; 
    TemplateBase<int> b; 
    d.Method1(b); 

    return 0; 
} 

正如你所看到的,還有一類,稱爲轉換,與執行一個類型轉換隻是一個模板方法。還有一個從Convertible繼承的模板類,然後是從前一個繼承的另一個模板類。最後一個模板類實現了一個方法,該方法使用模板方法AsPtrTo,該方法在編譯期間應該從Convertible繼承,並在編譯期間用於主函數中的類型T.

由於某種原因,我不明白,這失敗了。 GCC 4.4.1給我這個消息:

error: expected primary-expression before 'int'

我已經標記了錯誤的行。

我想也許這裏的一位C++專家可以幫我一把。

謝謝大家提前!

+0

「'return reinterpret_cast (this)''你不是那麼做,是嗎? – curiousguy 2011-12-19 05:49:14

回答

6

您需要使用關鍵字template爲:

t.template AsPtrTo<int>(); 

這已被討論過很多次,你會發現在SO帖子不計其數的。

但在這裏,你會找到最好的解釋之一:

+1

感謝您的回答,我搜索了與此相關的帖子,但找不到任何內容:(當然,我使用了錯誤的關鍵字。問題現在已經清楚了,再次感謝。 – Thund 2011-12-18 15:32:24

4

嘗試:

void Method1(TemplateBase<T> t) 
{ 
    t.template AsPtrTo<int>(); 
} 

的原因是,編譯器不知道是什麼的成員函數t具有解析時間,所以它不知道AsPtrTo是否是模板函數。正因爲如此,沒有提示就無法正確解析它。

至於爲什麼這是需要一個例子,考慮下面的代碼:

struct Foo 
{ 
    template<int N> int foo(int x) { return x + N; } 
}; 

struct Bar 
{ 
    int foo; 
}; 

template <typename T> 
int baz(T t) 
{ 
    return t.foo<0>(1); 
} 

一目瞭然,它看起來像baz<Foo>將工作,但baz<Bar>不會,但它是倒過來!

考慮一下,如果我叫baz<Bar>

return t.foo<0>(1);

foo是一個成員變量,所以當它看到它認爲它的<會發生什麼小於操作,所以它解析像這樣的表達:

return (t.foo < 0) > (1);

這是一個有效的表達式(一些隱式轉換到/從後)!

問題是,它會對FooBar這兩個表達式進行解析,這就是爲什麼需要template關鍵字的原因。編譯器必須假定它不是模板成員函數(除非你把那個關鍵字放在那裏)。