为什么不能推导出return类型的main?
Why can the return type of main not be deduced?
正如预期的那样,以下在 C++11 中失败,因为该语言没有 return 沼泽标准函数的类型推导:
auto main()
{
return 0;
}
但是,C++14 会,所以我无法解释以下错误(在 GCC trunk、clang 3.8 和 Visual Studio 2015 中具有相同的结果):
error: 'main' must return 'int'
标准中是否有一段我没有看到,禁止 main
的 return 类型推导?或者两个编译器都不兼容?
(为了它的价值,我从来没有真正这样做过。int main()
为了胜利......)
来自 3.6.1 [basic.start.main]
1 A program shall contain a global function called main, which is the
designated start of the program....
2 An implementation shall not
predefine the main function. This function shall not be overloaded. It
shall have a declared return type of type int, but otherwise its type
is implementation-defined...
如果标准是限制扣除,那么我认为措辞 "declared return type int" 就可以了。
正在阅读 the C++17 draft §3.6.1/2:
... and it shall have a declared return type of type int
, ...
所以是的,我会说禁止使用扣除。
the last C++14 draft中几乎完全相同的措辞(与 C++17 草案相同的部分):
It shall have a declared return type of type int
, ...
只是在阅读评论和其他答案后,对 可能 背后的推理进行个人反思。不允许 return 类型推导的推理是(我认为),因为编译器在看到 return
语句之前不知道 return 类型。其他类型(可隐式转换为 int
)可能被 return 编辑也很常见,这会使推导的类型错误。预先声明 return 类型(通过正常的老式方式,或使用尾随 return 类型)将在声明函数时设置类型,然后可以由编译器检查并且要正确。
至于允许类型别名,它们只是一种类型的别名。所以允许例如
typedef int my_type;
my_type main() { ... }
真的和
没什么区别
int main() { ... }
来自 3.6.1/2(强调我的):
[...]it shall have a declared return type of type int
, but otherwise its type is implementation-defined.
当使用 auto
时没有尾随 return 类型,函数的 声明的 return 类型 仍然是 auto
,即使 推导的 return 类型 可能是其他东西。 declared 和 deduced 之间的区别在标准中没有明确说明,但 7.1.6.4/7 可能会说明一些问题:
When [...] a return
statement occurs in a function declared with a return type that contains a placeholder type, the deduced return type [...] is determined from the type of its initializer. In the case of a return
with no operand or with an operand of type void
, the declared return type shall be auto
and the deduced return type is void
.
我的理解是:
auto main(){ return 0; }
声明的return类型仍然是auto
,虽然推断return类型 将是 int
。根据上面的 3.6.1/2,main
的 声明的 return 类型 必须 是 int
.因此,这是错误的。
但是,尾随 return 类型被视为 声明的 return 类型 。来自 7.1.6.4/2:
If the function declarator includes a trailing-return-type (8.3.5), that trailing-return-type specifies the declared return type of the function.
$ cat a.cpp
auto main() -> int {}
$ g++ -Wall -std=c++14 a.cpp
$
所有引用在 C++14 和 C++17 中都是相同的。
正如各种评论中所讨论的那样,我确实在标准中遗漏了它,因为我认为是 C++14 FDIS 的副本实际上不是这样的东西(而是一个稍旧的草案) , "declared" 这个词被偷偷塞进了 CWG 1669 之后的相关段落。
许多答案都很好地提到了标准中的引文。但是 auto
as return 类型还有另一个微妙的问题。
根据 C++ 标准 (somewhere), the return
statement is not mandatory inside main()
. This is explicitly mentioned in Bjarne Stroustrup's website:
In C++, main()
need not contain an explicit return
statement. In that case, the value returned is 0
, meaning successful execution.
这意味着下面的语句是有效的:
auto main () {}
可以假设在 }
之前有一个隐式的 return 0;
语句。所以在这种情况下 auto
被 解释为 int
。然而,从 C++14 的技术细节来看,auto
必须被 推导为 void
因为没有 return 语句!那么,“int
vs void
”,要考虑什么?
IMO 这是一个警告,它在逻辑意义上也阻止了 auto
作为 return 类型。
正如预期的那样,以下在 C++11 中失败,因为该语言没有 return 沼泽标准函数的类型推导:
auto main()
{
return 0;
}
但是,C++14 会,所以我无法解释以下错误(在 GCC trunk、clang 3.8 和 Visual Studio 2015 中具有相同的结果):
error: 'main' must return 'int'
标准中是否有一段我没有看到,禁止 main
的 return 类型推导?或者两个编译器都不兼容?
(为了它的价值,我从来没有真正这样做过。int main()
为了胜利......)
来自 3.6.1 [basic.start.main]
1 A program shall contain a global function called main, which is the designated start of the program....
2 An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a declared return type of type int, but otherwise its type is implementation-defined...
如果标准是限制扣除,那么我认为措辞 "declared return type int" 就可以了。
正在阅读 the C++17 draft §3.6.1/2:
... and it shall have a declared return type of type
int
, ...
所以是的,我会说禁止使用扣除。
the last C++14 draft中几乎完全相同的措辞(与 C++17 草案相同的部分):
It shall have a declared return type of type
int
, ...
只是在阅读评论和其他答案后,对 可能 背后的推理进行个人反思。不允许 return 类型推导的推理是(我认为),因为编译器在看到 return
语句之前不知道 return 类型。其他类型(可隐式转换为 int
)可能被 return 编辑也很常见,这会使推导的类型错误。预先声明 return 类型(通过正常的老式方式,或使用尾随 return 类型)将在声明函数时设置类型,然后可以由编译器检查并且要正确。
至于允许类型别名,它们只是一种类型的别名。所以允许例如
typedef int my_type;
my_type main() { ... }
真的和
没什么区别int main() { ... }
来自 3.6.1/2(强调我的):
[...]it shall have a declared return type of type
int
, but otherwise its type is implementation-defined.
当使用 auto
时没有尾随 return 类型,函数的 声明的 return 类型 仍然是 auto
,即使 推导的 return 类型 可能是其他东西。 declared 和 deduced 之间的区别在标准中没有明确说明,但 7.1.6.4/7 可能会说明一些问题:
When [...] a
return
statement occurs in a function declared with a return type that contains a placeholder type, the deduced return type [...] is determined from the type of its initializer. In the case of areturn
with no operand or with an operand of typevoid
, the declared return type shall beauto
and the deduced return type isvoid
.
我的理解是:
auto main(){ return 0; }
声明的return类型仍然是auto
,虽然推断return类型 将是 int
。根据上面的 3.6.1/2,main
的 声明的 return 类型 必须 是 int
.因此,这是错误的。
但是,尾随 return 类型被视为 声明的 return 类型 。来自 7.1.6.4/2:
If the function declarator includes a trailing-return-type (8.3.5), that trailing-return-type specifies the declared return type of the function.
$ cat a.cpp
auto main() -> int {}
$ g++ -Wall -std=c++14 a.cpp
$
所有引用在 C++14 和 C++17 中都是相同的。
正如各种评论中所讨论的那样,我确实在标准中遗漏了它,因为我认为是 C++14 FDIS 的副本实际上不是这样的东西(而是一个稍旧的草案) , "declared" 这个词被偷偷塞进了 CWG 1669 之后的相关段落。
许多答案都很好地提到了标准中的引文。但是 auto
as return 类型还有另一个微妙的问题。
根据 C++ 标准 (somewhere), the return
statement is not mandatory inside main()
. This is explicitly mentioned in Bjarne Stroustrup's website:
In C++,
main()
need not contain an explicitreturn
statement. In that case, the value returned is0
, meaning successful execution.
这意味着下面的语句是有效的:
auto main () {}
可以假设在 }
之前有一个隐式的 return 0;
语句。所以在这种情况下 auto
被 解释为 int
。然而,从 C++14 的技术细节来看,auto
必须被 推导为 void
因为没有 return 语句!那么,“int
vs void
”,要考虑什么?
IMO 这是一个警告,它在逻辑意义上也阻止了 auto
作为 return 类型。