Wak*_*zil 11 c++ extern language-lawyer c++11
clang,gcc和VS2013都抱怨重新定义win main(),但是我在标准中找不到任何禁止它的东西.
namespace N {
extern int j;
int j;
}
int main()
{
extern int w;
int w;
}
Run Code Online (Sandbox Code Playgroud)
这些段落说明了extern在块作用域中使用声明,但它们似乎不能证明错误消息是正确的:
§3.3.1/ 4
给定一个声明区域中的一组声明,......
[注意:这些限制适用于引入名称的声明性区域,该名称不一定与声明发生的区域相同.特别是,详细类型说明符(7.1.6.3)和友元声明(11.3)可能会将一个(可能不可见)名称引入封闭的名称空间中; 这些限制适用于该地区.本地extern声明(3.5)可能会在声明出现的声明区域中引入一个名称,并在一个封闭的命名空间中引入一个(可能不可见)名称 ; 这些限制适用于这两个地区. - 尾注]
§3.3.2/ 10
[注意:Friend声明引用的函数或类是最近的封闭命名空间的成员,但它们不会在该命名空间中引入新名称(7.3.1.2).块作用域中的函数声明和使用块作用域中的extern说明符的变量声明引用作为封闭命名空间成员的声明,但它们不会在该作用域中引入新名称. - 尾注]
我认为这主要由§3.5/ 6涵盖.
特别是:
在块作用域中声明的函数的名称和由块作用域extern声明声明的变量的名称具有链接.如果存在具有相同名称和类型的链接的实体的可见声明,忽略在最内部封闭命名空间范围之外声明的实体,则块范围声明声明该实体并接收先前声明的链接.如果存在多个这样的匹配实体,则该程序是不正确的.否则,如果未找到匹配的实体,则块范围实体接收外部链接.
因此,extern int w;声明a w具有链接(在这种情况下,外部链接,因为在该点处没有可见的匹配实体).
然后尝试定义一个w没有链接的本地(按§3.5/ 8).
这在相同的范围内给出了两个相同名称的声明,但具有不同的链接.这是§3.3.1/ 4所禁止的:
给定一个声明区域中的一组声明,每个声明区域指定相同的非限定名称,
- 它们都应指同一实体,或全部指功能和功能模板; 要么
- 正好一个声明应声明一个不是typedef名称的类名或枚举名,其他声明都应引用相同的变量或枚举,或者全部引用函数和函数模板; 在这种情况下,隐藏类名或枚举名(3.3.10).
两者都没有引用函数,函数模板,类名或枚举名,因此这些"转义子句"都不适用.这两个声明必须引用同一个实体,该实体必须同时具有外部链接和无链接.由于这是不可能的,代码是不正确的.
| 归档时间: |
|
| 查看次数: |
474 次 |
| 最近记录: |