2010-08-31 3 views
1

Motivé par le discussioncours Unnamed

La grammaire pour les classes de C est définie comme

class-key identifier *[opt]* base-clause *[opt]* (Italique sont les miens)

Cela me signifie que le nom de la classe est l'option et nous pouvons avoir sans nom classes en C++.

Alors, est-ce que ce qui suit est bien formé?

struct X{ 
    struct{ 
     int x; 
     int y; 
    }; 
}; 

int main(){} 

VS: error C2467: illegal declaration of anonymous 'struct'

Comeau online: error: declaration does not declare anything struct{

GCC(ideone): Compiles fine

Toute pensée?

+0

travaille ici sous g ++ 4.4.4 – knittl

+0

Fonctionne sous Borland C++ 5.6.4 (C++ Builder 6) –

+0

fonctionne ici sous VS2010 –

Répondre

7

Non, il n'est pas bien formé. Vous ne pouvez pas dériver la syntaxe du langage à partir de ces instructions grammaticales uniquement. Les exigences supplémentaires figurant dans le texte de la norme doivent également être prises en compte. Dans ce cas, ce serait

7 Declarations

...

3 In a simple-declaration, the optional init-declarator-list can be omitted only when declaring a class (clause 9) or enumeration (7.2), that is, when the decl-specifier-seq contains either a class-specifier, an elaboratedtype-specifier with a class-key (9.1), or an enum-specifier. In these cases and whenever a class-specifier or enum-specifier is present in the decl-specifier-seq, the identifiers in these specifiers are among the names being declared by the declaration (as class-names, enum-names, or enumerators, depending on the syntax). In such cases, and except for the declaration of an unnamed bit-field (9.6), the decl-specifier-seq shall introduce one or more names into the program, or shall redeclare a name introduced by a previous declaration.

La dernière phrase est celle qui compte dans ce cas

La partie « option » est là que pour permettre à des déclarations comme

struct { int x; } s; 
typedef struct { int x, y; } Point; 

Le premier qui déclare un type de classe sans lien et une variable s de ce type. Notez que les types sans lien ne peuvent pas être utilisés pour déclarer une variable avec liaison, ce qui signifie qu'une telle déclaration ne peut pas être utilisée dans la portée de l'espace de noms.

Votre exemple est mal formé, mais ce serait légal

struct X { 
    struct { 
     int x; 
     int y; 
    } point; 
}; 

En outre, la syntaxe de classe sans nom est utilisé pour déclarer les syndicats anonymes (bien que je suis un peu perplexe par le fait que 7/3-t ne pas mentionner les unions anonymes).

+1

C'est intéressant. – Chubsdad

0

Ce code est réellement valide dans MSVC, vous devez avoir compilé dans un mode restreint.

Et pendant que je probablement jamais les utiliser, ils permettent d'effectuer certaines utilisation intéressante, comme ceci:

X obj; 
obj.x=1; 
obj.y=2; 

Ils sont utilisés par exemple dans la LARGE_INTEGER classe, seulement il est un union à la place. De cette façon, vous pouvez éviter les sous-objets lorsque tout ce que vous voulez vraiment, c'est qu'un membre soit divisible en plus petits morceaux.

La déclaration LARGE_INTEGER comme un exemple visuel:

#if defined(MIDL_PASS) 
typedef struct _LARGE_INTEGER { 
#else // MIDL_PASS 
typedef union _LARGE_INTEGER { 
    struct { 
     DWORD LowPart; 
     LONG HighPart; 
    }; 
    struct { 
     DWORD LowPart; 
     LONG HighPart; 
    } u; 
#endif //MIDL_PASS 
    LONGLONG QuadPart; 
} LARGE_INTEGER; 

Pour autant que je sais cependant, ce n'est pas valide la norme C++, il est admis uniquement comme des extensions de gcc et msvc.