12

次のコードを検討してください。

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 ディレクティブを変更すると、期待どおりusing C::Xに解決さC::Xれます。

標準は、ディレクティブの使用について述べています [7.3.4.2]:

using-directive は、using-directive が using-directive の後に現れるスコープで、指定された名前空間の名前を使用できることを指定します。非修飾名のルックアップ (3.4.1) では、名前は、using ディレクティブと指定された名前空間の両方を含む、最も近い外側の名前空間で宣言されているかのように表示されます。

これについての私の読みはC::X、あたかも namespace 内で宣言されているかのように見えB、事実上 を隠しているということA::Xです。ディレクティブの使用と宣言の使用の間のこの不一致の背後にある標準のセクションはどれですか? using ディレクティブによって外部スコープから名前を隠す方法はありますか?

4

1 に答える 1

6

ディレクティブの使用に関する章では、期待される動作が見られていることがなんとなく明らかなようです。

7.3.4p2 using-directive は、using-directive が using-directive の後に現れる範囲で、指名された名前空間の名前を使用できることを指定します。非修飾名のルックアップ (3.4.1) では、名前は、using ディレクティブと指定された名前空間の両方を含む、最も近い外側の名前空間で宣言されているかのように表示されます。

7.3.4p3 using ディレクティブは、それが現れる宣言領域にメンバーを追加しません。

つまり、using ディレクティブは、 using ディレクティブが使用されるスコープに直接ではなく、ディレクティブの共通の名前空間の祖先と使用される名前空間のルックアップ セットに名前空間のメンバーを追加します。これは、2 番目の引用符で明示的に述べられています。これは、 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は非表示ではなく、非表示になっているようです。

于 2012-05-24T16:39:21.610 に答える