为什么gcc会警告decltype(main())而不是clang?

时间:2014-08-13 22:28:52

标签: c++ gcc c++11 clang

请使用以下代码:

int main()
{
    decltype(main()) x = 0;
    return x;
}

gcc抱怨:

main.cpp: In function 'int main()':
main.cpp:8:19: warning: ISO C++ forbids taking address of function '::main' [-Wpedantic]
     decltype(main()) x = 0;
                   ^
main.cpp:8:19: warning: ISO C++ forbids taking address of function '::main' [-Wpedantic]

但没有铿锵。那么decltype(main())会引发这个错误呢? decltype如何获取main的地址?

2 个答案:

答案 0 :(得分:11)

在这种情况下,GCC的诊断可能没有正确措辞,因为decltype不需要知道main的地址;它只需要知道它的类型。但是,警告基于标准(§3.6.1/ 3)中的以下内容:

  

函数main不得在程序中使用。

我认为GCC将此解释为意味着您甚至无法在未评估的表达中使用它。

Clang(版本3.4无论如何)似乎根本没有实现这个规则,即使我打开了我能想到的所有标志,即使main递归调用自己。这就是为什么它不会给你一个警告。

答案 1 :(得分:10)

这个主题最近实际上出现在帖子undefined behaviour study group discussion listWhat does "The function main shall not be used within a program" mean?中。它没有马上出现,但是here是它在线程中开始的地方,带有以下语句:

  

我不认为decltype(main())是一种使用,或者   的sizeof(decltype(主))。

一组非常简短的回复如下:

  

是的,我只是看不出那会是什么用途。你可能意味着   sizeof(decltype(& main))在后一种情况下。

     

我认为最常见的非ODR使用主要是在之后定义它   一个前瞻性声明,现在Steven Clamage已经澄清了这一点   应该是不正确的。 “使用”作为一种更广泛的定义   没有引用ODR的名称查找结果现在看起来正确。

  

C ++ 98提及'使用'有一个交叉引用3.2 [basic.def.odr]。   C ++ 11不再具有交叉引用,并且更改为说   ' odr-use',所以我希望它意味着任何使用。

所以似乎对3.6.1 主要功能的解释似乎是:

  

函数main不得在程序中使用。 [...]

表示任何即使在未评估的上下文中也是如此,因此gcc在这里产生错误是正确的,尽管消息本身似乎没有意义。

更新

注意original proposal: N3154修复Defect report 1109会将3.6.1更改为:

,这很有趣且有启发性。
  

函数main不应在程序中使用odr-used(3.2)。 ......

这将允许decltype示例,但在accepted时进行了修改,我们可以看到新proposal: N3214已更改为我们今天所拥有的内容:

  

函数main不得在程序中使用

这将强烈表明UB邮件列表中任何使用main格式错误的观点确实是正确的。