web-dev-qa-db-ja.com

ネストされた名前指定子とは何ですか?

関連 this

ネストされた名前指定子とは正確に何を知りたいですか?ドラフトを調べましたが、まだコンパイラデザインクラスを受講していないので、文法は理解できました。

void S(){}

struct S{
   S(){cout << 1;}
   void f(){}
   static const int x = 0;
}; 

int main(){ 
   struct S *p = new struct ::S;  
   p->::S::f();

   S::x;  

   ::S(); // Is ::S a nested name specifier?
   delete p;
} 
29
Glenn

::Squalified-idです。

qualified-id::S::fS::ネストされた名前指定子です。

非公式の言葉で1nested-name-specifieridの一部です

  • qualified-idの最初、または最初のスコープ解決演算子(::idの先頭にある場合、および
  • qualified-idの最後のスコープ解決演算子で終了します。

非常に非公式1idqualified-idまたはnqualified-idのいずれかです。 idqualified-idの場合、実際には、ネストされた名前指定子とそれに続くnqualified-idの2つの部分で構成されます。

与えられた:

struct  A {
    struct B {
        void F();
    };
};
  • Anqualified-idです。
  • ::Aqualified-idですが、-nested-name-specifierはありません。
  • A::Bqualified-idおよびA::ネストされた名前指定子です。
  • ::A::Bqualified-idおよびA::ネストされた名前指定子です。
  • A::B::Fqualified-idであり、両方のB::およびA::B::ネストされた名前指定子です。
  • ::A::B::Fqualified-idであり、両方のB::およびA::B::ネストされた名前指定子です。

[1]これはかなり不正確な説明です。文法を分かりやすい英語で説明するのは難しい...

34
James McNellis

ネストされた名前空間指定子は次のとおりです。

_nested-name-specifier :
    class-or-namespace-name::nested-name-specifier(optional)
_

つまり、名前空間とクラス名の空でないリストであり、それぞれの後に::が続き、プログラムの「名前空間ツリー」全体での相対的な分岐を表します。たとえば、_my_namespace::_、_my_namespace::inner_namespace::_、_my_namespace::my_class::_、_my_class::_などです。

特に以下との違いに注意してください。

_qualified-namespace-specifier :
    ::(optional) nested-name-specifier(optional) class-or-namespace-name
_

ネストされた名前指定子は絶対ではない場合があります(グローバルスコープを参照するために_::_が前に付けられます)。一方、修飾された名前空間指定子は絶対指定できますが、_::_で終了することはできません。

あなたの例では、_::S_は構造体ではなく関数::S()に解決されます(そのための優先規則は、質問の冒頭にリンクした質問のStackoverflowでここで説明されています)。ネストされた名前指定子ではありません。

6
Tony Delroy

良い質問!私はそれについて研究し実験することで何か新しいことを学びました。

あなたはコメントで正しいです、::S(); //Is ::S a nested name specifier <-- Yes, Indeed!

名前空間の作成を開始すると、それを高く評価するようになります。変数は名前空間全体で同じ名前を持つことができ、::演算子はそれらを区別するものです。名前空間は、ある意味ではクラスのようなものであり、抽象化のもう1つの層です。名前空間に飽きたくありません。この例では、ネストされた名前指定子に感謝しないかもしれません...これを検討してください:

#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;
}

::countを使用したことに注意してください。ここでは、単にcountを使用することもできました。 ::countは、グローバル名前空間を指します。

したがって、あなたのケースでは、S()はグローバル名前空間にあります(つまり、同じファイル、インクルードファイル、またはnamespace <name_of_namespace> { }で囲まれていないコードの一部で宣言されています) 、new struct ::Sまたはnew struct S;のどちらでも使用できます。

私はこの質問に答えたいと思っていたので、これを学びました。より具体的で学んだ答えがある場合は、共有してください:)

3
iGbanam