2016-02-29 12 views
18

Worauf kommt es bei der Deklaration von Aufzählungstypen an? Liegt es unmittelbar hinter dem Namen einer Aufzählung? Ich sah Standard C++ 14 (n4296) §3.3.2/3:Deklarationspunkt für eine Enumeration

Der Punkt der Deklaration für eine Aufzählung ist unmittelbar nach dem Identifizierer (falls vorhanden), entweder in seiner ENUM-Spezifikator (7.2) oder dessen erstes undurchsichtigen-enum-Deklaration (7.2), je nachdem was zuerst

kommt aber, wenn ich versuche, es zu reproduzieren;

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

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

Ich habe einen Fehler auf allen Compilern bekam, obwohl ENUM-Basis zur Zählung E nach der Kennung gesetzt und muss sichtbar sein.

+1

Ich würde sagen, es ist bei der ';' (vor '// Fehler') der * Opak-Enum-Deklaration *. – Jarod42

+1

Also in 'CL ', 'E' ist in der Tat noch nicht deklariert :( – Jarod42

+1

Jarod42, aber warum ist es noch nicht erklärt? Standard sagt, dass es unmittelbar nach der Kennung ist, nicht wahr? Ich verstehe nicht es – user3514538

Antwort

13

Das Folgende;

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

Wird in einigen aktuellen Implementierungen nicht als gültige Deklaration akzeptiert (getestet: clang ++, g ++ und MSVC). Sie akzeptieren den noch nicht vollständigen Typ E in der enum-BaseCL<E>::UndType nicht. Der in den getesteten Implementierungen angegebene Fehler ist, dass E zu diesem Zeitpunkt undeclared ist. Sie scheinen den Punkt der Erklärung am Ende der enum-base zu platzieren, sie betrachten es als deklariert, sobald es abgeschlossen ist.

Beim Lesen der Spezifikationen;

§14.3.1/2 Template Typargumente

[Anmerkung: Eine Vorlagenart Argument kann einen unvollständigen Typ (3,9) sein. - Endnote]

Und

§7.2/6 Enumeration Erklärungen

Eine Aufzählung, deren zugrunde liegenden Typ befestigt ist, ist ein unvollständiger Typ von seinem Punkt der Deklaration (3.3.2) bis unmittelbar nach seiner enum-Basis (wenn überhaupt), an welchem ​​Punkt es ein vollständiger Typ wird.

Zeigt an, dass es kompilierbar ist; wie dies bei CRTP-Implementierungen der Fall ist.

Ich bin mir sicher, wenn dies (d. H. Der Fehler zu kompilieren enum class E : CL<E>::UndType;) ist die Absicht oder wenn es als ein Anwendungsfall angesehen wurde. Aus der Spezifikation wird der opaken Enum-Deklaration eine "spezielle" Behandlung gegeben. sein Basistyp und die Anforderung, dass es ein integraler Typ sein muss.

Vermutlich sollte der Code kompilierbar angesichts der Auflösung CWG#1482 sein.


Wie für aktuelle Problemumgehungen ...

Dies;

enum class E; // default underlying type is int 

Die minimale Deklaration.

Die undurchsichtige Deklaration könnte entweder sein;

enum class E : int; // int base 

Folgendes wäre eine vollständige Definition (einschließlich Enumeratoren);

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

Oder die Klassenvorlage zu verwenden, einen anderen Typ (möglicherweise void) verwendet werden könnten.

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

Von http: // en.cppreference.com/w/cpp/language/enum, der zugrunde liegende Typ ist Teil der Deklaration. 'enum class E' ist nur äquivalent zu' enum class E: int'. Und das Ändern von "UndType" zu "char" erzeugt sogar den Fehler [Demo] (http://coliru.stacked-crooked.com/a/1b7463cc118c5fd6). – Jarod42

+1

Es ist jetzt besser, aber der Teil über die * enum-base *, der "noch nicht vollständig" ist, ist immer noch nicht richtig. Es ist ein Alias ​​für "int", das ist alles; die Tatsache, dass "E" tatsächlich unvollständig ist, wenn "CL " implizit instanziiert wird, ist in diesem Fall irrelevant. – bogdan

+1

@bogdan. Richtig, ich denke, das ist der Kern der Sache, die Implementierungen sehen es nicht als vollständig an - ich denke, ich muss diesen Teil irgendwie umschreiben. Vielleicht so etwas wie "Sie akzeptieren den, noch nicht abgeschlossenen' E' Typ in der Basis 'CL :: UndType'."? – Niall