为什么不能推导出main的返回类型? [重复]

问题描述 投票:0回答:5

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

auto main()
{
   return 0;
}

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

error: 'main' must return 'int'

标准中是否有一段我没有看到的内容,禁止

main
的返回类型扣除?或者两个编译器都不兼容?

(无论它的价值,我从来没有真正这样做过。

int main()
为了胜利......)

c++ c++14 return-type-deduction
5个回答
24
投票

阅读 C++17 草案 §3.6.1/2:

...并且它应具有

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

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


与最后一个 C++14 草案中的措辞几乎完全相同(与 C++17 草案相同的部分):

它应该有一个声明的返回类型,类型为

int

,...

在阅读评论和其他答案后,
只是对这背后的“可能”推理的个人反思。推理返回类型推导是不允许的(我认为),因为编译器在看到

return 语句之前并不知道返回类型。可能会返回其他类型(可隐式转换为 int

),这也会导致推导的类型错误,这种情况也并不罕见。预先声明返回类型(通过正常的老式方式,或使用尾随返回类型)将在声明函数时设置类型,并且可以由编译器立即检查是否正确。
至于允许类型别名,它们只是类型的别名。所以允许例如

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

真的没有什么不同

int main() { ... }

从3.6.1/2(强调我的):

17
投票

[...]它应具有

int
类型的

声明的返回类型,但除此之外,其类型是实现定义的。


当使用

auto
而没有尾随返回类型时,函数的

声明的返回类型

仍然是 
auto,即使推导的返回类型
可以是其他类型。标准中没有明确说明 
declareddeduced 之间的区别,但 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 指定函数声明的返回类型。 $ cat a.cpp auto main() -> int {} $ g++ -Wall -std=c++14 a.cpp $

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

从 3.6.1 [basic.start.main]开始

8
投票

1 程序应包含一个名为 main 的全局函数,它是 指定程序的开始....

2 实施不得 预定义主要功能。该函数不得超载。它 应具有 int 类型的声明返回类型,但除此之外其类型 是实现定义的...


如果标准是限制推导,那么我认为“声明返回类型 int”就是这样的说法。

许多答案都很好地提到了标准中的引用。但是

4
投票
作为返回类型还有另一个微妙的问题。

根据 C++ 标准 (
somewhere

),

return 语句在 main()

 内不是强制的
。 Bjarne Stroustrup 的网站
中明确提到了这一点:
在 C++ 中,

main()
不需要包含显式的

return

 语句。此时返回的值为
0
,表示执行成功。 

这意味着以下声明是有效的:

auto main () {}

可以假设在
return 0;
之前有一个隐式的

}

 语句。所以在这种情况下 
auto
解释为
 
int。然而,从 C++14 的技术细节来看,由于没有 return 语句,因此 auto
 必须 
推导为
 
void!那么,“int
 vs 
void
”,要考虑什么?
IMO 这是一个警告,它也阻止 
auto

作为逻辑意义上的返回类型。


正如各种评论中所讨论的,我确实在标准中遗漏了它,因为我认为是 C++14 FDIS 的副本实际上不是这样的东西(而是一个稍旧的草案),并且这个词“声明”被偷偷塞进了

3
投票
之后的相关段落中。

© www.soinside.com 2019 - 2024. All rights reserved.