Quels sont les espaces de noms et quelles sont les règles?

9

Remarque: cette question concerne name space, non namespace.

La norme C ++ a quelques références name space, mais je ne vois pas la définition de cela. Les normes indiquent que les étiquettes et les macros se trouvent dans des espaces de noms différents. Toutes les autres références à se name spacetrouvent dans la section de compatibilité C / C ++, comme ceci (version actuelle ):

Il s'agit de l'une des rares incompatibilités entre C et C ++ qui peuvent être attribuées à la nouvelle définition d'espace de nom C ++ où un nom peut être déclaré en tant que type et en tant que non-type dans une seule étendue, ce qui fait que le nom non-type masque le nom de type et nécessitant que la classe de mots clés, la structure, l'union ou l'énumération soient utilisés pour faire référence au nom de type. Cette nouvelle définition d'espace de nom offre des fonctionnalités de notation importantes aux programmeurs C ++ et aide à rendre l'utilisation des types définis par l'utilisateur aussi similaire que possible à l'utilisation des types fondamentaux.

Quelle est cette nouvelle définition d'espace de nom ? Où puis-je le trouver dans la norme? Quelles sont les règles exactes? Les règles semblent être plus compliquées que les «types de masques non-types». Comme, cela ne compile pas:

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

Mais cela:

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

Et cela ne compile pas non plus:

struct Foo { };   // Type
namespace Foo { } // Non-type, but compiler error instead of hiding
geza
la source
La vue pratique est qu'un espace de noms est une classe singleton avec des membres tout public (sous-classes). S'il vous plaît ne me
lynchez
2
@ peterh-ReinstateMonica lire la question (encore)
YSC
FWIW, votre lien renvoie aux sections pertinentes: Paragraphe concerné: [class.name] [voir aussi [dcl.typedef]] Vous pouvez voir ces sections pour voir comment les règles fonctionnent.
NathanOliver
Il y a au moins deux espaces de nom: un pour les étiquettes [stmt.label]/1et un pour les macros [cpp]/8.
YSC
1
Il est quelque peu intéressant (pour moi) que la description et l'exemple montrent le contraire de ce que la justification mentionne; un nom de type masquant un nom non-type. Compte tenu du statut provisoire, je m'attends à ce que ce paragraphe change.
molbdnilo

Réponses:

2

Le terme d' espace de nom peut être plus bien établi dans la norme ISO C; citant ISO C11 :

6.2.3 Espaces de noms des identifiants

Si plusieurs déclarations d'un identifiant particulier sont visibles à un moment donné dans une unité de traduction, le contexte syntaxique désambiguïsera les utilisations qui font référence à différentes entités. Ainsi, il existe des espaces de noms distincts pour différentes catégories d'identificateurs, comme suit:

  • noms d'étiquettes (sans ambiguïté par la syntaxe de la déclaration et de l'utilisation des étiquettes);
  • les balises de structures, d'unions et d'énumérations (sans ambiguïté en suivant any32) des mots-clés struct, union ou enum);
  • les membres de structures ou d'unions; chaque structure ou union a un espace de nom distinct pour ses membres (sans ambiguïté par le type de l'expression utilisée pour accéder au membre via l'opérateur. ou ->);
  • tous les autres identificateurs, appelés identificateurs ordinaires (déclarés dans des déclarants ordinaires ou sous forme de constantes d'énumération).

La nouvelle définition de l' espace de noms de C ++ n'est cependant en aucun cas récente et a été décrite dans [diff.class] / 1 dans sa forme actuelle depuis l'introduction de la norme ISO C ++ en '98 . Elle n'est mentionnée dans aucune longueur dans les contextes pour lesquels elle diffère de l'ISO C, selon [classe diff.] / 1 citée par l'OP.

Afaics, nous devons recourir à l'ISO C11 / 6.2.3 et la combiner avec [classe diff.] / 1 de la norme ISO C ++ pour une description cohérente et complète de la (nouvelle) définition d'espace de nom de C ++ , moins nous fouettons l'ISO Norme C ++ pour par exemple [basic.scope.hiding] , [class.name] / 2 , [stmt.label] / 1 , [cpp.replace] / 8 et ainsi de suite pour voir comment et où cela s'applique.

[class.name] / 2

Une déclaration de classe introduit le nom de classe dans la portée où il est déclaré et masque toute classe, variable, fonction ou autre déclaration de ce nom dans une portée englobante. [...]

[stmt.label] / 1

[...] Les étiquettes ont leur propre espace de nom et n'interfèrent pas avec d'autres identifiants [...]

[cpp.replace] / 1

[...] Il y a un espace de nom pour les noms de macro. [...]

dfri
la source
1

En C (6.2.3 Espaces de noms des identifiants), la notion d'espaces de noms est définie de la manière suivante.

1 Si plusieurs déclarations d'un identifiant particulier sont visibles à un moment donné dans une unité de traduction, le contexte syntaxique désambiguïsera les utilisations qui font référence à différentes entités. Ainsi, il existe des espaces de noms distincts pour différentes catégories d'identificateurs, comme suit:

- noms d'étiquettes (sans ambiguïté par la syntaxe de la déclaration et de l'utilisation des étiquettes);

