tags:

views:

77

answers:

2

Motivated by the discussion

The grammar for C++ classes is defined as

class-key identifier *[opt]* base-clause *[opt]* (Italics are mine)

This to me means that the class name is option and we can have unnamed classes in C++.

So, is the following well-formed?

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

Any thoughts?

A: 

That code is actually valid in MSVC, you must have compiled in a restricted mode.

And while I would most likely never use them, they do allow for some interesting usage, like this:

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

They're used for example in the LARGE_INTEGER class, only it's an union instead. This way you can avoid sub-objects when all you really want is one member to be splittable into smaller pieces.

The LARGE_INTEGER declaration as a visual example:

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

As far as I know however, this isn't valid standard C++, it's only allowed as extensions in gcc and msvc.

Blindy
+6  A: 

No, it is not well-formed. You cannot derive the language syntax from these grammar statements alone. The extra requirements are given in the text of the standard also have to be taken into account. In this case that would be

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.

The last sentence is the one that matters in this case

The "optional" part is only there to allow declarations like

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

The first one which declares a class type with no linkage and variable s of that type. Note that types with no linkage cannot be used to declare a variable with linkage, meaning that such declaration cannot be used in namespace scope.

Your example is ill-formed, but this would be legal

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

Also, nameless class syntax is used to declare anonymous unions (although I'm a bit puzzled by the fact that 7/3 does not mention anonymous unions).

AndreyT
@AndreyT: That's interesting.
Chubsdad