2012-02-05 51 views
5

我在設計D應用程序時遇到了麻煩。也許我的方法是完全錯誤的,所以我來這裏是爲了拯救我。任何建議,包括完整的重寫,都是值得歡迎的。處理D模板結構作爲常見類型

我有一些模板類型:

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

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

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

,我需要一般處理這些類型:

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); 

如何實現這樣的效果? 編輯:面向對象的替代品也受到歡迎。

回答

6

我會用一個標籤聯合自己

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; 
    } 
} 

注意,有沒有靜態(編譯時間)他們之間的差異,但它在相當多的情況下儘量繼承可以做

您可以添加一些額外的功能,所以它看起來更像繼承,所以你不需要在結構的函數之外檢查類型字段太多

+0

如何爲它添加函數看起來更像繼承?少檢查會更好。我喜歡你從爭論中推斷出這種類型的方式,在這裏很合適。 – 2012-02-06 01:08:36

+1

函數裏面你可以做'final Type(Type){case Type.Integer:... case Type.Message:...}'處理函數。我的意思是(大部分)這些檢查將在結構的定義內部居中,這樣當你想要添加一個類型時,你不需要全部搜索它們。 – 2012-02-06 01:15:16

+0

謝謝,現在我正在使用'final switch'爲了它。 – 2012-02-06 05:47:26

4

你可以使用std.variant。

我無法想象另一種方式。最後它們是完全獨立的類型。

+1

我在使用'std.variant'而不是構建我自己的標記聯盟方面有一些優勢嗎? – 2012-02-05 16:30:56

2

如果你確實需要保留原始結構,那麼你可以創建一個類的層次結構,指針到一個結構並相應地發送。

+0

不,我不需要保留結構。關於包裝受保護的聯盟的類層次結構怎麼樣?將會有_many_小的令牌,只有幾個或零個副本。 – 2012-02-07 01:03:35