- les balises de structures, d'unions et d'énumérations (sans ambiguïté en suivant any32) des mots-clés struct, union ou enum);

- les membres de structures ou d'unions; chaque structure ou union a un espace de nom distinct pour ses membres (sans ambiguïté par le type de l'expression utilisée pour accéder au membre via l'opérateur. ou ->);

- tous les autres identifiants, appelés identifiants ordinaires (déclarés dans des déclarants ordinaires ou sous forme de constantes d'énumération).

Ainsi, par exemple, un nom de balise de structure peut coïncider avec un nom de fonction car ils appartiennent à des espaces de noms différents. Lorsque vous spécifiez une structure avec un nom de balise de structure lorsque vous devez utiliser le mot clé struct. Ainsi, par exemple, ces déclarations ne sont pas en conflit.

struct s
{
    int s;
};

void s( void );

struct s s1;

Dans cet extrait de code, le nom sde balise de la structure n'entre pas en conflit avec le nom de la fonction s car le nom de balise doit être spécifié avec le mot clé struct.

En C ++, vous êtes autorisé à utiliser des noms de balises de structure sans le mot clé struct.

Par exemple

struct s
{
    int s;
};

s s;

est un code correct. Dans cette déclaration

s s;

le nom de l'identifiant déclaré scache le nom de la structure. Alors si tu écriras par exemple

s s1;

alors le compilateur émettra une erreur car dans cette instruction s est considéré comme le nom de l'identifiant déclaré ci-dessus. Pour résoudre l'ambiguïté, vous devez utiliser le mot clé struct

struct s
{
    int s;
};

s s;

struct s s1;

Ceci est décrit dans la citation suivante de la norme C ++ 20 (6.3.1 Régions déclaratives et étendues)

4 Étant donné un ensemble de déclarations dans une seule région déclarative, chacune spécifiant le même nom non qualifié,

(4.1) - ils doivent tous faire référence à la même entité, ou tous faire référence à des fonctions et des modèles de fonctions; ou

(4.2) - exactement une déclaration doit déclarer un nom de classe ou un nom d'énumération qui n'est pas un nom typedef et les autres déclarations doivent toutes faire référence à la même variable, membre de données non statique ou énumérateur, ou toutes se référer à des fonctions et des modèles de fonction ; dans ce cas, le nom de classe ou le nom d'énumération est masqué (6.3.10). [ Remarque: Un nom d'espace de noms ou un nom de modèle de classe doit être unique dans sa région déclarative (10.3.2, article 17). - note de fin ]

Comme vous pouvez le voir dans la citation, un nom d'espace de noms doit être unique dans sa région déclarative. Donc, ces déclarations

struct Foo { };
namespace Foo { } 

sont incorrects.

Vlad de Moscou
la source