2010-03-18 13 views
25

Ho il seguente frammento di codice:Perché posso impostare un enum anonimo uguale a un altro in C ma non in C++?

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

che compilerà in C, ma in C++, ho il seguente errore:

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

Qualcuno può spiegarmi perché questo sta accadendo? Preferirei una risposta con alcune specifiche sul perché il compilatore si comporta in questo modo, piuttosto che "Non puoi farlo"

+3

Questa è una domanda brillantemente oscura. –

+2

Felice che ti piaccia! – samoz

+0

Ricorderò questo esempio quando qualcuno mi dice che usano enum perché impedisce di scrivere codice sbagliato. Fondamentalmente, C ti permette di scrivere codice. Se scrivi codice errato, hai un codice errato. L'uso dei cast impliciti è un codice errato e (alcuni) C a quanto pare ti consente di farlo, anche se è pessimo come in questo caso. Ulteriore domanda: è qualcosa che è stato hackerato nel compilatore per "supportare più pienamente" l'uso * err * dell'enum senza nome per creare costanti? Probabilmente così. –

risposta

33

Convertire da un tipo di enum a un altro passa per un tipo intero (probabilmente il tipo sottostante del fonte, non sono sicuro).

Una conversione implicita da enum a un tipo intero è consentita sia in C che in C++. Una conversione implicita da un tipo intero a enum è consentita in C, ma non in C++.

Fondamentalmente, il C++ è più sicuro di tipo. Sta cercando di fermare voi di fare questo:

enum {zero, one, two} x; 

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

Se si desidera eseguire questa conversione enum-enum in C++, è possibile utilizzare typeof/declspec/typeof spinta o equivalente. In GCC:

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

Tuttavia, non ha senso farlo. Per la maggior parte degli scopi, le enumerazioni (e in particolare quelle anonime) sono "tipi enumerati". Sono semplicemente "implementati" dagli standard C e C++ come numeri interi che indossano cappelli divertenti, ma ciò non significa che lo red sia "uguale a" hammer solo perché ognuno di essi appare prima in due enumerazioni diverse (colori e strumenti rispettivamente). static_cast suggerisce che esiste una relazione tra i due tipi coinvolti. Qualsiasi tipo di enumerazione è "correlato" dal fatto che entrambi hanno un tipo intero sottostante, e quelli sono correlati, quindi la "relazione" in realtà non dice molto. Se scrivi questo codice stai ottenendo una versione piuttosto scadente della sicurezza del tipo.

+0

Hai un sacco di punti da questo, quindi perché non controllare e menzionare se Boost TYPEOF (o qualche altro mezzo) è in grado di costruire l'espressione cast che sarebbe necessaria per assegnare qualsiasi tipo strani a una variabile enum anonima ... (modifica - Non ho installato Boost, scandaloso !, o ci proverei.) – Potatoswatter

+0

Abbastanza giusto. Non so perché vorresti farlo, però, se vuoi trattare un enum come un intero, non usare un enum anonimo :-) Sono bloccato su una vecchia versione di boost, non ha tipo , ma l'ho provato su g ++ e sembra felice di prendere un tipo anonimo. Non ho controllato se 'decltype' farà lo stesso. –

+0

L'unica ragione che ho mai visto per la necessità era per la serializzazione. L'enumerazione è serializzata come tipo intero e deserializzata prima in un tipo intero e poi in un enum ... L'ho sempre trovato scomodo, soprattutto perché lo scrittore aveva usato un tipo intero senza segno ... –

1

La mia ipotesi è che ciò sia dovuto alla tipizzazione più rigorosa in C++.

In C x = 5; compila anche. In C++ non perché non è stata definita alcuna conversione di tipo. Questa è la stessa ragione per cui x = y non viene compilato.

È possibile dare un'occhiata a this example on codepad, che fornisce una descrizione di errore più dettagliata del compilatore.

0

Il compilatore non sa come convertire implicitamente un tipo di dati enumerato in un altro.

Provare quanto segue.

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

Mi occupo principalmente di enumerazioni anonime, non di nomi. – samoz

+0

@samoz: la risposta è la stessa indipendentemente dal fatto che le enumerazioni siano o meno nominate. Hai creato due nuovi tipi di dati e il compilatore non sa come convertire implicitamente uno in un altro, quindi l'errore. – semaj

Problemi correlati