Newsgroup: it.comp.lang.c++
Titolo: UNION - inesperto cerca aiuto.

Buon c++ a tutti. Vorrei porvi una domanda da principiante - dove
possono trovare impiego le Unioni? non riesco ad
immaginarmelo dato che, da quanto ho capito, nelle unioni le componenti si
sovrappongono,
distruggendo i valori precedentemente memorizzati.
Grazie 1000.
Francesco
gi...@tin.it

possono trovare impiego le Unioni? 
Un tipico uso delle union lo si ha in casi in cui e` importante
minimizzare l'uso di ram. In casi di questo tipo piu` tipi di variabili
vengono appunto raccolte insieme tramite union.
Ovviamente perche` la cosa funzioni e` necessario che
quando si scriva un valore nella union tramite un certo membro,
un eventuale precedente valore non sia piu` necessario 
anche se scritto tramite altro membro della union.
Paolo
-----------------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
-----------------------------------------------------------------


Lo union e' un costrutto quasi inutile in C++.
Stroustrup sconsiglia il loro uso.
Linguaggi piu' recenti come Java non li supportano.
Non esiste nessun equivalente in Eiffel.
Esistono costrutti equivalenti in FORTAN ,COBOL e Pascal.
un'uso molto noto degli union lo trovi nei VARIANT.
Un VARIANT e' definito piu' o meno cosi':
typedef struct tagVARIANT
{
    VARTYPE vt;
union value
    {
    LONG lVal;
    BYTE bVal;
    SHORT iVal;
    FLOAT fltVal;
    DOUBLE dblVal;
    ...
    }
}VARIANT;
un VARIANT puo' contenere uno e un solo valore di uno dei tipi supportati
Se quindi hai bisogno di un vettore di 50 variabili senza curarti di che
tipo queste siano, puoi scrivere:
VARIANT var_array[50];
Devi gestire il tipo tramite la variabile membro tagVARIANT::vt;
I VARIANT sono nati in OLE Automation per comunicare valori
con linguaggi di scripting non tipizzati (come VBA).
In C++ potresti ottenere un meccanismo equivalente costruendo una gerarchia
di classi usando l'idioma envelope/letter come presentato da Coplien,
leggermente modificato con l'uso dei template.
Ad esempio:
definisci un'interfaccia base.
per semplicita' verranno definite le funzioni menbro
per la gestione di bool e float.
altri tipi di dato sono equivaluenti.
class variant_base
{
public:
    ...
    operator bool() const;
    operator float() const;
    ...
protected:
    virtual bool as_bool(void) const = 0;
    virtual float as_float(void) const = 0;
    virtual ~variant_base();
};
implementi i metodi virtuali per la template classe che gestisce il valore
(classe letter)...
Tale classe parametrizzata ti permette, con un sola implementazione, di
gestire diversi tipi di dato.
Inoltre garantisci che la conversione tra tipi imcompatibili
(es: int e std::string) dia errore a compile-time.
template <class T>
class variant_value : variant_base
{
    T value;
...
public:
    variant_value(const T& t) : value (t){}
    template <class T2>
        variant_value(const variant_value<T2>& var) : value (var.value){}
    variant_value& operator= (const T& t) {value = t; return *this;}
    template <class T2>
        variant_value& operator= (const variant_value<T2>& var)
            {value = var.value; return *this;}
    virtual bool as_bool(void) const
    {
        return value;
    }
    virtual float as_float(void) const
    {
        return value;
    }
...
};
funzione di utilita' che ci permette di istanziare un
oggetto variant_value<...> senza esplicitare
il parametro del template...
typedef auto_ptr<variant_base> variant_ptr;
static template<class T> variant_ptr create_variant(T t)
{
    return variant_ptr(new variant_value<T> (t) );
}
definisci la classe wrap (envelope)...
class variant : public variant_base
{
...
    variant_ptr pvariant_value
public:
    variant (bool b): pvariant_value(create_value(b))
    {
    }
    variant (float f) : pvariant_value(create_value(f))
    {
    }
    variant (const variant& var): pvariant_value (var.pvariant_value)
    {
    }
    variant& operator= (bool b)
    {
        pvariant_value = create_variant(b);
        return *this;
    }
    variant& operator= (float f)
    {
        pvariant_value = create_variant(f);
        return *this;
    }
protected:
    virtual bool as_bool(void) const
    {
        return (bool)(*pvariant_value);
    }
    virtual float as_float(void) const
    {
        return (float)(*pvariant_value);
    }
...
};
cosě, ora puoi creare un'array di tipi di dati diversi:
std::vector<variant> vec(50);
vec[0] = 3.4;
vec[1] = true;
vec[2] = "It's a kind of magic";
....
la struttura presentata potrebbe essere migliorata, definendo
la classe template come classe innestata e privata della classe
variant, ecc.
Oreste Notelli.