为什么不能推断出主要的返回类型?

时间:2016-08-23 16:53:11

标签: c++ c++14 return-type-deduction

正如预期的那样,C ++ 11中的以下内容失败,因为该语言没有针对沼泽标准函数的返回类型推导:

auto main()
{
   return 0;
}

但是,C ++ 14确实如此,所以我无法解释以下错误(在GCC trunk,clang 3.8和Visual Studio 2015中具有相同的结果):

error: 'main' must return 'int'

我没有看到标准中的段落,禁止main的退货类型扣除?或者两个编译器都不兼容?

(对于它的价值,我从来没有真正这样做。int main()获胜......)

4 个答案:

答案 0 :(得分:23)

阅读the C++17 draft§3.6.1/ 2:

  

...它应具有类型为int的声明的返回类型,...

所以是的我会说它被禁止使用扣除。

the last C++14 draft中几乎完全相同的措辞(与C ++ 17草案相同):

  

它的声明返回类型为int,...

在阅读评论和其他答案之后,只是对这背后的可能的推理的个人反思。 (我认为)不允许推理返回类型推导,因为编译器在查看return语句之前不知道返回类型。其他类型(可隐式转换为int)可能会被返回,这会导致推断类型错误。预先声明返回类型(通过正常的老式方式,或使用尾随返回类型)将在声明函数时设置类型,然后由编译器检查然后是正确的。

至于允许类型别名,它们只是一种类型的别名。所以允许例如

typedef int my_type;
my_type main() { ... }

无异
int main() { ... }

答案 1 :(得分:17)

从3.6.1 / 2(强调我的):

  

[...]它应具有类型为int声明的返回类型,但其类型是实现定义的。

当使用auto而没有尾随返回类型时,函数的声明的返回类型仍然是auto,即使推断的返回类型可以是其他东西。 声明推导之间的区别在标准中没有明确说明,但7.1.6.4/7可能会有所启发:

  

当使用包含占位符类型的返回类型声明的函数中发生return语句时,推导出的返回类型[...]由其初始值设定项的类型确定。如果return没有操作数或操作数类型为void,则声明的返回类型应为auto,推导的返回类型为void

我的理解是:

auto main(){ return 0; }

声明的返回类型仍然是auto,尽管推断的返回类型将是int。根据上面的3.6.1 / 2,main 声明的返回类型必须int。因此,这是不正确的。

但是,尾随返回类型被视为声明的返回类型。从7.1.6.4/2开始:

  

如果函数声明符包含 trailing-return-type (8.3.5),则 trailing-return-type 指定函数的声明返回类型。 / p>

$ cat a.cpp
auto main() -> int {}
$ g++ -Wall -std=c++14 a.cpp
$

C ++ 14和C ++ 17中的所有引号都相同。

答案 2 :(得分:8)

来自3.6.1 [basic.start.main]

  

1程序应包含一个名为main的全局函数,即   指定的程序开始....
2实施不得   预定义主要功能。此功能不应过载。它   应该具有int类型的声明返回类型,否则它的类型   是实现定义的......

如果标准是限制扣除,那么我认为“声明返回类型为int”的措辞就是它。

答案 3 :(得分:3)

正如在各种评论中所讨论的那样,我确实在标准中忽略了它,因为我认为是C ++ 14 FDIS的副本实际上没有这样的东西(但是,相反,是一个稍微更旧的草案),以及声明"宣布"在CWG 1669之后偷偷溜进了相关的段落。