2012-02-05 48 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