2011-03-15 82 views
8

假設你的代碼「無效的模板參數」錯誤,但不是GCC

template <template<class> class BaseType> 
class EST16 
    : public BaseType<int> 
{ 
public: 
    EST16(double d) 
    { 
    } 
}; 

template <class T> 
class SCEST 
{ 
    T y; 
}; 
typedef EST16<SCEST> EST16_SC; 
class Child 
    : public EST16_SC 
{ 
public: 
    Child() 
     : EST16_SC(1.0) 
    { 
    } 

}; 



class NotWorkingChild 
    : public EST16<SCEST> 
{ 
public: 
    NotWorkingChild() 
     : EST16<SCEST>(1.0) 
    { 
    } 

}; 



TEST(TemplateTest, TestInstantiate) 
{ 
    Child child; 
    NotWorkingChild notWorkingChild; 
} 

兒童和NotWorkingChild只有typedef的不同。在GCC編譯兩種,在Visual Studio NotWorkingChild的構造產生以下錯誤:

2>..\..\..\src\itenav\test\SCKFErrorStateTest.cpp(43) : error C3200: 'SCEST<T>' : invalid template argument for template parameter 'BaseType', expected a class template 
2>  with 
2>  [ 
2>   T=int 
2>  ] 

你能解釋一下爲什麼是這樣的情況?有沒有比typedef更好的便攜式解決方案?

謝謝!

+1

你有沒有寫過任何實際實例化和使用模板類的代碼?我的意思是說,「主」。可能發生的一件事情是,VCC在看到'typedef'時測試實例化,而GCC在實際使用其中一個子類之前不會感到煩惱。如果那是真的,那麼只要你真正編寫使用其中一個子類模板的代碼,你也會在GCC中得到錯誤。 – phooji 2011-03-15 17:09:13

+0

是的,我做到了。 TEST宏創建一個實際從main()調用的Google測試。 – Philipp 2011-03-15 17:25:50

+0

對不起 - 'TEST'宏是在我滾動截斷之後,所以我錯過了它。我不是100%爲什麼會失敗,但是我已經發布了一個替代方法,它應該在編譯器中更具可移植性。這也是更可讀,在我的愚蠢觀點:) – phooji 2011-03-15 17:39:16

回答

11

該錯誤消息是因爲從SCEST<int>NotWorkingChild導出(間接地),這使得內部SCESTNotWorkingChild範圍指代替模板到類SCEST<int>,。 MSVC拒絕這個是正確的,GCC4.5也應該拒絕這個(GCC4.5有更正確的注入類名稱查找)。

這裏是一個可能的兩種編譯器

class NotWorkingChild 
    : public EST16<SCEST> 
{ 
public: 
    NotWorkingChild() 
     : EST16<::SCEST>(1.0) 
    { 
    } 

}; 

注意,我們使用範圍解析操作,需要把一個空間::(令牌<:否則會被視爲一個有向圖)前工作的解決方案。


最新新聞:C++ 0x中將會使即使你EST16<SCEST>上述工作。原因是,它表示如果將注入的類名稱傳遞給模板模板參數,則將注入的類名稱視爲模板,而不是視爲類型。因此,對於C++ 0x,GCC是編譯器正確執行的。

+0

似乎VS「14」CTP仍然需要範圍解析運算符。 – 2014-11-29 18:37:02

2

它在VS上進行編譯,如果您更改初始值以僅引用模板類名稱EST16。即:

class NotWorkingChild : public EST16<SCEST> 
{ 
public: 
    NotWorkingChild() 
     : EST16(1.0) 
    { 
    } 
}; 
+1

這是正確的,但我正在尋找一個便攜式的解決方案,這不會與GCC編譯:-( – Philipp 2011-03-15 18:42:21