2012-02-05 8 views
5

Sono in difficoltà nella progettazione di un'app D. Forse il mio approccio è completamente sbagliato, quindi vengo qui per salvarmi. Qualsiasi suggerimento, inclusa la riscrittura completa, è il benvenuto.Gestione di strutture con modelli D come tipo comune

Ho alcuni tipi templated:

enum Type : byte { Message='!', Integer='@' } 

struct Token (T) { 
    Type type; 
    T value; 
} 

alias Token!string MessageToken; 
alias Token!long IntegerToken; 

E ho bisogno di gestire questi tipi genericamente:

AnyToken genToken(bool cond) { 
    if (cond) 
    return MessageToken(Type.Message, "nighly builds"); 
    else 
     return IntegerToken(Type.Integer, -42); 
} 

AnyToken a = genToken(true); 
AnyToken b = genToken(false); 

Come faccio a ottenere questo effetto? Modifica: Anche le alternative OOP sono benvenute.

risposta

6

avrei utilizzato un'unione etichettato me

struct Token{ 
    Type type; 
    union{ 
     string str; 
     long integer; 
    } 
    @property string strMessage()in{assert(type==Type.Message)}body{ 
     return str; 
    } 
    @property void strMessage(string s){ 
     type=Type.Message; 
     str=s; 
    } 
    @property long intMessage()in{assert(type==Type.Integer)}body{ 
     return integer; 
    } 
    @property void intMessage(long l){ 
     type=Type.Integer; 
     integer=l; 
    } 
} 

nota che non c'è statico (tempo di compilazione) differenza tra di loro, ma è praticamente il migliore può fare a meno di successione

è possibile aggiungere alcune funzioni extra quindi assomiglia più all'ereditarietà, quindi non è necessario esaminare il campo tipo tanto fuori dalle funzioni della struttura

+0

Come posso aggiungere funzioni perché assomiglia più all'ereditarietà? Meno esami saranno migliori. Mi piace il modo in cui deduci il tipo dall'argomento, si adatta bene qui. –

+1

all'interno della funzione è possibile eseguire l'opzione finale (tipo) {caso Tipo.Intero: ... caso Tipo.Messaggio: ...} 'Gestisci la funzione. Intendevo che (la maggior parte) quegli assegni sarebbero stati centrati all'interno della definizione della struttura in modo tale che quando si desidera aggiungere un tipo non si debbano cacciarli tutti giù –

+0

Grazie, ora sto usando l'opzione finale per questo. –

4

È possibile utilizzare std.variant.

Non riesco a immaginare un altro modo. Alla fine sono tipi completamente separati.

+1

Avrei qualche vantaggio nell'usare 'std.variant' invece di costruire la mia unione con tag? –

2

Se è davvero necessario mantenere le strutture originali, è possibile creare una gerarchia di classi che avvolgano un pointer a una struttura e una spedizione di conseguenza.

+0

No, non ho bisogno di mantenere le strutture. Che dire di una gerarchia di classi che avvolge un'unione protetta? Ci saranno molti piccoli token con poche o zero copie. –

Problemi correlati