|
1 /* -*- C++ -*- |
|
2 * |
|
3 * This file is a part of LEMON, a generic C++ optimization library |
|
4 * |
|
5 * Copyright (C) 2003-2006 |
|
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport |
|
7 * (Egervary Research Group on Combinatorial Optimization, EGRES). |
|
8 * |
|
9 * Permission to use, modify and distribute this software is granted |
|
10 * provided that this copyright notice appears in all copies. For |
|
11 * precise terms see the accompanying LICENSE file. |
|
12 * |
|
13 * This software is provided "AS IS" with no warranty of any kind, |
|
14 * express or implied, and with no claim as to its suitability for any |
|
15 * purpose. |
|
16 * |
|
17 */ |
|
18 |
|
19 #ifndef LEMON_BITS_VARIANT_H |
|
20 #define LEMON_BITS_VARIANT_H |
|
21 |
|
22 #include <lemon/error.h> |
|
23 |
|
24 namespace lemon { |
|
25 |
|
26 template <bool left, bool right> |
|
27 struct CTOr { |
|
28 static const bool value = true; |
|
29 }; |
|
30 |
|
31 template <> |
|
32 struct CTOr<false, false> { |
|
33 static const bool value = false; |
|
34 }; |
|
35 |
|
36 template <bool left, bool right> |
|
37 struct CTAnd { |
|
38 static const bool value = false; |
|
39 }; |
|
40 |
|
41 template <> |
|
42 struct CTAnd<true, true> { |
|
43 static const bool value = true; |
|
44 }; |
|
45 |
|
46 template <int left, int right> |
|
47 struct CTEqual { |
|
48 static const bool value = false; |
|
49 }; |
|
50 |
|
51 template <int val> |
|
52 struct CTEqual<val, val> { |
|
53 static const bool value = true; |
|
54 }; |
|
55 |
|
56 |
|
57 template <int left, int right> |
|
58 struct CTLess { |
|
59 static const bool value = left < right; |
|
60 }; |
|
61 |
|
62 template <int left> |
|
63 struct CTLess<left, 0> { |
|
64 static const bool value = false; |
|
65 }; |
|
66 |
|
67 template <int right> |
|
68 struct CTLess<0, right> { |
|
69 static const bool value = true; |
|
70 }; |
|
71 |
|
72 template <> |
|
73 struct CTLess<0, 0> { |
|
74 static const bool value = false; |
|
75 }; |
|
76 |
|
77 template <> |
|
78 struct CTLess<1, 1> { |
|
79 static const bool value = false; |
|
80 }; |
|
81 |
|
82 template <bool less, int left, int right> |
|
83 struct CTMaxImpl { |
|
84 static const int value = left; |
|
85 }; |
|
86 |
|
87 template <int left, int right> |
|
88 struct CTMaxImpl<true, left, right> { |
|
89 static const int value = right; |
|
90 }; |
|
91 |
|
92 template <int left, int right> |
|
93 struct CTMax { |
|
94 static const int value = |
|
95 CTMaxImpl<CTLess<left, right>::value, left, right>::value; |
|
96 }; |
|
97 |
|
98 |
|
99 /// \brief Simple Variant type with two type |
|
100 /// |
|
101 /// Simple Variant type with two type |
|
102 template <typename _First, typename _Second> |
|
103 class BiVariant { |
|
104 public: |
|
105 |
|
106 typedef _First First; |
|
107 typedef _Second Second; |
|
108 |
|
109 struct WrongStateError : public lemon::LogicError { |
|
110 public: |
|
111 virtual const char* what() const throw() { |
|
112 return "lemon::BiVariant::WrongStateError"; |
|
113 } |
|
114 }; |
|
115 |
|
116 BiVariant() { |
|
117 flag = true; |
|
118 new(reinterpret_cast<First*>(data)) First(); |
|
119 } |
|
120 |
|
121 BiVariant(const First& first) { |
|
122 flag = true; |
|
123 new(reinterpret_cast<First*>(data)) First(first); |
|
124 } |
|
125 |
|
126 BiVariant(const Second& second) { |
|
127 flag = false; |
|
128 new(reinterpret_cast<Second*>(data)) Second(second); |
|
129 } |
|
130 |
|
131 BiVariant(const BiVariant& bivariant) { |
|
132 flag = bivariant.flag; |
|
133 if (flag) { |
|
134 new(reinterpret_cast<First*>(data)) First(bivariant.first()); |
|
135 } else { |
|
136 new(reinterpret_cast<Second*>(data)) Second(bivariant.second()); |
|
137 } |
|
138 } |
|
139 |
|
140 ~BiVariant() { |
|
141 destroy(); |
|
142 } |
|
143 |
|
144 BiVariant& setFirst() { |
|
145 destroy(); |
|
146 flag = true; |
|
147 new(reinterpret_cast<First*>(data)) First(); |
|
148 return *this; |
|
149 } |
|
150 |
|
151 BiVariant& setFirst(const First& first) { |
|
152 destroy(); |
|
153 flag = true; |
|
154 new(reinterpret_cast<First*>(data)) First(first); |
|
155 return *this; |
|
156 } |
|
157 |
|
158 BiVariant& setSecond() { |
|
159 destroy(); |
|
160 flag = false; |
|
161 new(reinterpret_cast<Second*>(data)) Second(); |
|
162 return *this; |
|
163 } |
|
164 |
|
165 BiVariant& setSecond(const Second& second) { |
|
166 destroy(); |
|
167 flag = false; |
|
168 new(reinterpret_cast<Second*>(data)) Second(second); |
|
169 return *this; |
|
170 } |
|
171 |
|
172 BiVariant& operator=(const First& first) { |
|
173 return setFirst(first); |
|
174 } |
|
175 |
|
176 BiVariant& operator=(const Second& second) { |
|
177 return setSecond(second); |
|
178 } |
|
179 |
|
180 |
|
181 BiVariant& operator=(const BiVariant& bivariant) { |
|
182 if (this == &bivariant) return *this; |
|
183 destroy(); |
|
184 flag = bivariant.flag; |
|
185 if (flag) { |
|
186 new(reinterpret_cast<First*>(data)) First(bivariant.first()); |
|
187 } else { |
|
188 new(reinterpret_cast<Second*>(data)) Second(bivariant.second()); |
|
189 } |
|
190 return *this; |
|
191 } |
|
192 |
|
193 First& first() { |
|
194 LEMON_ASSERT(flag, WrongStateError()); |
|
195 return *reinterpret_cast<First*>(data); |
|
196 } |
|
197 |
|
198 const First& first() const { |
|
199 LEMON_ASSERT(flag, WrongStateError()); |
|
200 return *reinterpret_cast<const First*>(data); |
|
201 } |
|
202 |
|
203 operator First&() { return first(); } |
|
204 operator const First&() const { return first(); } |
|
205 |
|
206 Second& second() { |
|
207 LEMON_ASSERT(!flag, WrongStateError()); |
|
208 return *reinterpret_cast<Second*>(data); |
|
209 } |
|
210 |
|
211 const Second& second() const { |
|
212 LEMON_ASSERT(!flag, WrongStateError()); |
|
213 return *reinterpret_cast<const Second*>(data); |
|
214 } |
|
215 |
|
216 operator Second&() { return second(); } |
|
217 operator const Second&() const { return second(); } |
|
218 |
|
219 bool firstState() const { return flag; } |
|
220 bool secondState() const { return !flag; } |
|
221 |
|
222 private: |
|
223 |
|
224 void destroy() { |
|
225 if (flag) { |
|
226 reinterpret_cast<First*>(data)->~First(); |
|
227 } else { |
|
228 reinterpret_cast<Second*>(data)->~Second(); |
|
229 } |
|
230 } |
|
231 |
|
232 char data[CTMax<sizeof(First), sizeof(Second)>::value]; |
|
233 bool flag; |
|
234 }; |
|
235 |
|
236 } |
|
237 |
|
238 |
|
239 #endif |