12

考虑以下代码:

namespace C {
    class X {};
}

namespace A {
    class X {};

    namespace B {
        using namespace C;

        X x;
    }
}

我期待的类型xC::X由于using namespace指令,但是VS2010和在线LLVM/Clang编译器X都在命名空间内解析BA::X. 使用 using 声明 () 更改 using 指令using C::X,然后它会C::X按预期解析。

该标准说明了使用指令 [7.3.4.2]:

using-directive 指定指定命名空间中的名称可以在 using-directive 出现在 using-directive 之后的范围内使用。在非限定名称查找 (3.4.1) 期间,名称看起来好像它们是在最近的封闭命名空间中声明的,其中包含使用指令和指定命名空间。

我对此的解读是,它C::X应该看起来好像在命名空间中声明B,有效地隐藏A::X。使用指令和使用声明之间的这种不一致背后是标准的哪些部分?有没有办法通过 using 指令从外部范围隐藏名称?

4

1 回答 1

6

关于using 指令的章节似乎以某种方式清楚地表明您正在看到预期的行为:

7.3.4p2 using-directive 指定指定命名空间中的名称可以在 using-directive 出现在 using-directive 之后的范围内使用。在非限定名称查找 (3.4.1) 期间,名称看起来好像它们是在最近的封闭命名空间中声明的,其中包含使用指令和指定命名空间。

7.3.4p3 using 指令不会将任何成员添加到它出现的声明区域。

也就是说,using-directive将命名空间的成员添加到指令的公共命名空间祖先和 used 命名空间的查找集中,而不是直接添加到使用 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
    }

最后一个示例用于阐明传递性(并包含更多代码),但是一旦您删除了额外的代码,它实际上就等同于您的代码。

因此,在您的情况下,使用指令似乎不是隐藏,而是被隐藏。

于 2012-05-24T16:39:21.610 回答