【问题标题】:Why don't I get compiler errors from returning from a void function template?为什么从 void 函数模板返回时不会出现编译器错误?
【发布时间】:2012-11-06 17:01:52
【问题描述】:

考虑:

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 语句,上述代码仍会通过。

【问题讨论】:

  • 如果您提供实际测试用例,您将获得 +1。我们不得不猜测您在使用模板 f() 做什么和不做什么。
  • @LightnessRacesinOrbit 我更新了。
  • 这是您按预期收到错误的代码。当您不,如未预期,即问题的焦点时,怎么样?

标签: c++ templates


【解决方案1】:

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

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

【讨论】:

  • @Kos template void f() 做什么?
  • @David:导致实例化的方式对于第一次阅读的人来说并不完全清楚!
  • Instantiates the template,就是这样:)
  • 这个答案有点误导:即使模板从未实例化,程序也是格式错误的。大多数编译器在标准中使用 no diagnostic required 注释并忽略该问题的事实是一个完全不同的问题。特别是,在模板实例化之前忽略此错误没有任何价值:一旦看到定义,编译器就可以退出并避免额外的处理成本。
  • @DavidRodríguez-dribeas 程序何时格式错误?类似“如果 arbitrary 模板参数无法实例化模板,则程序格式错误”?
【解决方案2】:

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: error: return-statement with a value, in function return 'void'

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

【讨论】:

  • 是否使用模板无关紧要,即使没有实例化,程序也是格式错误的,但不需要编译器进行诊断。
  • @DavidRodríguez-dribeas: I'm not sure about that.
  • @LightnessRacesinOrbit:我已经在答案中发布了标准 14.6/8 的报价。
【解决方案3】:

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

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

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

您不会在模板定义中收到错误,因为编译器遵循 no diagnostic required 路径,即忽略该问题,直到它在实例化中无法再忽略它。

【讨论】:

  • 我会把这句话解释为如果模板对任何可能的类型都无效,那么模板就是格式错误的,而不是单个无效类型使其格式错误。跨度>
  • @MarkB:我将引用解释为:如果模板对任何可能的类型都无效,则模板格式错误。问题中就是这种情况:template &lt;typename T&gt; void f() { return 0; } --> 无论T 的类型如何,函数都会返回void 并且有一个return 0;
  • 让我直说。这是否意味着即使我不实例化模板,编译器也可以生成错误?
  • @KarolyHorvath:是的,这意味着程序不正确,编译器可以拒绝该程序。允许不诊断问题,但代码不正确。
  • 所以我有两个编译器,都符合标准,一个编译它而另一个可以拒绝它? c++标准的****总是让我惊叹。
猜你喜欢
  • 1970-01-01
  • 2010-12-09
  • 1970-01-01
  • 1970-01-01
  • 2019-03-12
  • 2014-06-08
  • 2014-09-28
相关资源
最近更新 更多