port boost.variant to D

今晚无聊,完整用D实现了Boost.Variant 的绝大部分,权当娱乐了。


1 // Module: variant.d
2 // Author: Oldrev (wstring#AT#gmail.com)
3 // License: BSD
4
5 module dust.meta.variant;
6
7 import std.typetuple;
8 import std.traits;
9
10 private template MaxSizeImp(T, V...)
11 {
12 static if(V.length > 0)
13 private const int tailResult = MaxSizeImp!(V).result;
14 else
15 private const int tailResult = T.sizeof;
16
17 public const int result = T.sizeof > tailResult ? T.sizeof : tailResult;
18 };
19
20 template MaxSize(TList...)
21 {
22 const int MaxSize = MaxSizeImp!(TList).result;
23 }
24
25 struct Variant(TList...)
26 {
27 public alias TList TypeList;
28 public alias Variant!(TypeList) SelfType;
29 private alias ubyte[MaxSize!(TypeList)] Holder;
30
31 private Holder m_held;
32 private int m_which = -1;
33
34 public int which()
35 {
36 return m_which;
37 }
38
39 public SelfType assign(ValueType)(ValueType val)
40 {
41 static if(is(ValueType == SelfType))
42 {
43 foreach(T; TypeList)
44 {
45 const int i = IndexOf!(T, TypeList);
46 if(val.which == i)
47 {
48 assign!(T)(val.get!(T));
49 m_which = i;
50 }
51 }
52 }
53 else
54 {
55 const int i = IndexOf!(ValueType, TypeList);
56 static assert(i >= 0);
57 ValueType* heldPtr = cast(ValueType*)m_held.ptr;
58 *heldPtr = val;
59 m_which = i;
60 }
61
62 return *this;
63 }
64
65 public SelfType opAssign(ValueType)(ValueType rhs)
66 {
67 return assign!(ValueType)(rhs);
68 }
69
70 public bool opEquals(ValueType)(ValueType rhs)
71 {
72 static if(is(ValueType == SelfType))
73 {
74 foreach(T; TypeList)
75 {
76 const int i = IndexOf!(T, TypeList);
77 if(i == which)
78 {
79 return (rhs.which == which) && (get!(T) == rhs.get!(T));
80 }
81 }
82 }
83 else
84 {
85 const int i = IndexOf!(ValueType, TypeList);
86 static assert(i >= 0);
87
88 ValueType* heldPtr = cast(ValueType*)m_held.ptr;
89 return *heldPtr == rhs;
90 }
91 }
92
93 public int opCmp(ValueType)(ValueType rhs)
94 {
95 if(rhs == *this)return 0;
96 static if(is(ValueType == SelfType))
97 {
98 foreach(T; TypeList)
99 {
100 const int i = IndexOf!(T, TypeList);
101 if((i == which) && (rhs.which == which))
102 {
103 return get!(T) < rhs.get!(T) ? -1 : 1;
104 }
105 }
106 }
107 else
108 {
109 const int i = IndexOf!(ValueType, TypeList);
110 static assert(i >= 0);
111
112 ValueType* heldPtr = cast(ValueType*)m_held.ptr;
113 return *heldPtr < rhs ? -1 : 1;
114 }
115 }
116
117 public TypeInfo type()
118 {
119 foreach(T; TypeList)
120 {
121 const int i = IndexOf!(T, TypeList);
122 if(i == which)
123 {
124 return typeid(TypeList[i]);
125 }
126 }
127 }
128
129 public ValueType get(ValueType)()
130 {
131 return *(cast(ValueType*)m_held.ptr);
132 }
133
134 public bool empty()
135 {
136 return m_which < 0;
137 }
138
139 public bool isKindOf(ValueType)(ValueType val)
140 {
141 const int i = IndexOf!(ValueType, TypeList);
142 static assert(i >= 0);
143 return which == i;
144 }
145
146 }
147
148 unittest
149 {
150 class Foo
151 {
152 public:
153 int n = 0;
154 int x = 0;
155 int y = 0;
156 int z = 0;
157
158 Foo opAssign(int rhs)
159 {
160 z = rhs;
161 return this;
162 }
163 }
164
165 Variant!(double, char, int, char[], Foo) v;
166 v = 2;
167 assert(v == 2);
168 v = 2.22;
169 assert(v == 2.22);
170 assert(v.type == typeid(double));
171 v = new Foo;
172 assert(v.type == typeid(Foo));
173 v.get!(Foo)() = 2;
174 assert(v.get!(Foo)().z == 2);
175 typeof(v) v2 = v;
176 assert(v2 == v);
177 assert(v <= 2);
178 v = cast(char[])"Foobar";
179 assert(v == cast(char[])"Foobar");
180
181 }

你可能感兴趣的:(Gmail)