C++ 局部变量能否与命名空间同名?

C++ 局部变量能否与命名空间同名?,c++,namespaces,language-lawyer,C++,Namespaces,Language Lawyer,GCC、clang和VS2013编译以下代码段: namespace A{} int main() { int A; } 但是[namespace.alias]/4说明了以下内容: 名称空间名称或名称空间别名不得声明为 同一声明区域中任何其他实体的名称 及 [basic.scope.declarative]/1表示: 每个名称都在程序文本的某个部分中引入,称为 声明性区域,它是程序中该名称有效的最大部分,也就是说,该名称可以用作 引用同一实体的非限定名称 也就是说,我的印象是main(

GCC、clang和VS2013编译以下代码段:

namespace A{}
int main()
{
    int A;
}
但是[namespace.alias]/4说明了以下内容:

名称空间名称或名称空间别名不得声明为 同一声明区域中任何其他实体的名称

[basic.scope.declarative]/1表示:

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

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

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


如果您查看示例3.3.1(2),请参见3.3.1(1)下面的示例

它被称为

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

注意它所说的名称的范围。我的


因此,在程序的全局空间中,您有一个名称
a
,这是您的名称空间。然后输入
main()
的范围,并且
名称空间A
仍然是有效名称,直到在
int A
的声明中看到。一旦在main的作用域中发生这种情况,名称空间
A
将被隐藏,对
A
的任何非限定调用都将指向已声明的
int

int A有效的最大作用域是
main
的整个作用域,因此其声明区域是
main
。命名空间在全局范围内有效,因此不在同一声明性范围内。请注意,虽然作用域重叠,但它们不是相同的作用域。考虑到您引用的标准代码,我认为该代码是有效的。

您提到的第一个引用[namespace.alias]/4实际上是为了涵盖扩展名称空间,并且是缺陷报告的主题,随后被删除并替换为更具体的措辞。从中我们可以看出:

根据7.3.1[namespace.def]第2段

原始名称空间定义中的标识符之前不得在 将显示原始名称空间定义

显然,该要求的目的是说,鉴于 声明

namespace N { }
namespace N { }
第二项声明将被视为 扩展命名空间定义,而不是 原始名称空间定义,因为3.3.1中的一般规则 [basic.scope.declarative]涵盖标识符具有 以前已声明为命名空间以外的内容

并告诉我们,
3.3.1
[basic.scope.declarative]涵盖了您所指的案例,它在第
1
段中就是这样做的:

每个名称都会引入程序文本的某个部分,称为声明性区域,这是最大的部分 该名称有效的程序的名称,也就是说,该名称可以用作非限定名称 指同一实体。通常,每个特定名称仅在某些可能不连续的范围内有效 程序文本的一部分称为其作用域。要确定声明的范围,有时很方便 引用声明的潜在范围。声明的范围与其潜在范围相同 除非潜在作用域包含另一个同名声明。在这种情况下,潜在的范围 内部(包含的)声明区域中声明的范围被排除在声明的范围之外 在外部(包含)声明性区域中

3

给定单个声明区域中的一组声明,每个声明指定相同的非限定名称

  • 它们应全部引用同一实体,或全部引用功能和功能模板

从[basic.scope.declarative]中,“声明性区域”的定义是:

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

我强调,限制是:

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

回到你的例子。如果我们对这两个声明性区域进行注释,我们有:

namespace A{}    + region #1
                 |
int main()       |           +
{                |           |
    int A;       |           | region #2               
                 |           |
}                +           +
名称空间A
(#1)和
int A
(#2)的声明区域是不同的(第二个是第一个的严格子集,但这并不重要)。因为它们是不同的,所以使用单一名称的限制不适用。#2中有一个
A
,#1中有一个
A

但是,如果我们将
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."
这将违反[basic.scope.declarative]/4,并且gcc和clang都正确地拒绝代码,并带有:

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

注t
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."