c++ names

c++ - ¿Qué es un especificador de nombre anidado?



names (3)

Relacionado con this

Quiero saber qué es exactamente un especificador de nombre anidado? Busqué en el borrador, pero pude entender la gramática ya que todavía no he tomado ninguna clase de Diseño de compiladores.

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


¡Buena pregunta! Aprendí algo nuevo investigando y experimentando en ello.

Tienes razón en tu comentario, ::S(); //Is ::S a nested name specifier <-- Yes, Indeed! ::S(); //Is ::S a nested name specifier <-- Yes, Indeed!

Llegarías a apreciarlo cuando comiences a crear espacios de nombres. Las variables pueden tener los mismos nombres en los espacios de nombres y el operador :: es lo que los distingue. Los espacios de nombres son como clases en un sentido, otra capa de abstracción. No quisiera aburrirte con espacios de nombres. Es posible que no aprecie el especificador de nombre anidado en este ejemplo ... considere este:

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

Observe que usé ::count donde podría haber usado simplemente count . ::count refiere al espacio de nombres global.

Entonces, en su caso, dado que S () está en el espacio de nombres global (es decir, se declara en el mismo archivo o en un archivo incluido o en cualquier pieza de código donde no esté envuelto por el namespace <name_of_namespace> { } de namespace <name_of_namespace> { } , puede usar la new struct ::S o new struct S , lo que prefiera.

Aprendí esto porque tenía curiosidad por responder esta pregunta, así que si tiene una respuesta más específica y aprendida, por favor comparta :)


Un especificador de espacio de nombres anidado es:

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

Es decir, una lista no vacía de espacios de nombres y nombres de clase, cada uno seguido de ::, que representa una ramificación relativa en el "árbol de espacio de nombres" general del programa. Por ejemplo, my_namespace:: , my_namespace::inner_namespace:: , my_namespace::my_class:: y my_class:: .

Note específicamente la diferencia de:

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

En ese sentido, un especificador de nombre anidado puede no ser absoluto (prefijado con :: para referirse al ámbito global), mientras que un especificador de espacio de nombres calificado puede ser, pero no termina con :: .

En su ejemplo, ::S resuelve con la función ::S() , y no con la estructura (las reglas de precendencia para esto se discutieron aquí en en la pregunta que vinculó al comienzo de su pregunta), por lo que no es una Especificador de nombre anidado.


::S es un id calificado .

En el recurso calificado id ::S::f , S:: es un especificador de nombre anidado .

En términos informales 1 , un especificador de nombre anidado es la parte del ID que

  • comienza ya al principio de un id calificado o después del operador de resolución de alcance inicial ( :: si aparece uno al comienzo del id y
  • termina con el último operador de resolución de alcance en el id-calificado .

Muy informalmente 1 , un id es un id calificado o un id no calificado . Si el id es un id calificado , en realidad está compuesto de dos partes: un especificador de nombre anidado seguido de un id no calificado .

Dado:

struct A { struct B { void F(); }; };

  • A es un id no calificado .
  • ::A es un id-calificado pero no tiene un especificador de nombre anidado .
  • A::B es un id-calificado y A:: es un especificador de nombre anidado .
  • ::A::B es un id-calificado y A:: es un especificador de nombre anidado .
  • A::B::F es un id. Calificado y tanto B:: como A::B:: son especificadores de nombre anidados .
  • ::A::B::F es un id. Calificado y tanto B:: como A::B:: son especificadores de nombres anidados .

[1] Esta es una descripción bastante inexacta. Es difícil describir una gramática en un lenguaje sencillo ...