2009-01-13 11 views
5

declaración using no parecen funcionar con el tipo de enumeraciónusando declaración con enum?

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

using Sample::Colour; 

no funciona !! ¿Necesitamos agregar usando la declaración para cada enumerador de tipo enum? como debajo de

using sample::Colour::RED; 
+0

¿Hay alguna otra manera de hacerlo? – yesraaj

+1

No es realmente relevante para su pregunta en sí, pero le recomiendo encarecidamente que no use identificadores mayúsculas para enumeraciones y constantes. Preprocessor #defines son usualmente mayúsculas en C/C++ y ellos -manclarán otros símbolos con el mismo nombre. –

+0

El uso de la resolución de alcance operator :: on enumeraciones (como en "sample :: Color :: RED") es una extensión específica del compilador, no estándar C++. – bk1e

Respuesta

10

Una clase no define un espacio de nombres, por lo tanto "usar" no es aplicable aquí.

Además, debe hacer que la enumeración sea pública.

Si usted está tratando de utilizar la enumeración dentro de la misma clase, he aquí un ejemplo:

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

    void foo(); 
} 

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

Y para acceder a ella desde fuera de la clase:

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

C++ estándar, 7.3. 3.1:

el nombre de usuario especificado en una declaración usando- se declara en el región declarativa en la que aparece la declaración de uso . [Nota: solo el nombre especificado es tan declarado; especificar una enumeración nombre en una declaración de uso no declarar sus enumeradores en declaración declarativa región. nota -fin]

+1

Estándar C++ o Una noche en la ópera? (Lo siento, no pude resistir). – Gorpik

+0

¿Podría explicarme este modismo, no soy muy fuerte en inglés? :) –

+2

No estoy seguro de que el estándar esté escrito en inglés. Se parece mucho a hablar de abogado :-) –

6

Para añadir a Stevela de answer, el problema con el código original es que se hace referencia a un miembro, pero el uso de la declaración no es en sí una declaración de miembro:

7.3.3/6 tiene:

Una declaración de uso para un miembro de clase será una declaración de miembro.

Para resaltar esto, el siguiente ejemplo funciona:

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

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

Por último, como se ha señalado por Igor Semenov here, aunque se mueva la definición de enumeración en un espacio de nombres, permitiendo así que el uso de la declaración, la declaración de uso solo declarará el nombre del tipo de enumeración en el espacio de nombre (La referencia estándar de 2003 es 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 
} 

tipos base dependientes

Para permitir especializaciones parciales y explícitos, cuando el compilador analiza una plantilla de clase que no realiza ninguna consulta en las clases de base dependientes. Como resultado, la siguiente variación con la Muestra como una plantilla no se compila:

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; 
    } 
}; 

El problema es que Derived::Colour se trata como un objeto por el compilador (14.6/2):

Se asume que un nombre utilizado en una declaración o definición de plantilla y que depende de un parámetro de plantilla no nombra un tipo a menos que la búsqueda de nombre aplicable encuentre un nombre de tipo o el nombre esté calificado por la palabra clave typename.

En cuanto a las dos condiciones para el nombre de un tipo:

  1. búsqueda de Colour no encuentra un tipo porque la base depende Sample<T> no se busca.
  2. El nombre no está calificado por typename

Por tanto, el ejemplo necesita el typename palabra clave:

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; 
    } 
}; 

Nota: La versión 98 de la norma no permitieron typename para ser utilizado con una declaración using y por lo tanto la corrección anterior no fue posible. Ver Accessing types from dependent base classes y CWG11.

+1

En su primer ejemplo, ¿puede explicar por qué la muestra _no_ funciona con 'plantilla clase Muestra' y' plantilla clase Derivada: muestra pública '? – imallett