[英]Can a local variable have the same name as a namespace?
GCC,clang和VS2013会编译以下代码段:
namespace A{}
int main()
{
int A;
}
但是[namespace.alias] / 4表示以下内容:
不能将名称空间名称或名称空间别名声明为同一声明性区域中任何其他实体的名称。
和
[basic.scope.declarative] / 1说:
每个名称都会在程序文本的称为声明性区域的一部分中引入,这是该名称有效的程序的最大部分,也就是说,该名称可以用作引用相同实体的非限定名称。 。
也就是说,我的印象是main()
中的int
变量不能与名称空间A
具有相同的名称。 观察到[basic.scope.declarative] / 2中的示例似乎证实了这一点
第一个j的声明性区域包括整个示例。
从[basic.scope.declarative]中,“声明性区域”的定义为:
每个名称都会在程序文本的称为声明性区域的一部分中引入,这是该名称有效的程序的最大部分,也就是说,该名称可以用作引用相同实体的非限定名称。 。
限制是,重点是:
给定一个声明区域中的一组声明 ,每个声明指定相同的非限定名称
—它们都应引用同一个实体,或均引用功能和功能模板
回到您的示例。 如果注释两个声明性区域,则有:
namespace A{} + region #1
|
int main() | +
{ | |
int A; | | region #2
| |
} + +
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."
这将违反[basic.scope.declarative] / 4,并且gcc和clang均正确拒绝代码,并带有:
错误:将“
A
”重新定义为另一种符号
请注意,正如沃恩·卡托 ( Vaughn Cato)所指出的那样,对于声明性区域的用语,存在活跃的缺陷报告 。
您提到的第一个[namespace.alias] / 4引号实际上是在覆盖扩展名称空间,并且是缺陷报告的主题,随后被删除并替换为更具体的措词。 从DR 1795可以看到:
根据7.3.1 [namespace.def]第2段,
原始名称空间定义中的标识符不应事先在显示原始名称空间定义的声明性区域中定义。
显然,此要求的意图是,鉴于声明
namespace N { } namespace N { }
第二个声明应被视为扩展名空间定义而不是原始名称空间定义,因为3.3.1 [basic.scope.declarative]中的一般规则涵盖了标识符先前已声明为除名称空间外的其他内容。
并告诉我们,第3.3.1
[basic.scope.declarative]涵盖了您所指的情况,它在第1
段中做了说明:
每个名称都会在程序文本的称为声明性区域的一部分中引入,这是该名称有效的程序的最大部分,也就是说,该名称可以用作引用相同实体的非限定名称。 。 通常,每个特定名称仅在程序文本的某些可能不连续的部分(称为范围)内有效。 要确定声明的范围,有时可以方便地引用声明的潜在范围。 声明的范围与其潜在范围相同,除非潜在范围包含另一个同名声明。 在那种情况下,内部(包含)声明性区域中声明的潜在范围被排除在外部(包含)声明性区域中声明的范围之外。
和3
:
给定一个声明区域中的一组声明,每个声明指定相同的非限定名称,
- 它们都应指代同一个实体,或均指功能和功能模板;
如果看3.3.1(1)下方的示例3.3.1(2)
int j = 24;
int main() {
int i = j, j;
j = 42;
}
注明为
标识符j两次声明为一个名称(并使用两次)。 第一个j的声明性区域包括整个示例。 第一个j的潜在范围从该j之后立即开始,一直延伸到程序的结尾,但是其(实际)范围不包括,和}之间的文本。 j的第二个声明的声明区域(分号前的j)包括{和}之间的所有文本,但其潜在范围不包括i的声明。 j的第二个声明的范围与其潜在范围相同。
请注意其名称的含义。 强调我的。
因此,在程序的全局空间中,您有一个名称A
,即您的命名空间。 然后输入main()
的范围,并且在看到int A
的声明之前,名称namespace A
仍然是有效名称。 一旦这在main范围内发生,则名称空间A
将被隐藏,并且对A
任何不合格调用将被声明为int
。
您的int A
有效的最大范围是main
的整个范围,因此它的声明性区域是main
。 命名空间在全局范围内有效,因此不在同一声明性范围内。 请注意,虽然范围重叠,但它们不是同一范围。 根据您对标准的引用,该代码对我而言似乎有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.