2012-11-06 48 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

模板是否被使用并不重要,即使没有实例化,该程序也是不合格的,但编译器不需要诊断它。 –

相关问题