Why class {int i; }; not fully standard compatible?

This is the next question.

In a previous question, @ JohannesSchaub-litb said the following code is not fully standard compatible:

class { int i; }; //unnamed-class definition. Β§ 9/1 allows this! 

and then added:

while it is grammatically correct, it violates the rule that such a class must declare at least one name in its scope.

I could not understand this. What name is he talking to?

Can anyone dwell on this in more detail (preferably with reference to the standard)?

+43
c ++ definition class identifier
Oct 30 '12 at 12:05
source share
5 answers

In section 9 of the standard, class {public: int i;} allowed (note the absence of an end semicolon), because this decl-specifier-seq for an unnamed class can be used in some other construct such as typedef or variable declaration . Problem with class {public: int i;}; (note that the last semicolon is now present) is that this class specification now becomes a declaration. This is an illegal declaration in accordance with paragraph 7 of Article 7 of the standard:

In such cases, and with the exception of declaring an unnamed bit field (9.6), decl-specifier-seq must enter one or more names in the program or update the name entered by the previous declaration.

+50
Oct 30 '12 at 12:50
source share

The fact is that by declaring class{ int i; }; class{ int i; }; , you collect a bunch of character ( int i , in this case), you cannot use anywhere in any code.

For this code to make sense, you must at least do one of the following:

 class Myclass { int i; }; //I can furthermore instantiate variables of Myclass class { int i; } myvar; //This in fact creates a myvar object typedef class { int i; } MyType; //I can funthermore instantiate variables of MyType 

Simply put, class{ int i; }; class{ int i; }; you tell the compiler:

  • save int and name it i ,
  • wrap it in class I'll never call and ...
  • Forget it! ( }; )

If you remove this ad from your program, nothing will change.

+26
Oct. 30 '12 at 12:22
source share

class { int i; }; is not a valid declaration because it is a simple declaration without an init-declarator list, but it does not enter (or re-declare) the class name.

ISO / IEC 14882: 2011 7 [dcl.dcl] / 3:

In a simple declaration, the optional init-declarator list can only be omitted when declaring a class (section 9) or listing (7.2), that is, when spec-specifier-seq contains either a class specifier, a specified type specifier with a class key (9.1), or an enumeration specifier . In these cases, and whenever a class specifier or an enumeration specifier is present in the description specifier-seq, identifiers in these qualifiers are among the names declared by the declaration (as class names, enumerated names or enumerations, depending on the syntax). In such cases, and with the exception of declaring an unnamed bit field (9.6), decl-specifier-seq must enter one or more names in the program or update the name entered by the previous declaration.

+11
Oct 30 '12 at 12:52
source share

The error message from GCC explains this quite briefly:

 $ cat > a.cc class { int i; }; $ g++ -Wall -std=c++98 a.cc a.cc:1: error: abstract declarator '<anonymous class>' used as declaration 

class { int i; } class { int i; } is an abstract declarator (standard, Β§8), but is not a valid declaration (Β§7). This is the rule referenced by @ JohannesSchaub-litb: for a valid announcement you need to declare something, for example. class name or variable name.

+10
Oct 30 '12 at 12:28
source share

You are violating [basic.scope.pdecl]/6 , which states:

The declaration point of the class first declared in the specified type specifier is as follows:
- to declare a form
class-key attribute-specifier-seqopt identifier ;

the identifier is declared as the class name in the scope containing the declaration, otherwise
- for the specified type specifier type
class-key identifier

if the specified type specifier is used in the decl-specifier-seq or declaration parameter function defined in the namespace area, the identifier is declared as the class name in the namespace, contains a declaration; otherwise, except for declaring a friend, the identifier is declared in the smallest namespace or block area containing the declaration. [Note. These rules also apply within patterns. - end note] [Note: Other forms of the specified type specifier do not declare a new name, and therefore must reference an existing type name. See 3.4.4 and 7.1.6.3. - final note]

  • you are not creating an anonymous type variable
  • you are not creating a type

There is another example in the standard (in [basic.def]/2 ) that proves that your example does not comply with the standard:

 struct S { int a; int b; }; // defines S, S::a, and S::b struct X { // defines X int x; // defines non-static data member x static int y; // declares static data member y X(): x(0) { } // defines a constructor of X }; int X::y = 1; // defines X::y enum { up, down }; // defines up and down namespace N { int d; } // defines N and N::d namespace N1 = N; // defines N1 X anX; // defines anX 

In your example, nothing is defined (except for the anonymous structure, which fields cannot be accessed).

Note the exclusion from the listing, because this case introduces two values ​​to use.

+3
30 Oct '12 at 12:56
source share



All Articles