2010-03-18 20 views
25

Tengo el siguiente fragmento de código:¿Por qué puedo establecer una enumeración anónima igual a otra en C pero no en C++?

enum { one } x; 
enum { two } y; 
x = y; 

que recopilará en C, pero en C++, me sale el siguiente error:

test.c:6: error: cannot convert ‘main()::<anonymous enum>’ to ‘main()::<anonymous enum>’ in assignment 

Puede alguien explicarme por qué está sucediendo esto? Preferiría una respuesta con algunos detalles sobre por qué el compilador se comporta de esta manera, en lugar de simplemente "No se puede hacer eso"

+3

Esta es una pregunta brillantemente oscura. –

+2

¡Me alegro de que lo disfrutes! – samoz

+0

Voy a recordar este ejemplo cuando alguien me dice que usa enum porque evita escribir código incorrecto. Básicamente, C te permite escribir código. Si escribe un código incorrecto, tiene un código incorrecto. Usar moldes implícitos es un código incorrecto, y (algunos) C aparentemente te permite hacerlo, aunque sea tan malo como este caso. Pregunta adicional: ¿Esto está pirateado en el compilador para "soportar más completamente" el * mis * uso de enum sin nombre para crear constantes? Probablemente. –

Respuesta

33

La conversión de un tipo de enumeración a otro pasa por un tipo entero (probablemente el tipo subyacente del fuente, no estoy seguro).

Se permite una conversión implícita de enum a un tipo entero tanto en C como en C++. Se permite una conversión implícita de un tipo entero a enum en C, pero no en C++.

Básicamente, C++ está siendo más seguro. Se trata de intentar que le impida hacer esto:

enum {zero, one, two} x; 

x = 143; // assigns a value outside the range of the enum 

Si desea realizar esta conversión enumeración-enum en C++, se puede usar typeof/declspec/typeof impulso o equivalente. En GCC:

int main() { 
    enum {zero, one, two} x; 
    enum {zero1, one1, two1} y = two1; 
    typedef typeof(x) xtype; 
    x = static_cast<typeof(x)>(y); 
} 

Sin embargo, normalmente no tiene sentido hacerlo. Para la mayoría de los propósitos, las enumeraciones (y especialmente las anónimas) son "tipos enumerados". Simplemente resultan ser "implementados" por los estándares C y C++ como enteros usando sombreros divertidos, pero eso no significa que red es "igual a" hammer simplemente porque cada uno aparece primero en dos enumeraciones diferentes (colores y herramientas respectivamente)) static_cast sugiere que hay una relación entre los dos tipos involucrados. Dos tipos de enum están "relacionados" por el hecho de que ambos tienen un tipo entero subyacente y están relacionados, por lo que la "relación" realmente no dice mucho. Si escribe este código, obtendrá una versión bastante pobre de seguridad tipo.

+0

Tiene un montón de puntos, así que ¿por qué no verificar y mencionar si Boost TYPEOF (u otro medio) es capaz de construir la expresión de conversión que sería necesaria para asignar cualquier tipo de letra extranjera a una variable enum anónima ... (Editar - No tengo Boost instalado, ¡escandaloso !, o lo intentaría) – Potatoswatter

+0

Lo suficiente. Sin embargo, no estoy seguro de por qué querría hacerlo, si quiere tratar una enumeración como un entero, no use una enumeración anónima :-) Estoy atascado en una versión anterior de boost, no tengo typeof , pero lo probé en g ++ y parece feliz tomar un tipo anónimo. No he comprobado si 'decltype' hará lo mismo. –

+0

La única razón por la que he visto la necesidad era por la serialización. La enumeración que se serializa como tipo entero y se deserializa primero en un tipo entero y luego enum ... Siempre me ha parecido incómodo, especialmente porque el escritor había usado un tipo entero sin signo ... –

1

Supongo que esto se debe a la tipificación más estricta en C++.

En C x = 5; también se compila. En C++ no lo hará porque no hay una conversión de tipo definida. Esa es la misma razón por la cual x = y no compila.

Puede echar un vistazo a this example on codepad, que ofrece una descripción de error más detallada que su compilador.

0

El compilador no sabe cómo convertir implícitamente un tipo de datos enumerados a otro.

Intente lo siguiente.

enum typeX { one } x; 
enum typeY { two } y; 
x = (typeX) y; 
+0

Me preocupan principalmente las enumeraciones anónimas, sin nombrarlas. – samoz

+0

@samoz - La respuesta es la misma independientemente de si las enumeraciones son nombradas o no. Ha creado dos nuevos tipos de datos y el compilador no sabe cómo convertir implícitamente uno a otro, por lo tanto, el error. – semaj

Cuestiones relacionadas