OMG*_*chy 3 c++ namespaces ambiguous
请考虑以下两个代码段:
#include <iostream>
namespace
{
bool foo = false;
}
bool foo = true;
int main()
{
std::cout << foo << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
#include <iostream>
namespace A
{
namespace
{
bool foo = false;
}
bool foo = true;
}
int main()
{
std::cout << A::foo << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
在Snippet A中,foo里面的用法int main()是模棱两可的,而在Snippet B中则不然.为什么会这样?
相关:匿名命名空间歧义
未命名的命名空间的行为在§7.3.1.1[namespace.unnamed]/p1中指定:
一个不愿透露姓名的命名空间定义的行为就好像它被取代
Run Code Online (Sandbox Code Playgroud)inline_opt namespace unique { /* empty body */ } using namespace unique ; namespace unique { namespace-body }其中
inline当且仅当它出现在出现 未命名的名称空间定义,所有出现unique在翻译单元由相同的标识符代替,并且该标识符从在整个程序中所有其他标识符不同.
特别要注意,未命名的命名空间内的声明通过using-directive 在周围的作用域中可见using namespace unique;.
在Snippet A中,foo是不合格的,因此编译器执行非限定名称查找(§3.4.1[basic.lookup.unqual]).这里的相关内容是子条款的第2段:
2从由指定的命名空间中的声明使用指示符 在命名空间变得可见包围使用指示符 ; 见7.3.4.出于3.4.1中描述的非限定名称查找规则的目的,using-directive指定的命名空间中的声明 被视为该封闭命名空间的成员.
因此,非限定名称查找会查找两个声明foo,并且名称不明确.
在Snippet B中,A::foo是合格的,因此适用限定名称查找规则.由于A是名称空间,适用的子条款是§3.4.3.2[namespace.qual].与此相关,该规则在该子条款第2款中规定:
对于命名空间
X和名称m,命名空间限定的查找集S(X,m)定义如下:S'(X,m)设为min 的所有声明的X集合和X(7.3.1)的内联命名空间集合.如果S'(X,m)不是空的,S(X,m)是S'(X,m); 否则,S(X,m)是联盟S(Ni,m)的所有命名空间Ni提名using指令在X其内嵌的命名空间集中.
换句话说,只有在指定的命名空间及其内联命名空间集中找不到该名称时,限定名称查找才会考虑使用指令指定的命名空间.这里,名称foo在命名空间中找到A,因此不考虑由using-directive指定的未命名命名空间,并且没有歧义.
如果你::foo不是foo在Snippet A中编写,那么将适用合格的查找规则,并且再次没有歧义.