2009-01-13 41 views
5

Erklärung mit scheint nicht mit Aufzählungstyp zu arbeitenmit Deklaration mit enum?

class Sample{ 
public: 
enum Colour { RED,BLUE,GREEN}; 
} 

using Sample::Colour; 

funktioniert nicht !! müssen wir mit Deklaration für alle Enumeratoren des Enum-Typs hinzufügen? wie unter

using sample::Colour::RED; 
+0

Gibt es einen anderen Weg, dies zu tun – yesraaj

+1

Nicht wirklich relevant für Ihre Frage per se, aber ich würde Ihnen dringend empfehlen, nicht alle Großbuchstaben Bezeichner für Enums und Konstanten zu verwenden. Präprozessor-#defines sind in C/C++ in der Regel nur in Großbuchstaben, und sie werden andere Symbole mit demselben Namen bearbeiten. –

+0

Die Verwendung des Scope-Auflösungsoperators :: on enums (wie in "sample :: Color :: RED") ist eine Compiler-spezifische Erweiterung, nicht Standard C++. – bk1e

Antwort

10

Eine Klasse definiert keinen Namespace, daher ist "using" hier nicht anwendbar.

Auch müssen Sie die Enum veröffentlichen.

Wenn Sie die Enum innerhalb der gleichen Klasse zu verwenden sind versuchen, hier ein Beispiel:

class Sample { 
public: 
    enum Colour { RED, BLUE, GREEN }; 

    void foo(); 
} 

void Sample::foo() { 
    Colour foo = RED; 
} 

Und es aus, ohne die Klasse zugreifen:

void bar() { 
    Sample::Colour colour = Sample::RED; 
} 
5

C++ Standard 7.3. 3.1:

der Elementname angegeben in einer using-Deklaration in denerklärtdeklarative Region, in der die using-Deklaration angezeigt wird. [Hinweis: Nur der angegebene Name ist so deklariert; Angeben einer Aufzählung Name in einer using-Deklaration nicht deklarieren seine Enumeratoren in derusing-Deklaration deklarativen Region. -Ende note]

+1

C++ Standard oder Eine Nacht in der Oper? (Entschuldigung, konnte nicht widerstehen). – Gorpik

+0

Können Sie mir dieses Idiom erklären, ich bin nicht sehr stark in Englisch? :) –

+2

Ich bin mir nicht sicher, ob der Standard in Englisch geschrieben ist. Sieht sehr nach Anwalt aus :-) –

6

zu Stevela des hinzuzufügen answer, das Problem mit dem Original-Code ist, dass Sie auf ein Mitglied beziehen, aber die Verwendung von Erklärung ist nicht selbst Mitglied Erklärung:

7.3.3/6 hat:

Eine Verwendungsdeklaration für ein Klassenmitglied soll eine Member-Deklaration sein.

Um dies zu unterstreichen, wird das folgende Beispiel funktioniert:

class Sample 
{ 
public: 
    enum Colour { RED,BLUE,GREEN}; 
}; 

class Derived : public Sample 
{ 
public: 
    using Sample::Colour; // OK 
}; 

Schließlich wird, wie von Igor Semenov here wies darauf hin, auch wenn Sie die Enum-Definition in einem Namensraum zu bewegen, wodurch die Verwendung Erklärung erlaubt, Die using-Deklaration deklariert den Namen des enum-Typs nur in den Namespace (Die Standardreferenz von 2003 ist 7.3.3/2).

namespace Sample 
{ 
    enum Colour { RED,BLUE,GREEN}; 
} 

using Sample::Colour; 
using Sample::BLUE; 


void foo() 
{ 
    int j = BLUE; // OK 
    int i = RED; // ERROR 
} 

Dependent Basistypen

für Teil- und explizite Spezialisierungen zu ermöglichen, wenn der Compiler eine Klassenvorlage analysiert es keine Lookups in den abhängigen Basisklassen durchführt. Als Ergebnis, wird die folgende Variante mit Probe als Template nicht kompiliert:

template <typename T> 
class Sample 
{ 
public: 
    enum Colour { RED,BLUE,GREEN}; 
}; 

template <typename T> 
class Derived : public Sample<T> 
{ 
public: 
    using Sample<T>::Colour; // What kind of entity is Colour? 

    Colour foo()  // Not OK! 
    { 
    return this->RED; 
    } 
}; 

Das Problem ist, dass Derived::Colour als ein Objekt durch den Compiler behandelt wird (14.6/2):

Ein Name in einer Template-Deklaration oder Definition verwendet und das ist abhängig von einem Template-Parameter wird angenommen, dass keine Art zu nennen, es sei denn die entsprechenden Name-Lookup einen Typnamen findet oder der Namen qualifiziert nach dem Schlüsselwort typename.

Betrachtet man die beiden Bedingungen für die Namen ein Typ zu sein:

  1. Lookup für Colour keine Art finden, weil die abhängige Basis Sample<T> nicht gesucht wird.

    template <typename T> 
    class Derived : public Sample<T> 
    { 
    public: 
        using typename Sample<T>::Colour; // Colour is treated as a typedef-name 
    
        Colour foo() // OK 
        { 
        return this->RED; 
        } 
    }; 
    

    Hinweis: Die '98 Version des Standards nicht erlauben typename verwendet werden

  2. Der Name von ist typename

Das Beispiel muss daher die typename Schlüsselwort nicht qualifiziert mit einer using-Deklaration und so war der obige Fix nicht möglich. Siehe Accessing types from dependent base classes und CWG11.

+1

In Ihrem ersten Beispiel, können Sie erklären, warum das Beispiel _not_ arbeitet mit 'Vorlage Klasse Sample' und' Vorlage Klasse abgeleitet: öffentliche Beispiel '? – imallett