请考虑以下两个代码段:
#include <iostream>
namespace
{
bool foo = false;
}
bool foo = true;
int main()
{
std::cout << foo << std::endl;
}
#include <iostream>
namespace A
{
namespace
{
bool foo = false;
}
bool foo = true;
}
int main()
{
std::cout << A::foo << std::endl;
}
在Snippet A中,foo
内int main()
的使用情况不明确,而在Snippet B中则不然。为什么会这样?
答案 0 :(得分:5)
未命名的命名空间的行为在§7.3.1.1[namespace.unnamed] / p1中指定:
unnamed-namespace-definition 的行为就好像被
取代一样inline_opt namespace unique { /* empty body */ } using namespace unique ; namespace unique { namespace-body }
当且仅当
inline
出现在unique
中时才出现 unnamed-namespace-definition ,翻译单元中所有出现的using namespace unique;
都被相同的标识符替换, 标识符与整个程序中的所有其他标识符不同。
请特别注意,未命名的命名空间内的声明通过 using-directive foo
在周围的范围内可见。
在Snippet A中,foo
是不合格的,因此编译器执行非限定名称查找(§3.4.1[basic.lookup.unqual])。这里相关的是子条款的第2段:
2 using-directive 指定的命名空间声明 在包含 using-directive 的命名空间中可见;看到 7.3.4。出于3.4.1中描述的非限定名称查找规则的目的,由名称空间提名的声明 using-directive 被认为是该封闭命名空间的成员。
因此,非限定名称查找会找到A::foo
的声明,并且名称不明确。
在代码段B中,A
是合格的,因此适用了限定名称查找规则。由于X
是命名空间,因此适用的子句是§3.4.3.2[namespace.qual]。与此相关,该规则在该子条款第2款中规定:
对于名称空间
m
和名称S(X,m)
,名称空间限定的查找集S'(X,m)
的定义如下:让m
成为所有的集合X
中X
的声明以及S'(X,m)
的内联命名空间集 (7.3.1)。如果S(X,m)
不为空,则S'(X,m)
为S(X,m)
;除此以外,S(Ni,m)
是Ni
的联盟,用于提名所有名称空间X
通过foo
中的 using-directives 及其内联命名空间集。
换句话说,只有在指定的命名空间及其内联命名空间集中找不到该名称时,限定名称查找才会考虑由 using-directives 指定的命名空间。这里,名称A
位于名称空间::foo
中,因此不考虑 using-directive 指定的未命名名称空间,并且没有歧义。
如果您在代码段A中写foo
而不是{{1}},那么将会应用合格的查找规则,而且再次没有歧义。