2011-06-15 11 views
15

無名の名前空間のこれらのネストされた2つの用法の間の機能の違いはあります:ネスト無名の名前空間

namespace A { namespace { 
    void foo() {/*...*/} 
}} 

namespace { namespace A { 
    void foo() {/*...*/} 
}}} 

限り、私はそれを見るように、両方のfoo sが内部ユニークを取得しますコンパイル単位あたりの識別子はA::fooでアクセスできますが、私が見ていないような微妙な違いはありませんか?

+1

(編集済み)ファイルレベルで別の 'A :: foo'を宣言することで、2番目の' foo'を効果的に隠すことができます。最初の 'foo'は' :: A :: foo'として常にアクセス可能です。あなたが 'A'を再び開き、別の' foo'をそこに宣言しない限り。つまり、はい、ほとんど同じです。 –

答えて

7

入力したとおり、違いはありません。

もちろん、第1レベルのネームスペースの宣言をブースの例に追加することはできますが、違いがあります。もしプログラマが区別する方法がありませんが、コンパイラのために、名前空間は区別され、

namespace A { 
    int i;   // Accessed globally in this file as "A::i". 
    namespace { 
    void foo() {/*...*/} 
}} 


namespace { 
    int i;   // Accessed globally in this file simply as "i". 
    namespace A { 
    void foo() {/*...*/} 
}}} 

注:

unnamed_namespaces.cpp:42:5: error: reference to ‘A’ is ambiguous 
unnamed_namespaces.cpp:19:17: error: candidates are: namespace A { } 
unnamed_namespaces.cpp:28:19: error:     namespace <unnamed>::A { } 

お役立ち:


EDIT:

ADL(引数依存名ルックアップ)に関しては、私はそれが他のためのオーバーロードの解決には優先順位の差がないことを理解foo()以下のようになります。

#include <iostream> 

void foo() { std::cout << "::foo()" << std::endl; } 

namespace A { 
    namespace { 
     void foo() { std::cout << "A::<unnamed>::foo()" << std::endl; } 

     class AClass 
     { 
     public: 
      AClass() 
      { foo(); } 
     }; 
    } 
} 


namespace { 
    namespace B { 
     void foo() { std::cout << "B::<unnamed>::foo()" << std::endl; } 

     using namespace A; 

     class BClass 
     { 
     public: 
      BClass() 
      { foo(); } 

      ~BClass() 
      { A::foo(); } 
     }; 
    } 
} 

int main() 
{ 
    A::foo(); 
    B::foo(); 
    foo(); 

    A::AClass a; 
    B::BClass b; 

    return 0; 
} 

C ompilerは、明示的に指定されない限り、最も近いfoo()を優先します。 したがって、コンストラクタはB::foo()を呼び出し、それにusing namespace Aが含まれています。 BClassデストラクタでA::foo()を呼び出すには、呼び出しを明示的に修飾する必要があります。我々はネストされたという名前名前空間に考え、どのように引数依存が解決されるかどう

A::<unnamed>::foo() 
B::<unnamed>::foo() 
::foo() 
A::<unnamed>::foo() 
B::<unnamed>::foo() 
A::<unnamed>::foo() 

多分それが明確になります。 olnyの違いは、無名のものに暗黙的にusingですが、コンパイラの設定は変更されません。

+2

あなたのアクセスの例は後方にあると思います。最初のものは 'A :: i'で、2番目のものは' i'です。 –

+0

デニスに感謝します。私はそれを修正した。 – j4x

+0

これまでのところ素晴らしい答えですが、名前空間がどのような種類の効果をADL上に持つことができるのか疑問を抱いていました。 'namespace A {void bar();}は' foo() 'を例? – ltjax