局部变量是否可以与命名空间具有相同的名称
Can a local variable have the same name as a namespace?
GCC、clang和VS2013编译以下代码段:
namespace A{}
int main()
{
int A;
}
然而,〔namespace.alias〕/4表示如下:
命名空间名称或名称空间别名不应声明为同一声明性区域中任何其他实体的名称。
和
[基本范围声明性]/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)的声明性区域不同(第二个是第一个的严格子集,但这无关紧要)。由于它们是不同的,所以对只有一个名字的限制不适用。在#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
"重新定义为不同类型的符号
请注意,正如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
[基本.scope.declarative]涵盖了您所指的案例,它在第1
:段中做到了这一点
每个名称都被引入程序文本的某个部分,称为声明性区域,这是最大的部分该名称有效的程序的,也就是说,该名称可以用作非限定名称指代同一实体。一般来说,每个特定的名称只有在某些可能不连续的情况下才有效程序文本的一部分称为其作用域。为了确定声明的范围,有时很方便引用声明的潜在范围。声明的范围与其潜在范围相同除非潜在作用域包含另一个同名声明。在这种情况下,潜在范围内部(包含的)声明性区域中声明的在外部(包含)声明性区域中。
和3
:
给定单个声明性区域中的一组声明,每个声明都指定相同的非限定名称
- 它们应全部引用同一实体,或全部引用函数和函数模板
您的int A
有效的最大范围是main
的整个范围,因此它的声明性区域是main
。命名空间在全局范围内有效,因此不在同一声明性范围内。请注意,虽然作用域重叠,但它们不是相同的作用域。考虑到您引用的标准代码,该代码在我看来是有效的。
如果你看看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()
的作用域,namespace A
仍然是一个有效名称,直到在int A
的声明中看到为止。一旦在main的作用域中发生这种情况,名称空间A
将被隐藏,并且对A
的任何非限定调用都将是对已声明的int
的调用。
- 是否可以将函数导入命名空间,但不能导出它?
- VS2017 是否更改了 C++ 中访问 C# 命名空间的方式?
- C++ - 是否将常量幻数放入命名空间
- 初始化命名空间中的变量是否类似于将它们初始化为类成员?
- 是否将命名空间范围文件本地 (.cpp) 常量放在匿名命名空间中
- c++ 内联友元函数是否会导致命名空间之间的名称隐藏?
- 将以"_[a-z0-9]"开头和"using"的标识符导入全局命名空间是否定义良
- 是否可以在相同的命名空间中,但在不同的嵌套项目中定义具有相同名称的类
- 是否可以在 c ++ 中查看命名空间的所有内容?
- 是否有 GCC 警告,用于使用 C 库中的符号而不是通过命名空间 std?
- 是否有一个很好的方法可以在C 11中打印出像JSON一样的Trie结构(仅迭代解决方案)的扁平命名空间
- 使用显式命名空间限定符时模板实例化行为是否发生变化?
- 调用 ADL 时,表达式和命名空间之间是否会发生冲突
- 在同一命名空间中声明变量和函数是否出错?[C++]
- 是否可以将一个命名空间类 #include 到另一个命名空间中
- 是否可以避免在前向声明中使用嵌套命名空间?
- winrt 命名空间是否具有控制台函数?
- 在全局命名空间中重载不依赖于用户定义类型的标准定义类型的运算符是否格式正确?
- 命名空间别名是否会更改链接?
- 命名空间的定义是否可以跨越多个翻译单元