考虑以下程序:
extern int x;
auto x = 42;
int main() { }
Clang 3.5 接受它(现场演示),GCC 4.9 和 VS2013 没有(前者的现场演示)。谁是对的?C++ 标准中规定的正确行为在哪里?
令人惊讶的是,标准中对此的内容很少。我们听到的有关重新声明的信息是:
[C++11: 3.1/1]:
声明(第 7 条)可以将一个或多个名称引入翻译单元或重新声明先前声明引入的名称。[..]
以及唯一相关的部分auto
的语义:
[C++11: 7.1.6.4/3]:
否则,变量的类型是从其初始值设定项推导出来的。[..]
(提醒我们,类型x
is int
).
我们知道所有声明都必须为变量指定相同的类型:
[C++11: 3.5/10]:
在所有类型调整之后(在此期间 typedefs (7.1.3) 被它们的定义替换),引用给定变量或函数的所有声明指定的类型应相同,除了数组对象的声明可以指定因存在或不存在主数组边界而不同的数组类型(8.3.4)。违反此类型标识规则不需要诊断。
并且“类型的所有调整”应该解决有关的任何问题auto
参与这一切;那么我的解释是这本质上是一个有效的重新声明(和定义)x
在全局范围内使用类型int
,并且 Clang 是正确的。即使我们建议auto
不算是“类型调整”,因为最坏情况下不需要诊断all列出的实现以自己的方式兼容。
我相信 GCC 和 Visual Studio 受到以下启发:
[C++11: 7.1.6.4/5]:
一个程序使用auto
在本节未明确允许的上下文中是格式错误的。
……但我认为这是短视的。标准语言似乎不太可能禁止通常的重新声明规则,仅仅因为它们没有在内部重复或明确引用7.1.6.4
.
C++14 添加了与声明相关的措辞功能推导类型:
[C++14: 7.1.6.4/13]:
具有使用占位符类型的声明返回类型的函数或函数模板的重新声明或特化也应使用该占位符,而不是推导类型。[..]
通过对称性,人们可能会认为,在你的int
在这种情况下,GCC 和 VS 应该正确拒绝该程序。然而,这是一个不同的特征(因为演绎不能应用于单纯的声明),因此是一个不同的场景。
无论哪种方式,改进的标准措辞都会有所帮助。我认为这是一个[相当小的]编辑缺陷。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)