c++ - ejemplo - typedef enum c
usando declaraciĆ³n con enum? (3)
Estándar de C ++, 7.3.3.1:
El nombre de miembro especificado en una declaración de uso se declara en la región declarativa en la que aparece la declaración de uso. [Nota: solo el nombre especificado es declarado así; la especificación de un nombre de enumeración en una declaración using no declara sus enumeradores en la región declarativa de la declaración de uso. -finalizar nota]
usar declaración no parece funcionar con el tipo enum
class Sample{
public:
enum Colour { RED,BLUE,GREEN};
}
using Sample::Colour;
¡¡No funciona!! ¿Necesitamos agregar usando declaración para cada enumerador de tipo enum? como abajo
using sample::Colour::RED;
Una clase no define un espacio de nombres, por lo tanto "usar" no es aplicable aquí.
Además, necesita hacer que la enumeración sea pública.
Si intentas usar la enumeración dentro de la misma clase, aquí hay un ejemplo:
class Sample {
public:
enum Colour { RED, BLUE, GREEN };
void foo();
}
void Sample::foo() {
Colour foo = RED;
}
Y para acceder desde fuera de la clase:
void bar() {
Sample::Colour colour = Sample::RED;
}
Para agregar a la respuesta de Stevela, el problema con el código original es que se refiere a un miembro, pero la declaración de uso no es en sí misma una declaración de miembro:
7.3.3 / 6 tiene:
Una declaración de uso para un miembro de la clase debe 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
};
Finalmente, como señala Igor Semenov aquí , incluso si mueve la definición enum a un espacio de nombres, permitiendo así la declaración using, la declaración using solo declarará el nombre del tipo enum en el espacio de nombres (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 de base dependientes
Para permitir especializaciones parciales y explícitas, cuando el compilador analiza una plantilla de clase no realiza ninguna búsqueda en clases base dependientes. Como resultado, la siguiente variación con Sample como 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
es tratado como un objeto por el compilador (14.6 / 2):
Se supone 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.
Mirando las dos condiciones para que el nombre sea un tipo:
- La búsqueda de
Colour
no encuentra un tipo porque no se busca la base dependienteSample<T>
. - El nombre no está calificado por
typename
Por lo tanto, el ejemplo necesita la palabra clave typename
:
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 permitía que typename
se utilizara con una declaración using y por lo tanto la corrección anterior no fue posible. Consulte Acceso a tipos de clases base dependientes y CWG11 .