2014-07-23 97 views
5

下面的代碼編譯在Visual C++ 2013但不G ++ 4.8.2下:處理的非實例模板函數

template<class T> 
int MyFunc(T& t) 
{ 
    return static_cast<int>(CCodes::blah); 
} 

template<> 
int MyFunc(float& t) 
{ 
    return 0; 
} 

int main() { 
    float f = 10.f; 
    return MyFunc(f); 
} 

的Visual C++似乎忽略一般模板函數,因爲僅專業化MyFunc<float>被使用。無論如何,G ++解析了一般函數,並指出CCodes枚舉尚未定義。

這是對的嗎?或者是這個實現定義的?

+0

無論哪種方式,格式錯誤的代碼仍然是格式錯誤的代碼。 –

+0

所以我想我的問題可以重寫:這是畸形的代碼?或者,編譯器是否允許不解析未經實例化的模板定義? – Tom

+0

@Tom如果你寫'return static_cast (CCodes :: blah);'?會發生什麼? –

回答

6

GCC是正確的,除了MSVC以外的其他編譯器都會做同樣的事情。

這是一個主要的錯誤,它實際上出現在一個MSVC未來的路線圖上。它處於「遙遠的未來」範疇。他們將不得不重寫他們的模板引擎來修復它。

有一條論據說診斷不合格模板是可選的,因爲它實際上是一個沒有格式化實例化的模板,並且這些模板不需要被標記。但是,

  1. 該標準要求模板進行分析,並且無論是否實例化都必須診斷失敗。
  2. 每個其他編譯器都會進行診斷,所以實際上不這樣做會導致MSVC用戶生成不可移植的代碼。抱怨是一個非常好的主意,即使它不是必需的。
+0

嗯,§14.6[temp.res]/p10說:「如果名稱不依賴於模板參數(如14.6.2中定義),則該名稱的聲明(或聲明集)應在名稱出現在模板定義中的點「。與一般的「無效專業化」規則不同,沒有「不需要診斷」。 –

+0

@ T.C。對。由於C++是一種上下文相關(非上下文無關)語法,因此名稱查找需要作爲解析的一部分來執行。這是我的意思(1)的一部分。 – Potatoswatter

+0

事實上,情況比這更糟糕 - 你可以從字面上把幾乎任何垃圾都放在一個沒有實際意義的模板函數中,而VC++編譯器會忽略它。只要它不包含大括號,並且不會影響預處理器,看起來並不重要。 – Tom