2015-12-16 13 views
5

Betrachten Sie die folgende C++ Aufzählungen lösen:Wie Compiler Enum Neudeklaration Konflikt

enum Identity 
{ 
    UNKNOWN = 1, 
    CHECKED = 2, 
    UNCHECKED = 3 
}; 

enum Status 
{ 
    UNKNOWN = 0, 
    PENDING = 1, 
    APPROVED = 2, 
    UNAPPROVED = 3 
}; 

Der Compiler kollidierten die beiden UNKNOWN Artikel und warf diesen Fehler:

error: redeclaration of 'UNKNOWN'

Ich bin in der Lage, diesen Fehler zu lösen eine Veränderung von UNKNOWN bis UNKNOWN_a, aber ich möchte die Namen nicht ändern.

Wie kann ich diesen Konflikt lösen ohne Ändern der enum Artikel Name?

Antwort

11

Sie können hierfür scoped enumerations verwenden. Dies erfordert C++ 11 oder höhere Unterstützung.

enum class Identity 
{ 
     UNKNOWN = 1, 
     CHECKED = 2, 
     UNCHECKED =3 
}; 

enum class Status 
{ 
     UNKNOWN = 0, 
     PENDING = 1, 
     APPROVED = 2, 
     UNAPPROVED =3 
}; 

int main() 
{ 
    Identity::UNKNOWN; 
    Status::UNKNOW; 
} 

Live Example

4

Verwendung Bereich enum s (C++ 11) - enum class es. Sie werden den äußeren Geltungsbereich nicht mit doppelten Namen verschmutzen.

Aber Sie müssen Zugriff auf die aufgezählten Werte mit einem Scope-Auflösung-Operator - Identity::UNKNOWN, die nicht eine schlechte Sache ist.

3

Wenn 11 unter Verwendung von C++ nicht möglich ist (es sollte wirklich jetzt, ich meine, es ist schon 2015), sollten Namespaces:

namespace Identity { 
enum { 
     UNKNOWN = 1, 
     CHECKED = 2, 
     UNCHECKED =3 
}; 
} 

namespace Status { 
enum { 
     UNKNOWN = 0, 
     PENDING = 1, 
     APPROVED = 2, 
     UNAPPROVED =3 
}; 
} 

Aber , wirklich, enum class ist viel besser.

+0

Funktioniert nicht wie es ist, wenn Sie einen als Parameter haben möchten. – chris

+0

@chris Ich bin mir bewusst. Dies ist eines der Probleme, die 'enum-Klasse' nicht einfach zu verwenden. Ich meine, du könntest die enums immer noch mit einem Namen deklarieren ('enum value {/*...*/') und sie wie 'void foo (Identity :: value)' verwenden, aber du verlierst immer noch die Vorteile von type Sicherheit, etc. –

+0

Nun, die lustige Sache ist, dass C++ 11 ist ziemlich häufig nicht möglich, besonders im kommerziellen Bereich - zum Beispiel viele Kunden des Unternehmens, für das ich arbeite, sind immer noch alte Systeme wie RHEL und nicht wollen Upgraden, solange das System gut läuft (es kommt häufig vor, dass beim Release-Upgrade schwerwiegende Inkompatibilitäten auftreten). Als Ergebnis ist C++ 11 verboten und alles muss auch in älteren Compilern erstellt werden. In der Tat war C++ 11 in jedem der letzten 4 Unternehmen, für die ich arbeitete, verboten. Und eine Firma, für die ich vorher gearbeitet habe, ist AFAIK, die auch noch in MSVC 6 baut :-) – axalis

2

Dies ist, wie ich in der Regel solche Aufzählungen erklären würde (wenn ich etwas mehr Phantasie nicht benötigen, wie die automatischen Umwandlungen des Enum-Namen in Zeichenfolge, Serialisierung/Deserialisierung etc.):

struct Identities 
{ 
    enum Type 
    { 
     UNKNOWN = 1, 
     CHECKED = 2, 
     UNCHECKED = 3 
    }; 
}; 

typedef Identities::Type Identity; 

struct States 
{ 
    enum Type 
    { 
     UNKNOWN = 0, 
     PENDING = 1, 
     APPROVED = 2, 
     UNAPPROVED = 3 
    }; 
}; 

typedef States::Type Status; 

// usage 
Identity identity = Identities::UNKNOWN; 
Status status = States::UNKNOWN; 

Werke in jede C++ - Version und ist ebenfalls typsicher. Namespaces können auch anstelle von structs verwendet werden (aber normalerweise verwende ich structs).