Point of declaration for an enumeration

What is the point of declaration of enumeration types? Is it immediately after the name of an enumeration? I saw Standard C++ 14 (n4296) §3.3.2/3:

The point of declaration for an enumeration is immediately after the identifier (if any) in either its enum-specifier (7.2) or its first opaque-enum-declaration (7.2), whichever comes first

But when I try to reproduce it;

template <class T>
struct CL
{
    using UndType = int;
};

enum class E: CL<E>::UndType;  //error: E is undefined

I have got an error on all the compilers, although enum-base for enumeration E is placed after the identifier and must be visible.


The following;

enum class E : CL<E>::UndType;

Is not accepted as a valid declaration in some current implementations (tested clang++, g++ and MSVC). They do not accept the, as yet incomplete type E, in the enum-base CL<E>::UndType. The error given in the tested implementations is that E is undeclared at that point. They seem to place the point of declaration at the end of the enum-base, they consider it declared once it is complete.

When reading the specifications;

§14.3.1/2 Template type arguments

[ Note: A template type argument may be an incomplete type (3.9). — end note ]

And

§7.2/6 Enumeration declarations

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.

Does hint at it being compilable; as is the case with CRTP implementations.

I'm note sure if this (i.e. the failure to compile enum class E : CL<E>::UndType;) is the intention or if it was considered as a use case. From the specification, the opaque enum declaration is given some "special" treatment w.r.t. its base type and the requirement that it must be an integral type.

Presumably, the code should be compilable given the resolution to CWG#1482.


As for current workarounds...

This;

enum class E; // default underlying type is int

Is the minimum declaration.

The opaque declaration could be either;

enum class E : int; // int base

The following would be a full definition (including enumerators);

enum class E : int {/*...*/};

Or to use the class template, another type (possibly void) could be used.

enum class E : CL<void>::UndType;