GG
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