2012-11-06 60 views
4

考慮:爲什麼我無法從void函數模板返回編譯器錯誤?

void f() { 
    return 5; 
} 

以上將引發錯誤。但爲什麼不是這樣?:

template <typename = void> void f() { 
    return 0; 
} 

我在用gcc-4.5.1編譯。爲什麼它使用模板有所作爲,使得我不會因爲執行與非模板函數相同的非法返回語句而收到錯誤?我得到的唯一挫折是我不能調用函數(即f())沒有得到:

error: return-statement with a value, in function returning 'void'

但儘管如此,這可能是我能夠定義一個return語句爲void函數模板的原因?

這裏是我的代碼:

template <typename = void> void f() { 
    return 0; 
} 

// pass 

int main() { 



} 

上面的代碼會通過,儘管在一個功能想必非法return語句返回void。

+0

如果您提供實際的測試用例,您將獲得+1。我們不得不猜測你在做什麼,也沒有在模板f()中做什麼。 –

+0

@LightnessRacesinOrbit我更新了。 – 0x499602D2

+0

這就是您按預期得到錯誤的代碼。那麼當你不希望這個問題的焦點時,你怎麼樣呢? –

回答

6

這是實施質量問題。從標準的具體報價爲:

14.6/8 [...] If no valid specialization can be generated for a template definition, and that template is not instantiated, the template definition is ill-formed, no diagnostic required. [...]

也就是說,生病形成你的程序,因爲模板不能用來產生任何有效專業化,但不是必需的編譯器來診斷這一點。當稍後您實例化模板時,編譯器必須生成專門化,專業化無效且編譯器投訴。

由於編譯器在之後沒有要求診斷路徑,所以在模板定義中沒有出現錯誤,即忽略該問題,直到它在實例化中不再忽略它爲止。

+0

我會解釋引用的意思是說,如果該模板對任何可能的類型都是無效的,那麼該模板是不合格的,而不是單個無效類型使其不合格。 –

+0

@MarkB:我完全是這樣解釋引用的:如果模板對於任何可能的類型都是無效的,那麼該模板是不合格的。這是在這個問題的情況:'template '** void **'f(){return 0; }' - >無論'T'類型如何,函數都會返回'void'並且有一個'return 0;' –

+0

讓我直截了當。這是否意味着即使我沒有實例化模板,編譯器*也會產生錯誤? –

10

大多數檢查只在您實例化模板時完成。

這通常是一件好事,因爲代碼可以在一種模板參數下正常工作,但無法與另一種模板參數一起編譯。如果您有模板重載,編譯器甚至會忽略無法編譯的候選對象,請參閱SFINAE

+0

True,http://ideone.com/ZLiQNY – Kos

+0

@Kos'template void f()'做了什麼? – 0x499602D2

+0

@David:以首次讀者不完全清楚的方式導致實例化! –

7

You do

template <typename = void> void f() { 
    return 0; 
} 

int main() 
{ 
    f<int>(); 
} 

prog.cpp: In function 'void f() [with = int]':
prog.cpp:7:12: instantiated from here
prog.cpp:2:12: error: return-statement with a value, in function returning 'void'

儘管程序仍然是形成不良,編譯器選擇不診斷語義錯誤(這是它的特權),因爲你從來沒有真正實例該功能。

+0

謝謝。這有幫助! – 0x499602D2

+0

@大衛:不客氣。 :) –

+0

模板是否被使用並不重要,即使沒有實例化,該程序也是不合格的,但編譯器不需要診斷它。 –

相關問題