2011-08-10 10 views
4

ポイント:3.4.3.2/1名前空間のメンバーISO C++ドラフト(n3290)からポイント:ISO C++ドラフト(n3290)から3.4.3.2/1名前空間のメンバー

ネストされた名の場合qualified-idの指定子がネームスペースを指定した場合、ネストされた名前指定子の後に指定された名前 は、 の名前空間のスコープ内で検索されます。 修飾IDが::で始まる場合、::の後の という名前はグローバル名前空間で検索されます。 のいずれかの場合、template-idのtemplate-argumentの名前は、postfix-expression全体が発生するコンテキストで が検索されます。資格-idが始まる場合ここで

は、いずれかがBOLDの部分について説明することができます....とそれ以前のC++ 03のドラフトからのC++ 0xのドラフトに彼は

を追加しました::の後の名前は、グローバル名前空間の を参照しています。

はいずれも

答えて

5

::Sは資格-IDでくださいプログラム例で説明することができます。

修飾ID ::S::fでは、S::はネストされた名前指定子です。非公式の用語で

は、ネストされた名指定子は

  • は、資格-IDの先頭にまたは初期スコープ解決演算子(後のいずれかから始まるIDの一部です::)場合1つはIDの冒頭に現れ、
  • はqualified-idの最後のスコープ解決演算子で終わります。

非常に非公式には、idはqualified-idまたはunqualified-idです。 idがqualified-idの場合、実際には2つの部分で構成されます。つまり、ネストされた名前の指定子の後ろにunqualified-idが続きます。

は考える:

struct A { 
    struct B { 
     void F(); 
    }; 
}; 
  • Aは、修飾されていない-IDです。
  • ::Aは修飾IDですが、ネストされた名前指定子はありません。
  • A::Bは修飾IDで、A::はネストされた名前指定子です。
  • ::A::Bは修飾IDで、A::はネストされた名前指定子です。
  • A::B::Fは修飾IDであり、B::A::B::の両方はネストされた名前指定子です。
  • ::A::B::Fは修飾IDであり、B::A::B::の両方はネストされた名前指定子です。

もう一つの例:

#include <iostream> 
using namespace std; 

int count(0);     // Used for iteration 

class outer { 
public: 
    static int count;   // counts the number of outer classes 
    class inner { 
    public: 
     static int count;  // counts the number of inner classes 
    }; 
}; 

int outer::count(42);   // assume there are 42 outer classes 
int outer::inner::count(32768); // assume there are 2^15 inner classes 
           // getting the hang of it? 

int main() { 
    // how do we access these numbers? 
    // 
    // using "count = ?" is quite ambiguous since we don't explicitly know which 
    // count we are referring to. 
    // 
    // Nested name specifiers help us out here 

    cout << ::count << endl;  // The iterator value 
    cout << outer::count << endl;   // the number of outer classes instantiated 
    cout << outer::inner::count << endl; // the number of inner classes instantiated 
    return 0; 
} 

EDIT:

あなたのコメントを受けて、私はその文は、単にWRTにテンプレートの引数が処理されることによって、彼らのコンテキストとラインを意味信じます宣言されている。例えば、

f.~foo();で、fooがf.以内に検索され、そしてfoo<int>の範囲内で、それだけでfooとでそれを参照するために有効です。

+0

この部分について「どちらの場合でも、template-idのテンプレート引数の名前は、postfix-expression全体が発生するコンテキストで検索されます。」 ...これも説明してください – user751747

+0

@user:私の編集を参照してください。 –

5

修飾名検索と呼ばれます。
先頭の::は、グローバル名前空間を参照します。 ::で始まる修飾識別子は、常に、ローカル名前空間内の同じ名前付き識別子を介してグローバル名前空間内の何らかの識別子を参照します。

namespace A 
{ 
    namespace B 
    { 
     void doSomething(); 
    } 
} 

namespace Z 
{ 
    namespace A 
    { 
     namespace B 
     { 
      void doSomething(); 
     } 
    } 

    using namespace A::B // no leading :: refers to local namespace layer 

    void doSomethingMore() 
    { 
     doSomething(); // calls Z::A::B::doSomething(); 

    } 
} 

namespace Z 
{ 
    namespace A 
    { 
     namespace B 
     { 
      void doSomething(); 
     } 
    } 

    using namespace ::A::B // leading :: refers to global namespace A 
    void doSomethingMore() 
    { 
     doSomething(); // calls ::A::B::doSomething(); 
    } 
} 
+0

私はこれが答えではないことを恐れています - > "どのような例でもプログラムの例がありますか?" –

+0

@phresnel:恐れていない、今は答えです:) –

+0

+1ここに私のupvoteがあります。 –

2

太字のテキストは、2つの異なる状況を指します。最初の部分は、::をプレフィックスとして使用するかどうかの区別です。修飾名は、::を起動すると、正確な名前空間は、それが存在しない場合、検索は、ネストされた名前空間を検討する一方で、空の名前空間から始まるがチェックされます。

namespace A { 
    void f() { std::cout << "::A::f" << std::endl; } 
} 
namespace B { 
    namespace A { 
     void f() { std::cout << "::B::A::f" << std::endl; } 
    } 
    void g() { 
     A::f();  // ::B::A::f 
     ::A::f(); // ::A::f 
    } 
} 

段落の最後の文は、特定のを指し、テンプレート引数、そしてそれは、ルックアップはテンプレートが宣言された名前空間で開始されませんが、むしろそれがインスタンス化されている名前空間にいることを示しています:

struct A { 
    static void f() { std::cout << "::A::f()" << std::endl; } 
}; 
template <typename T> 
void f() { 
    T::f(); 
} 
namespace N { 
    struct A { 
     static void f() { std::cout << "::N::A::f()" << std::endl; } 
    }; 
    void g() { 
     f<A>(); 
    } 
} 

は、ルックアップは、テンプレートの名前空間でコールを開始した場合f<A>()f<::A>を指すが、その節は、参照がネームスペースN全体のpostfix-expressionがとなる)内で開始され、したがって::N::A::f()を呼び出します。

0
int a(1); 

class someCls { 
    private: 
    int a; 
    public: 
    // Assigns this->a with the value of the global variable ::a. 
    void assignFromGlobal() { 
     a = ::a; 
    } 
}; 
関連する問題