Reputation: 6390
7.2/6 (C++14):
An enumeration whose underlying type is fixed is an incomplete type from its point of declaration (3.3.2) to immediately after its enum-base (if any), at which point it becomes a complete type. An enumeration whose underlying type is not fixed is an incomplete type from its point of declaration to immediately after the closing } of its enum-specifier, at which point it becomes a complete type.
Take a look at the snippet below (see live example):
enum A{} t; // enum A{} is a complete type (OK)
enum class B:int z; // enum class B:int is not a complete type
int main()
{
}
I understand why B
is not a complete type. But, by just looking at the paragraph above, this doesn't seem so clear to me. z
is declared right after the enum-base of an enumeration, whose underlying type is fixed, the same way t
is declared right after the closing }
of the enum-specifier of an enumerator whose underlying type is not fixed.
Upvotes: 2
Views: 116
Reputation: 137310
The problem isn't that B
isn't complete. As shown in your own quote, it is complete immediately after its enum-base, : int
. The problem is that you are using a construct that the grammar doesn't allow.
The type-specifier production allows two ways in which the keyword enum
can appear in it ([dcl.type]):
An elaborated-type-specifier containing enum
looks like ([dcl.type.elab])
enum
nested-name-specifieropt identifier
which doesn't fit your code, and moreover cannot declare a new type (see [basic.lookup.elab]/p2). That is, while struct A* pa;
is legal even without a previous declaration of A
, enum B * pb;
is not legal.
An enum-specifier ([dcl.enum]/p1) is one of
enum-head
{
enumerator-listopt}
enum-head{
enumerator-list,
}
without digging into what enum-head is, it is obvious this requires braces, which isn't in your code.
enum class B : int;
is an opaque-enum-declaration, whose grammar is
enum-key attribute-specifier-seqopt identifier enum-baseopt
;
This doesn't allow you to declare anything other than the enum itself.
In short, the grammar simply doesn't allow enum class B:int z;
. Instead, you can write enum class B:int; B z;
, which is perfectly valid, though the : int
is redundant.
Upvotes: 2