为什么不从void函数模板返回编译器错误?

时间:2012-11-06 17:01:53

标签: c++ templates

考虑:

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'

但是,为什么我可以为void函数模板定义一个return语句呢?

这是我的代码:

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

// pass

int main() {



}

尽管在返回void的函数中有一个非法的返回语句,但上面的代码仍将通过。

3 个答案:

答案 0 :(得分:10)

大多数检查仅在您实例化模板时完成。

这通常是一件好事,因为代码可以使用一种模板参数正常工作但无法使用另一种模板参数进行编译。如果您有模板重载,编译器甚至会忽略无法编译的候选者,请参阅SFINAE

答案 1 :(得分:7)

You do

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

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

prog.cpp:在函数'void f()[with = int]'中:
  prog.cpp:7:12:从这里实例化   prog.cpp:2:12:错误:带有值的return语句,函数返回'void'

虽然程序仍然是格式错误,但编译器选择不诊断语义错误(这是它的特权),因为你实际上从未实例化该函数。

答案 2 :(得分:6)

这是一个实施质量问题。标准的特别引用是:

  

14.6 / 8 [...]如果无法为模板定义生成有效的专业化,并且未实例化该模板,则模板定义格式错误,无需诊断。 [...]

也就是说,您的程序生成错误,因为该模板不能用于生成任何有效的特化,但编译器不需要诊断它。当您稍后实例化模板时,编译器必须生成特化,专业化无效并且编译器会抱怨。

您不会在模板定义中出现错误,因为编译器正在遵循无需诊断路径,即忽略该问题,直到它在实例化中不再忽略它为止。< / p>

相关问题