¿Qué espacios de nombres hay y cuáles son las reglas?

9

Nota: esta pregunta es sobre name space, no namespace.

El estándar C ++ tiene algunas referencias name space, pero no veo la definición de esto. Los estándares dicen que las etiquetas y las macros están en diferentes espacios de nombres. Todas las demás referencias name spaceestán en la sección de compatibilidad C / C ++, como esta ( borrador actual ):

Esta es una de las pocas incompatibilidades entre C y C ++ que se puede atribuir a la nueva definición de espacio de nombres de C ++ en la que un nombre se puede declarar como un tipo y como un no tipo en un solo ámbito, lo que hace que el nombre sin tipo oculte el escriba el nombre y requiera que las palabras clave class, struct, union o enum se usen para referirse al nombre del tipo. Esta nueva definición de espacio de nombres proporciona importantes ventajas de notación a los programadores de C ++ y ayuda a que el uso de los tipos definidos por el usuario sea lo más similar posible al uso de los tipos fundamentales.

¿Cuál es esta nueva definición de espacio de nombres ? ¿Dónde puedo encontrarlo en el estándar? ¿Cuáles son las reglas exactas? Las reglas parecen ser más complicadas que los "tipos no ocultos". Como, esto no compila:

typedef int Foo; // Foo is a type
void Foo();      // not a type, but compile error, instead of hiding

Pero esto hace:

struct Foo { }; // Foo is a type as well
void Foo();     // This hides the type Foo. "struct Foo" refers to the type

Y esto tampoco compila:

struct Foo { };   // Type
namespace Foo { } // Non-type, but compiler error instead of hiding
geza
fuente
La visión práctica es que un espacio de nombres es una clase singleton con miembros públicos (subclases). Por favor, no me linchen :-)
peterh - Reinstale a Monica el
2
@ peterh-ReinstateMonica leyó la pregunta (nuevamente)
YSC
FWIW, su enlace enlaza con las secciones relevantes: Subcláusula afectada: [class.name] [vea también [dcl.typedef]] Puede ver esas secciones para ver cómo funcionan las reglas.
NathanOliver
Hay al menos dos espacios de nombres: uno para etiquetas [stmt.label]/1y otro para macros [cpp]/8.
YSC
1
Es algo interesante (para mí) que tanto la descripción como el ejemplo muestran lo contrario de lo que menciona la justificación; un nombre de tipo que oculta un nombre que no es de tipo. Dado el estado del borrador, esperaría que ese párrafo cambie.
molbdnilo

Respuestas:

2

El término de espacio de nombres puede estar más bien establecido en la Norma ISO C; citando ISO C11 :

6.2.3 Espacios de nombres de identificadores

Si más de una declaración de un identificador particular es visible en cualquier punto de una unidad de traducción, el contexto sintáctico desambigua los usos que se refieren a diferentes entidades. Por lo tanto, hay espacios de nombres separados para varias categorías de identificadores, como sigue:

  • nombres de etiqueta (desambiguado por la sintaxis de la declaración y uso de la etiqueta);
  • las etiquetas de estructuras, uniones y enumeraciones (desambiguadas siguiendo any32) de las palabras clave struct, union o enum);
  • los miembros de estructuras o sindicatos; cada estructura o unión tiene un espacio de nombre separado para sus miembros (desambiguado por el tipo de expresión utilizada para acceder al miembro a través del operador. o ->);
  • todos los demás identificadores, llamados identificadores ordinarios (declarados en declaradores ordinarios o como constantes de enumeración).

La nueva definición de espacio de nombres de C ++ es, sin embargo, de ninguna manera reciente en el tiempo , y se ha descrito en [diff.class] / 1 en su forma actual desde la introducción de C ++ estándar ISO en el '98 . Solo se menciona en cualquier extensión en los contextos en los que difiere de ISO C, según [diff.class] / 1, que es citado por el OP.

