Newsgroup: it.comp.lang.c++
Titolo: stampare un valore di tipo enum

Dati:
enum TipoEnum {zero, uno, due}
TipoEnum tipoEnum;
tipoEnum = uno;
Un:
cout << tipoEnum;
Stampa "1".
E` possibile far stampare "uno"?


if ( tipoEnum == uno )
  cout << "uno";
else if...
Oppure variazioni piu' o meno sofisticate sul tema. Un modo "automatico"
non esiste.
Ciao,
Nicola


Risposta breve: non direttamente.
Risposta piu' articolata: ridefinisci l'operatore << per il tipo "TipoEnum".
Esempio:
std::ostream& operator <<( std::ostream& _os, const TipoEnum& _tipo ) {
    switch( _tipo ) {
        case zero:
            _os << "zero";
        case uno:
            _os << "uno";
        case due:
            _os << "due";
    }
    return _os;
};

     switch( _tipo ) {
Brrr.... Le variabili con l'underscore iniziale rendono il codice 
illeggibile quando ce ne sono un bel po...
E VAI DI MEGA-AZIMUTH-THREAD ORA!!! :)
-- 
Luc.


:-D
*** Azimuth ***

illeggibile quando ce ne sono un bel po...
Soprattutto sono riservate.
-- 
Marco Barisione (ICQ 84277092)

 Soprattutto sono riservate.
Ma non erano solamente gli identificatori con _due_ underscore iniziali, ad
essere riservati ?

essere riservati ?
Sono sempre riservati i nomi che contengono due underscore e quelli
che iniziano per underscore + lettera maiuscola.
Invece i nomi che iniziano per underscore + lettera minuscola o numero
o niente (cioč solo l'underscore) sono riservati solo nel namespace
globale. Quindi in questo caso in effetti mi pare si possono usare.
Ovviamente potrei aver detto cavolate visto che le regole sono un po'
macchinose.


 "automatico" non esiste.
Se a qualcuno interessa, tempo fa ho preparato uno scriptino Perl che
leggendo la dichiarazione di un enum genera il codice C++ per tradurre un
valore nella sua rappresentazione come stringa, o anche ricavare il valore
partendo da una stringa. La prima cosa è comoda per il logging, la
seconda, ad esempio, per la lettura di un file di configurazione.
Lo script non incorpora un vero parser C++, quindi richiede un *minimo* di
collaborazione da parte di chi scrive la dichiarazione.
Max

 [snip]
Thanks

 di collaborazione da parte di chi scrive la dichiarazione.
scommetto che questo funziona, vero?
template<int a, int b>
struct bar {
  static const int res = a-b;
};
template<int a, int b>
struct foo {
  static const int res = bar<a, 1>::res * b;
};
enum dummy {
  a = foo<1,1>::res,
  b = foo<22,5>::res,
  c = foo<123, 4>::res
};
:-)))
ciao Anto
-- 
"Computer science is not about computers any more than astronomy
is about telescopes." -- EW Dijkstra

 
Beh, sě. Al mio script basta identificare i *nomi*. I valori vengono
ignorati. Infatti, basta conoscere i nomi per generare le due routine che
ci servono: una che restituisce i valori a, b o c quando riceve "a", "b" o
"c" e una che fa il contrario.
Se gli passo il tuo codice, il mio script prouce questo header
 namespace enum_values { namespace dummy {
 int from_name( const char* ptr );
 const char* from_value( ::dummy val, bool qualified = false );
 }  }
 inline std::ostream& operator<<( std::ostream& out, ::dummy val )
 { return out << enum_values::dummy::from_value(val); }    
e un .ccp che implementa le due funzioni.
Lo script si incasina se, ad esempio, i valori contegnono '='.  :-)
Ad esempio:
 enum { a = 1==2 }
Max


 Soprattutto sono riservate.
Secondo lo standard...?
*** Azimuth ***

 writes:

Si, quando sono nel global scope.  Sono ammesse e.g. come nome dei
membri di una classe, e quindi con scope ristretto.
Piu' esattamente (ISO/IEC 14882-1998 17.4.3.1.2): identifiers che
contengono un doppio underscore o iniziano per singolo underscore
seguito da maiuscola sono comunque riservate all'implementazione;
identifiers che iniziano per singolo underscore non seguito da
maiuscola sono riservati all'implementazione nel namespace globale.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Dept. of Physics, Univ. of Padova, Italy          loreti at pd dot infn dot it

 "a", "b" o "c" e una che fa il contrario.
ah, ecco dove era l'inghippo :-))


questo funziona (gcc 2.95.3) anche se non bellissimo:
// --------------------------------------------------
// --------------------------------------------------
// --------------------------------------------------
#include <iostream>
class TipoEnum;
ostream & operator << (ostream & ccc, const TipoEnum & value);
enum TipoEnum_Imp {uno, due, tre };
class TipoEnum
{
   static char *names[];
public:
   TipoEnum (TipoEnum_Imp val) : value(val) {}
   friend ostream & operator << (ostream & ccc, const TipoEnum & value);
private:
   TipoEnum_Imp value;
   const char* name () const { return names[value]; }
};
ostream & operator << (ostream & ccc, const TipoEnum & value)
{
   ccc << 
value.name
();
}
char * TipoEnum::names[] = {"uno","due","tre" };
int main ()
{
    TipoEnum tipoEnum = uno;
    cout << tipoEnum << endl;
    return 0;
}
// --------------------------------------------------
// --------------------------------------------------
// --------------------------------------------------
Una cosa più generica che puoi fare è un classe che mappa valore-stringa 
(valore non necessariamente intero). E registrare (anche a runtime) le 
coppie. Stai solo attento a cosa metti nell'interfaccia: ovvero, se 
inserisci entrambi i cast automatici al "tipo del valore" (enum qui 
sopra) e alle stringhe poi cout non sa cosa chiamare.
ciao
