局部变量可以与命名空间同名吗?

Leo*_*eon 10 c++ namespaces language-lawyer

GCC,clang和VS2013编译下面的代码:

namespace A{}
int main()
{
    int A;
}
Run Code Online (Sandbox Code Playgroud)

但[namespace.alias]/4表示如下:

一个命名空间名称命名空间别名不得申报为同一任何其他实体的名称声明区.

[basic.scope.declarative]/1说:

每个名称都在程序文本的某些部分中引入,称为 声明性区域,该声明区域是该名称有效的程序的最大部分,也就是说,该名称可以用作非限定名称以引用同一实体.

也就是说,我的印象是int变量in main()不能与命名空间同名A.注意到[basic.scope.declarative]/2中的例子似乎证实了这一点

第一个j 的声明区域包括整个示例.

Bar*_*rry 5

从[basic.scope.declarative]来看,"声明区域"的定义是:

每个名称都在程序文本的某些部分中引入,称为声明性区域,该声明区域是该名称有效的程序的最大部分,也就是说,该名称可以用作非限定名称以引用同一实体.

限制是,强调我的:

给定一个声明区域中的一组声明,每个声明都指定相同的非限定名称
- 它们都应引用同一个实体,或者全部引用函数和函数模板

回到你的榜样.如果我们注释两个声明区域,我们有:

namespace A{}    + region #1
                 |
int main()       |           +
{                |           |
    int A;       |           | region #2               
                 |           |
}                +           +
Run Code Online (Sandbox Code Playgroud)

namespace A(#1)和int A(#2)的声明区域是不同的(第二个是第一个的严格子集,但这无关紧要).由于它们不同,因此对单一名称的限制不适用.有一个单一的A在#2和一个单一A在#1.

但是,如果我们搬到int A同一个声明区域:

namespace A {}     +   the only declarative region. even though the
int A;             |   potential scope of "int A" does not include
                   |   "namespace A", the declarative region does.
int main() {       |   The intent of this is expressed in the example
                   |   in [basic.scope.declarative]/2:
                   |        int main() {
                   |            int i = j, j;
                   |            j = 42;
                   |        }
                   |
                   |   "The declarative region of the [j] includes all 
                   |    the text between { and }, but its potential scope
}                  +    excludes the declaration of i."
Run Code Online (Sandbox Code Playgroud)

这将违反[basic.scope.declarative]/4,并且gcc和clang都正确拒绝代码:

错误:将' A' 重新定义为不同类型的符号

请注意,正如Vaughn Cato指出的那样,关于声明性区域的措辞存在一个活跃的缺陷报告.


Nat*_*ica 0

如果你看看 3.3.1(1) 下面的例子 3.3.1(2)

int j = 24;
int main() {
    int i = j, j;
    j = 42;
}
Run Code Online (Sandbox Code Playgroud)

记为

标识符 j 作为名称被声明两次(并使用两次)。第一个 j 的声明区域包括整个示例。第一个 j 的潜在作用域紧随该 j 之后开始,一直延伸到程序末尾,但其(实际)作用域不包括 , 和 } 之间的文本。j 的第二个声明(分号之前的 j)的声明区域包括 { 和 } 之间的所有文本,但其潜在范围不包括 i 的声明。j 的第二个声明的范围与其潜在范围相同。

请注意名称的范围。强调我的。

因此,在程序的全局空间中,您有一个名称A,即您的命名空间。然后您输入 的范围main()namespace A直到在 的声明中int A看到 之前, 仍然是有效名称。一旦在 main 范围内发生这种情况,命名空间A将被隐藏,任何不合格的调用都A将针对int已声明的。