Afaics necesitamos recurrir a ISO C11 / 6.2.3 y combinarlo con [diff.class] / 1 del estándar ISO C ++ para obtener una descripción coherente y completa de la (nueva) definición de espacio de nombres de C ++ , menos que azotemos el ISO Estándar de C ++ para, por ejemplo, [basic.scope.hiding] , [class.name] / 2 , [stmt.label] / 1 , [cpp.replace] / 8 y así sucesivamente para ver cómo y dónde se aplica.

[class.name] / 2

Una declaración de clase introduce el nombre de la clase en el ámbito donde se declara y oculta cualquier clase, variable, función u otra declaración de ese nombre en un ámbito adjunto. [...]

[etiqueta stmt] / 1

[...] Las etiquetas tienen su propio espacio de nombre y no interfieren con otros identificadores [...]

[cpp.replace] / 1

[...] Hay un espacio de nombre para los nombres de macro. [...]

dfri
fuente
1

En C (6.2.3 Espacios de nombre de identificadores) la noción de espacios de nombre se define de la siguiente manera.

1 Si más de una declaración de un identificador particular es visible en cualquier punto de una unidad de traducción, el contexto sintáctico desambigua los usos que se refieren a diferentes entidades. Por lo tanto, hay espacios de nombres separados para varias categorías de identificadores, como sigue:

- nombres de etiqueta (desambiguado por la sintaxis de la declaración y el uso de la etiqueta);

- las etiquetas de estructuras, uniones y enumeraciones (desambiguadas siguiendo any32) de las palabras clave struct, union o enum);

- los miembros de estructuras o sindicatos; cada estructura o unión tiene un espacio de nombre separado para sus miembros (desambiguado por el tipo de expresión utilizada para acceder al miembro a través del operador. o ->);

- todos los demás identificadores, llamados identificadores ordinarios (declarados en declaradores ordinarios o como constantes de enumeración).

Entonces, por ejemplo, un nombre de etiqueta de estructura puede coincidir con un nombre de función porque pertenecen a diferentes espacios de nombre. Cuando especifica una estructura con un nombre de etiqueta de estructura cuando tiene que usar la palabra clave struct. Entonces, por ejemplo, estas declaraciones no entran en conflicto.

struct s
{
    int s;
};

void s( void );

struct s s1;

En este fragmento de código, el nombre sde la etiqueta de la estructura no entra en conflicto con el nombre de la función s porque el nombre de la etiqueta se especificará con la palabra clave struct.

En C ++ puede usar nombres de etiquetas de estructura sin la palabra clave struct.

Por ejemplo

struct s
{
    int s;
};

s s;

Es un código correcto. En esta declaración

s s;

El nombre del identificador declarado soculta el nombre de la estructura. Entonces si entonces escribirás por ejemplo

s s1;

entonces el compilador emitirá un error porque en esta declaración s se considera como el nombre del identificador declarado anteriormente. Para resolver la ambigüedad, debe usar la palabra clave struct

struct s
{
    int s;
};

s s;

struct s s1;

Esto se describe en la siguiente cita del Estándar C ++ 20 (6.3.1 Regiones declarativas y ámbitos)

4 Dado un conjunto de declaraciones en una sola región declarativa, cada una de las cuales especifica el mismo nombre no calificado,

(4.1) - todos se referirán a la misma entidad, o todos se referirán a funciones y plantillas de funciones; o

(4.2) - exactamente una declaración declarará un nombre de clase o nombre de enumeración que no sea un nombre de tipo typedef y las otras declaraciones se referirán a la misma variable, miembro de datos no estático o enumerador, o todas se referirán a funciones y plantillas de funciones ; en este caso el nombre de la clase o el nombre de la enumeración está oculto (6.3.10). [ Nota: Un nombre de espacio de nombres o un nombre de plantilla de clase debe ser único en su región declarativa (10.3.2, Cláusula 17). - nota final ]

Como puede ver en la cita, un nombre de espacio de nombres debe ser único en su región declarativa. Entonces estas declaraciones

struct Foo { };
namespace Foo { } 

son incorrectos

Vlad de Moscú
fuente