Est la définition de type-nom facultatif dans une définition de type de déclaration?
J'ai été assez surpris quand j'ai vu le code suivant compile sans erreurs ou des avertissements dans g++-4.2:
typedef enum test { one };
Mon hypothèse était que si vous avez utilisé le typedef
mot-clé, il aurait besoin d'un identificateur dans:
typedef enum test { one } test;
Comme déjà mentionné, g++-4.2 l'accepte sans même un avertissement. Clang++ 3.0 avertit "avertissement: typedef nécessite un nom", de même Comeau avertit "avertissement: déclaration requiert une définition de type nom", et g++-4.6 informe: "avertissement: 'typedef" a été ignoré dans la présente déclaration".
Je n'ai pas été en mesure de déterminer où dans la norme de ce qui est permis, et je trouve ça un peu confus que deux des compilateurs avertir qu'il est nécessaire, ne devrait-elle pas être une erreur si la définition de type nom-de-l'est nécessaire mais n'est pas présent?
Mise à JOUR: j'ai vérifié en C avec la même compilateurs. Clang et comeau rendement de la même sortie, gcc donne un avertissement: "avertissement: inutile de stockage de classe spécificateur de vide déclaration", ce qui semble encore plus de confusion.
Mise à JOUR: j'ai vérifié la suppression du nom de l'enum et les résultats sont les mêmes:
typedef enum { one };
De même avec un nom struct:
typedef struct named { int x };
Mais pas avec une nouvelle structure, dans lequel cas, le code a été rejetée en g++ (4.2/4.6) avec "erreur: manque de type nom dans la définition de type-déclaration", gcc (4.2/4.6) a donné un avertissement: "avertissement: sans nom struct/union qui définit aucun cas", clang++ "avertissement: déclaration ne rien déclarer", comeau "erreur: déclaration requiert une définition de type nom"
- Intéressant, VS2010 accepte aussi le code sans avertissement / d'erreur.
- N'est-ce pas la syntaxe
typedef enum { one } test
? - ouais, je pense que ça doit être une erreur.
- C'est la syntaxe pour une sans nom enum, pas ce qui est demandé ici.
- Ce n'est pas vraiment le C++, est-il?
- Pourquoi n'est-ce pas?
- C++ ne nécessite pas l'enum qualifier une fois qu'il a déjà été typedef avais.
- Et cela fait de la non-C++ dans quel sens? Je ne nécessite même pas l'enum qualifier si elle n'a pas été
typedef
'd. - C++ est plus typesafe.
Vous devez vous connecter pour publier un commentaire.
C'est un dégénéré, la syntaxe est autorisée, mais ne fournit aucune prestation. Plus les compilateurs modernes peuvent être provoquées en émettant un avertissement à ce sujet; par défaut, ils ne peuvent pas. Sans la définition de type nom, le mot-clé
typedef
est superflue; dans votre exemple, il est complètement équivalent à:Un autre endroit où il peut se produire avec une structure:
Ceci est équivalent à:
Noter que
typedef
est officiellement (ou syntaxique) est une "classe de stockage spécificateur", commestatic
,extern
,auto
etregister
.C Standard
Dans la norme ISO/IEC 9899:1999 (c'est la norme), nous trouvons:
Et (comme demandé):
Si vous suivez à travers cette syntaxe, il y a beaucoup de dégénérer possibilités, et ce que vous avez montré est juste l'un des nombreux.
C++ Standard
Il est possible que le C++ a des règles différentes.
Dans la norme ISO/IEC 14882:1998 (l'original de la norme C++), nous trouvons dans le §7.1.1 'classe de Stockage des prescripteurs' que le C++ ne permet pas de traiter
typedef
comme une classe de stockage; la liste ajoutemutable
et excluttypedef
. Ainsi, la grammaire de la spécification detypedef
en C++ est certainement différente de la C les spécifications.Déclarations de spécifier la façon dont les noms doivent être interprétés. Des déclarations ont la forme
Depuis §7 ¶5 dit que
typedef
noms proviennent de la init-déclaration de et la init-demande de déclaration-liste est marqué 'opt', je pense que cela signifie que letypedef
nom peut être omis en C++, tout comme en C.typedef
est traitée comme un cas additionnel. Voir §7.1(.1).decl-specifier
j'avais déduit qu'il doit être dans la déclaration d'un identificateur, et depuis il n'y a rien de tout cela ne serait pas valable? (Que certains compilateurs C++ accepter, c'est autre chose).typedef struct {};
est diagnostiquée dans g++ comme une erreur lors de latypedef enum {};
n'est pas (dans le vide sans nom struct, gcc juste avertit, llvm/clang++ avertir, comeau rejette le code en C et C++ en mode...)La seule chose que j'ai pu trouver a été le suivant dans le C++03 standard
§7.1.3 [dcl.typedef] p1
:Avis le manque opt après identificateur, qui indique, au moins pour moi, qu'un identificateur est nécessaire pour la typedef-nom. Étrange que tous testés compilateurs (silencieusement) accepter cela.
Modifier: Après @la réponse de Jonathan, j'ai trouvé ce qui suit dans la même norme que ci-dessus:
Comme on peut le voir, il fournit un supplément de cas pour
typedef
et à la liste de stockage de classe spécificateurs de confirme:Donc, nous sommes tout aussi paumé qu'avant dans le C++ cas.
-Werror
alors vous n'avez pas à s'inquiéter à propos de la différence entre le diagnostic et le rejet 🙂Il ressemble vraiment un C vs C++ différence, pour moi. C++ implicitement typedefs les structures et les syndicats à leurs balises; ainsi, l'ajout de la définition de type est superflu, mais pas une erreur. Je ne sais pas si cela fonctionne pour les enums ainsi.
La chose à faire est de voir ce que les définitions de variables sont autorisés, après ces déclarations.
typedef
en C++ n'est pas superflu, car elle affecte l'interprétation du code, vous pouvez en lire plus dans ce answer à une ancienne question.