请考虑以下代码:
namespace C {
class X {};
}
namespace A {
class X {};
namespace B {
using namespace C;
X x;
}
}
由于x
指令,我期待C::X
的类型为using namespace
,而是 VS2010 和在线 LLVM / Clang 编译器将名称空间X
中的B
解析为A::X
。使用using声明(using C::X
)更改using指令,然后它会按预期解析为C::X
。
标准说明了使用指令[7.3.4.2]:
using-directive指定指定命名空间中的名称可以在using-directive之后出现using-directive的范围内使用。在非限定名称查找(3.4.1)期间,名称看起来好像是在最近的封闭命名空间中声明的,其中包含using-directive和指定的命名空间。
我对此的解读是C::X
应该看起来好像在命名空间B
中声明,有效隐藏A::X
。标准的哪个部分是在使用指令和使用声明之间的这种不一致的背后?有没有办法通过using指令隐藏外部作用域的名称?
答案 0 :(得分:6)
关于使用指令的章节似乎以某种方式清楚地表明您正在看到预期的行为:
7.3.4p2 using-directive指定指定命名空间中的名称可以在using-directive出现在using-directive之后的范围内使用。在非限定名称查找(3.4.1)期间,名称看起来好像是在最近的封闭命名空间中声明的,其中包含 both using-directive和指定的命名空间。
7.3.4p3 using-directive不会将任何成员添加到它出现的声明区域。
也就是说, using-directive 将命名空间的成员添加到指令的公共命名空间祖先和使用的命名空间的查找集中,而不是直接到的范围内使用using-directive 。这在第二个引用中明确说明:它不会将任何成员添加到 using-directive 的声明区域。
后来有一个例子旨在说明其他内容,但实际上显示了这一点:
7.3.4p4 [...]另一个例子
namespace A {
int i;
}
namespace B {
int i;
int j;
namespace C {
namespace D {
using namespace A;
int j;
int k;
int a = i; // B::i hides A::i
}
最后一个示例用于阐明传递性(并包含更多代码),但是一旦删除了额外的代码,它实际上等同于您的代码。
所以看来在你的情况下, using-directive 并没有隐藏,而是被隐藏了。