4

考虑:

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 的函数中可能存在非法的 return 语句,上述代码仍将通过。

4

3 回答 3

10

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

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

于 2012-11-06T17:03:26.750 回答
7

这样做

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:错误:带有值的返回语句,在函数返回'空白'

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

于 2012-11-06T17:04:13.933 回答
6

这是实施质量问题。标准中的特定报价是:

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

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

您不会在模板定义中遇到错误,因为编译器遵循不需要诊断的路径,即忽略问题,直到它在实例化中不再忽略它。

于 2012-11-06T17:55:06.203 回答