GG: StrongTypedef.h Source File

GG

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

StrongTypedef.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 /* GG is a GUI for SDL and OpenGL.
3 Copyright (C) 2003-2008 T. Zachary Laine
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public License
7 as published by the Free Software Foundation; either version 2.1
8 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA
19
20 If you do not wish to comply with the terms of the LGPL please
21 contact the author as other terms are available for a fee.
22
23 Zach Laine
24 whatwasthataddress@gmail.com */
25
30 #ifndef _GG_StrongTypedef_h_
31 #define _GG_StrongTypedef_h_
32
33 #include <boost/static_assert.hpp>
34 #include <boost/type_traits/is_integral.hpp>
35
36 #include <iostream>
37
38
39 namespace GG {
40
42 inline int Value(int i)
43 { return i; }
44
46 inline double Value(double d)
47 { return d; }
48
50 inline std::size_t Value(std::size_t s)
51 { return s; }
52
53 }
54
55 #define GG_MEMBER_BOOL_OP_SELF_TYPE(op, rhs_type) \
56 inline bool operator op (rhs_type rhs) const \
57 { return m_value op rhs.m_value; }
58
59 #define GG_MEMBER_BOOL_OP_OTHER_TYPE(op, rhs_type) \
60 inline bool operator op (rhs_type rhs) const \
61 { return m_value op Value(rhs); }
62
63 #define GG_MEMBER_NEG_INCR_DECR(this_type) \
64 inline this_type operator-() const \
65 { return this_type(-m_value); } \
66 inline this_type& operator++() \
67 { \
68 ++m_value; \
69 return *this; \
70 } \
71 inline this_type& operator--() \
72 { \
73 --m_value; \
74 return *this; \
75 } \
76 inline this_type operator++(int) \
77 { \
78 this_type retval(m_value); \
79 ++m_value; \
80 return retval; \
81 } \
82 inline this_type operator--(int) \
83 { \
84 this_type retval(m_value); \
85 --m_value; \
86 return retval; \
87 }
88
89 #define GG_MEMBER_ASSIGN_OP_SELF_TYPE(op, rhs_type) \
90 inline rhs_type& operator op (rhs_type rhs) \
91 { \
92 m_value op rhs.m_value; \
93 return *this; \
94 }
95
96 #define GG_MEMBER_ASSIGN_OP_OTHER_TYPE_DECL(op, self_type, rhs_type) \
97 inline self_type& operator op ## = (rhs_type rhs)
98
99 #define GG_MEMBER_ASSIGN_OP_OTHER_TYPE(op, self_type, rhs_type) \
100 GG_MEMBER_ASSIGN_OP_OTHER_TYPE_DECL(op, self_type, rhs_type) \
101 { \
102 m_value = static_cast<self_type::value_type>( \
103 m_value op Value(rhs) \
104 ); \
105 return *this; \
106 }
107
108 #define GG_MEMBER_OP_OTHER_TYPE_DECL(op, self_type, rhs_type) \
109 inline self_type& operator op (rhs_type rhs) const
110
111 #define GG_MEMBER_OP_OTHER_TYPE(op, self_type, rhs_type) \
112 GG_MEMBER_OP_OTHER_TYPE_DECL(op, self_type, rhs_type) \
113 { return self_type(m_value op Value(rhs)); }
114
115 #define GG_NONMEMBER_OP_SELF_TYPE(op, self_type) \
116 inline self_type operator op (self_type lhs, self_type rhs) \
117 { return lhs op ## = rhs; }
118
119 #define GG_NONMEMBER_OP_OTHER_TYPE(op, self_type, rhs_type) \
120 inline self_type operator op (self_type lhs, rhs_type rhs) \
121 { return lhs op ## = Value(rhs); }
122
123 #define GG_MEMBER_SELF_COMPARATORS(self_type) \
124 GG_MEMBER_BOOL_OP_SELF_TYPE(==, self_type); \
125 GG_MEMBER_BOOL_OP_SELF_TYPE(!=, self_type); \
126 GG_MEMBER_BOOL_OP_SELF_TYPE(<, self_type); \
127 GG_MEMBER_BOOL_OP_SELF_TYPE(>, self_type); \
128 GG_MEMBER_BOOL_OP_SELF_TYPE(<=, self_type); \
129 GG_MEMBER_BOOL_OP_SELF_TYPE(>=, self_type);
130
131 #define GG_MEMBER_OTHER_COMPARATORS(rhs_type) \
132 GG_MEMBER_BOOL_OP_OTHER_TYPE(==, rhs_type); \
133 GG_MEMBER_BOOL_OP_OTHER_TYPE(!=, rhs_type); \
134 GG_MEMBER_BOOL_OP_OTHER_TYPE(<, rhs_type); \
135 GG_MEMBER_BOOL_OP_OTHER_TYPE(>, rhs_type); \
136 GG_MEMBER_BOOL_OP_OTHER_TYPE(<=, rhs_type); \
137 GG_MEMBER_BOOL_OP_OTHER_TYPE(>=, rhs_type);
138
139 #define GG_MEMBER_ARITH_ASSIGN_OPS_SELF_TYPE(rhs_type) \
140 GG_MEMBER_ASSIGN_OP_SELF_TYPE(+=, rhs_type); \
141 GG_MEMBER_ASSIGN_OP_SELF_TYPE(-=, rhs_type); \
142 GG_MEMBER_ASSIGN_OP_SELF_TYPE(*=, rhs_type); \
143 GG_MEMBER_ASSIGN_OP_SELF_TYPE(/=, rhs_type);
144
145 #define GG_MEMBER_ARITH_ASSIGN_OPS_OTHER_TYPE(self_type, rhs_type) \
146 GG_MEMBER_ASSIGN_OP_OTHER_TYPE(+, self_type, rhs_type); \
147 GG_MEMBER_ASSIGN_OP_OTHER_TYPE(-, self_type, rhs_type); \
148 GG_MEMBER_ASSIGN_OP_OTHER_TYPE(*, self_type, rhs_type); \
149 GG_MEMBER_ASSIGN_OP_OTHER_TYPE(/, self_type, rhs_type);
150
151 #define GG_NONMEMBER_ARITH_OPS_SELF_TYPE(self_type) \
152 GG_NONMEMBER_OP_SELF_TYPE(+, self_type); \
153 GG_NONMEMBER_OP_SELF_TYPE(-, self_type); \
154 GG_NONMEMBER_OP_SELF_TYPE(*, self_type); \
155 GG_NONMEMBER_OP_SELF_TYPE(/, self_type);
156
157 #define GG_NONMEMBER_ARITH_OPS_OTHER_TYPE(self_type, rhs_type) \
158 GG_NONMEMBER_OP_OTHER_TYPE(+, self_type, rhs_type); \
159 GG_NONMEMBER_OP_OTHER_TYPE(-, self_type, rhs_type); \
160 GG_NONMEMBER_OP_OTHER_TYPE(*, self_type, rhs_type); \
161 GG_NONMEMBER_OP_OTHER_TYPE(/, self_type, rhs_type);
162
163 #define GG_NONMEMBER_REVERSED_BOOL_OP_SET(lhs_type, self_type) \
164 inline bool operator==(lhs_type x, self_type y) \
165 { return y == x; } \
166 inline bool operator!=(lhs_type x, self_type y) \
167 { return y != x; } \
168 inline bool operator<(lhs_type x, self_type y) \
169 { return !(y < x || y == x); } \
170 inline bool operator>(lhs_type x, self_type y) \
171 { return !(y > x || y == x); } \
172 inline bool operator<=(lhs_type x, self_type y) \
173 { return !(y < x); } \
174 inline bool operator>=(lhs_type x, self_type y) \
175 { return !(y > x); }
176
177 #define GG_NONMEMBER_REVERSED_ARITH_OP_SET(lhs_type, self_type) \
178 inline self_type operator+(lhs_type x, self_type y) \
179 { return y += x; } \
180 inline self_type operator-(lhs_type x, self_type y) \
181 { return -(y -= x); } \
182 inline self_type operator*(lhs_type x, self_type y) \
183 { return y *= x; }
184
185
186 #define GG_STRONG_DOUBLE_TYPEDEF(name, type) \
187 class name; \
188 class name ## _d; \
189 type Value(name x); \
190 double Value(name ## _d x); \
191 \
192 class name ## _d \
193 { \
194 private: \
195 struct ConvertibleToBoolDummy {int _;}; \
196 \
197 public: \
198 typedef double value_type; \
199 \
200 name ## _d() : m_value(0.0) {} \
201 explicit name ## _d(double t) : m_value(t) {} \
202 \
203 GG_MEMBER_SELF_COMPARATORS(name ## _d); \
204 \
205 GG_MEMBER_OTHER_COMPARATORS(double); \
206 \
207 operator int ConvertibleToBoolDummy::* () const \
208 { return m_value ? &ConvertibleToBoolDummy::_ : 0; } \
209 \
210 GG_MEMBER_NEG_INCR_DECR(name ## _d); \
211 \
212 GG_MEMBER_ARITH_ASSIGN_OPS_SELF_TYPE(name ## _d); \
213 \
214 GG_MEMBER_ARITH_ASSIGN_OPS_OTHER_TYPE(name ## _d, double); \
215 \
216 GG_MEMBER_ASSIGN_OP_OTHER_TYPE_DECL(+, name ## _d, name); \
217 GG_MEMBER_ASSIGN_OP_OTHER_TYPE_DECL(-, name ## _d, name); \
218 GG_MEMBER_ASSIGN_OP_OTHER_TYPE_DECL(*, name ## _d, name); \
219 GG_MEMBER_ASSIGN_OP_OTHER_TYPE_DECL(/, name ## _d, name); \
220 \
221 private: \
222 double m_value; \
223 \
224 friend double Value(name ## _d x); \
225 }; \
226 \
227 GG_NONMEMBER_ARITH_OPS_SELF_TYPE(name ## _d); \
228 \
229 GG_NONMEMBER_ARITH_OPS_OTHER_TYPE(name ## _d, double); \
230 \
231 GG_NONMEMBER_REVERSED_BOOL_OP_SET(double, name ## _d); \
232 \
233 GG_NONMEMBER_REVERSED_ARITH_OP_SET(double, name ## _d); \
234 \
235 inline double Value(name ## _d x) \
236 { return x.m_value; } \
237 \
238 inline std::ostream& operator<<(std::ostream& os, name ## _d x) \
239 { os << Value(x); return os; } \
240 \
241 inline std::istream& operator>>(std::istream& os, name ## _d& x) \
242 { \
243 double t; \
244 os >> t; \
245 x = name ## _d(t); \
246 return os; \
247 } \
248 \
249 void dummy_function_to_force_semicolon()
250
259 #define GG_STRONG_INTEGRAL_TYPEDEF(name, type) \
260 GG_STRONG_DOUBLE_TYPEDEF(name, type); \
261 \
262 type Value(name x); \
263 \
264 class name \
265 { \
266 private: \
267 struct ConvertibleToBoolDummy {int _;}; \
268 \
269 public: \
270 BOOST_STATIC_ASSERT((boost::is_integral<type>::value)); \
271 \
272 typedef type value_type; \
273 \
274 name() : m_value(0) {} \
275 explicit name(type t) : m_value(t) {} \
276 explicit name(name ## _d t) : \
277 m_value(static_cast<type>(Value(t))) \
278 {} \
279 \
280 name& operator=(name ## _d t) \
281 { m_value = static_cast<type>(Value(t)); return *this; } \
282 \
283 GG_MEMBER_SELF_COMPARATORS(name); \
284 \
285 GG_MEMBER_OTHER_COMPARATORS(type); \
286 GG_MEMBER_OTHER_COMPARATORS(name ## _d); \
287 GG_MEMBER_OTHER_COMPARATORS(double); \
288 \
289 operator int ConvertibleToBoolDummy::* () const \
290 { return m_value ? &ConvertibleToBoolDummy::_ : 0; } \
291 \
292 GG_MEMBER_NEG_INCR_DECR(name); \
293 \
294 GG_MEMBER_ARITH_ASSIGN_OPS_SELF_TYPE(name); \
295 GG_MEMBER_ASSIGN_OP_SELF_TYPE(%=, name); \
296 \
297 GG_MEMBER_ARITH_ASSIGN_OPS_OTHER_TYPE(name, type); \
298 GG_MEMBER_ASSIGN_OP_OTHER_TYPE(%, name, type); \
299 \
300 GG_MEMBER_ARITH_ASSIGN_OPS_OTHER_TYPE(name, name ## _d); \
301 GG_MEMBER_ARITH_ASSIGN_OPS_OTHER_TYPE(name, double); \
302 \
303 private: \
304 type m_value; \
305 \
306 friend class name ## _d; \
307 friend type Value(name x); \
308 }; \
309 \
310 GG_NONMEMBER_ARITH_OPS_SELF_TYPE(name); \
311 GG_NONMEMBER_OP_SELF_TYPE(%, name); \
312 \
313 GG_NONMEMBER_ARITH_OPS_OTHER_TYPE(name, type); \
314 GG_NONMEMBER_OP_OTHER_TYPE(%, name, type); \
315 \
316 GG_NONMEMBER_REVERSED_BOOL_OP_SET(type, name); \
317 GG_NONMEMBER_REVERSED_BOOL_OP_SET(name ## _d, name); \
318 GG_NONMEMBER_REVERSED_BOOL_OP_SET(double, name); \
319 \
320 GG_NONMEMBER_REVERSED_ARITH_OP_SET(type, name); \
321 \
322 inline name ## _d operator+(name x, double y) \
323 { return name ## _d(Value(x)) + y; } \
324 inline name ## _d operator-(name x, double y) \
325 { return name ## _d(Value(x)) - y; } \
326 inline name ## _d operator*(name x, double y) \
327 { return name ## _d(Value(x)) * y; } \
328 inline name ## _d operator/(name x, double y) \
329 { return name ## _d(Value(x)) / y; } \
330 \
331 inline name ## _d operator+(double x, name y) \
332 { return x + name ## _d(Value(y)); } \
333 inline name ## _d operator-(double x, name y) \
334 { return x - name ## _d(Value(y)); } \
335 inline name ## _d operator*(double x, name y) \
336 { return x * name ## _d(Value(y)); } \
337 \
338 inline type Value(name x) \
339 { return x.m_value; } \
340 \
341 inline std::ostream& operator<<(std::ostream& os, name x) \
342 { os << Value(x); return os; } \
343 \
344 inline std::istream& operator>>(std::istream& os, name& x) \
345 { \
346 type t; \
347 os >> t; \
348 x = name(t); \
349 return os; \
350 } \
351 \
352 inline name ## _d& name ## _d::operator+=(name rhs) \
353 { m_value += Value(rhs); return *this; } \
354 inline name ## _d& name ## _d::operator-=(name rhs) \
355 { m_value -= Value(rhs); return *this; } \
356 inline name ## _d& name ## _d::operator*=(name rhs) \
357 { m_value *= Value(rhs); return *this; } \
358 inline name ## _d& name ## _d::operator/=(name rhs) \
359 { m_value /= Value(rhs); return *this; } \
360 \
361 GG_NONMEMBER_ARITH_OPS_OTHER_TYPE(name ## _d, name); \
362 \
363 GG_NONMEMBER_REVERSED_ARITH_OP_SET(name, name ## _d); \
364 inline name ## _d operator/(name x, name ## _d y) \
365 { return name ## _d(Value(x) / Value(y)); } \
366 \
367 void dummy_function_to_force_semicolon()
368
374 #define GG_STRONG_SIZE_TYPEDEF(name) \
375 class name; \
376 std::size_t Value(name x); \
377 \
378 class name \
379 { \
380 private: \
381 struct ConvertibleToBoolDummy {int _;}; \
382 \
383 public: \
384 typedef std::size_t value_type; \
385 \
386 name() : m_value(0) {} \
387 explicit name(std::size_t t) : m_value(t) {} \
388 \
389 GG_MEMBER_SELF_COMPARATORS(name); \
390 \
391 GG_MEMBER_OTHER_COMPARATORS(std::size_t); \
392 \
393 operator int ConvertibleToBoolDummy::* () const \
394 { return m_value ? &ConvertibleToBoolDummy::_ : 0; } \
395 \
396 GG_MEMBER_NEG_INCR_DECR(name); \
397 \
398 GG_MEMBER_ARITH_ASSIGN_OPS_SELF_TYPE(name); \
399 GG_MEMBER_ASSIGN_OP_SELF_TYPE(%=, name); \
400 \
401 GG_MEMBER_ARITH_ASSIGN_OPS_OTHER_TYPE(name, std::size_t); \
402 GG_MEMBER_ASSIGN_OP_OTHER_TYPE(%, name, std::size_t); \
403 \
404 private: \
405 std::size_t m_value; \
406 \
407 friend class name ## _d; \
408 friend std::size_t Value(name x); \
409 }; \
410 \
411 GG_NONMEMBER_ARITH_OPS_SELF_TYPE(name); \
412 GG_NONMEMBER_OP_SELF_TYPE(%, name); \
413 \
414 GG_NONMEMBER_ARITH_OPS_OTHER_TYPE(name, std::size_t); \
415 GG_NONMEMBER_OP_OTHER_TYPE(%, name, std::size_t); \
416 \
417 GG_NONMEMBER_REVERSED_BOOL_OP_SET(std::size_t, name); \
418 \
419 GG_NONMEMBER_REVERSED_ARITH_OP_SET(std::size_t, name); \
420 \
421 inline std::size_t Value(name x) \
422 { return x.m_value; } \
423 \
424 inline std::ostream& operator<<(std::ostream& os, name x) \
425 { os << Value(x); return os; } \
426 \
427 inline std::istream& operator>>(std::istream& os, name& x) \
428 { \
429 std::size_t t; \
430 os >> t; \
431 x = name(t); \
432 return os; \
433 } \
434 \
435 void dummy_function_to_force_semicolon()
436
437 #endif