web-dev-qa-db-fra.com

Qu'est-ce qu'un spécificateur de nom imbriqué?

Lié à this

Je veux savoir ce qu'est exactement un spécificateur de nom imbriqué? J'ai recherché dans le brouillon mais je pouvais comprendre la grammaire car je n'ai pas encore pris de cours de conception de compilateur.

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

::S est un qualifié-id.

Dans le qualifié-id::S::f, S:: est un spécificateur de nom imbriqué.

En termes informels1, un spécificateur de nom imbriqué est la partie du id qui

  • commence soit au tout début d'un qualifié-id ou après l'opérateur de résolution de portée initial (::) si l'on apparaît au tout début de la id et
  • se termine par le dernier opérateur de résolution de portée dans qualified-id.

Très informellement1, un id est soit un qualifié-id ou un nqualified-id. Si le id est un qualified-id, il est en fait composé de deux parties: un spécificateur de nom imbriqué suivi d'un nqualified-id.

Donné:

struct  A {
    struct B {
        void F();
    };
};
  • A est un nqualified-id.
  • ::A est un id qualifié mais n'a pas spécificateur de nom imbriqué.
  • A::B est un qualifié-id et A:: est un spécificateur de nom imbriqué.
  • ::A::B est un qualifié-id et A:: est un spécificateur de nom imbriqué.
  • A::B::F est un qualifié-id et les deux B:: et A::B:: sont spécificateurs de noms imbriqués.
  • ::A::B::F est un qualifié-id et les deux B:: et A::B:: sont spécificateurs de noms imbriqués.

[1] Ceci est une description assez inexacte. Il est difficile de décrire une grammaire en anglais simple ...

34
James McNellis

Un spécificateur d'espace de noms imbriqué est:

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

C'est-à-dire une liste non vide d'espaces de noms et de noms de classes, chacun suivi de ::, représentant une ramification relative dans "l'arborescence des espaces de noms" globale du programme. Par exemple, my_namespace::, my_namespace::inner_namespace::, my_namespace::my_class:: Et my_class::.

Notez spécifiquement la différence avec:

qualified-namespace-specifier :
    ::(optional) nested-name-specifier(optional) class-or-namespace-name

En ce sens, un spécificateur de nom imbriqué peut ne pas être absolu (préfixé avec :: Pour faire référence à la portée globale), tandis qu'un spécificateur d'espace de nom qualifié peut l'être, mais ne se termine pas par ::.

Dans votre exemple, ::S Se résout en fonction ::S(), et non en struct (les règles de priorité pour cela ont été discutées ici sur Stackoverflow dans la question à laquelle vous avez lié au début de votre question), il ne s'agit donc pas d'un spécificateur de nom imbriqué.

6
Tony Delroy

Bonne question! J'ai appris quelque chose de nouveau en faisant des recherches et en expérimentant dessus.

Vous avez raison dans votre commentaire, ::S(); //Is ::S a nested name specifier <-- Yes, Indeed!

Vous l'apprécieriez lorsque vous commenceriez à créer des espaces de noms. Les variables peuvent avoir les mêmes noms dans les espaces de noms et le :: L'opérateur est ce qui les distingue. Les espaces de noms sont comme des classes dans un sens, une autre couche d'abstraction. Je ne voudrais pas vous ennuyer avec des espaces de noms. Vous ne pouvez pas apprécier le spécificateur de nom imbriqué dans cet exemple ... considérez celui-ci:

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

Notez que j'ai utilisé ::count où j'aurais pu simplement utiliser count. ::count fait référence à l'espace de noms global.

Donc, dans votre cas, puisque S() est dans l'espace de noms global (c'est-à-dire qu'il est déclaré dans le même fichier ou un fichier inclus ou tout morceau de code où il n'est pas enveloppé par namespace <name_of_namespace> { }, vous pouvez utiliser new struct ::S ou new struct S; celui que tu préfères.

Je viens d'apprendre cela car j'étais curieux de répondre à cette question, donc si vous avez une réponse plus spécifique et apprise, veuillez la partager :)

3
iGbanam