GG
|
00001 // -*- C++ -*- 00002 /* GG is a GUI for SDL and OpenGL. 00003 Copyright (C) 2003-2008 T. Zachary Laine 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Lesser General Public License 00007 as published by the Free Software Foundation; either version 2.1 00008 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public 00016 License along with this library; if not, write to the Free 00017 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 00018 02111-1307 USA 00019 00020 If you do not wish to comply with the terms of the LGPL please 00021 contact the author as other terms are available for a fee. 00022 00023 Zach Laine 00024 whatwasthataddress@gmail.com */ 00025 00030 #ifndef _GG_StrongTypedef_h_ 00031 #define _GG_StrongTypedef_h_ 00032 00033 #include <boost/static_assert.hpp> 00034 #include <boost/type_traits/is_integral.hpp> 00035 #include <boost/serialization/nvp.hpp> 00036 00037 #include <iostream> 00038 00039 00040 namespace GG { 00041 00043 inline int Value(int i) 00044 { return i; } 00045 00047 inline double Value(double d) 00048 { return d; } 00049 00051 inline std::size_t Value(std::size_t s) 00052 { return s; } 00053 00054 } 00055 00056 #define GG_MEMBER_BOOL_OP_SELF_TYPE(op, rhs_type) \ 00057 inline bool operator op (rhs_type rhs) const \ 00058 { return m_value op rhs.m_value; } 00059 00060 #define GG_MEMBER_BOOL_OP_OTHER_TYPE(op, rhs_type) \ 00061 inline bool operator op (rhs_type rhs) const \ 00062 { return m_value op Value(rhs); } 00063 00064 #define GG_MEMBER_NEG_INCR_DECR(this_type) \ 00065 inline this_type operator-() const \ 00066 { return this_type(-m_value); } \ 00067 inline this_type& operator++() \ 00068 { \ 00069 ++m_value; \ 00070 return *this; \ 00071 } \ 00072 inline this_type& operator--() \ 00073 { \ 00074 --m_value; \ 00075 return *this; \ 00076 } \ 00077 inline this_type operator++(int) \ 00078 { \ 00079 this_type retval(m_value); \ 00080 ++m_value; \ 00081 return retval; \ 00082 } \ 00083 inline this_type operator--(int) \ 00084 { \ 00085 this_type retval(m_value); \ 00086 --m_value; \ 00087 return retval; \ 00088 } 00089 00090 #define GG_MEMBER_ASSIGN_OP_SELF_TYPE(op, rhs_type) \ 00091 inline rhs_type& operator op (rhs_type rhs) \ 00092 { \ 00093 m_value op rhs.m_value; \ 00094 return *this; \ 00095 } 00096 00097 #define GG_MEMBER_ASSIGN_OP_OTHER_TYPE_DECL(op, self_type, rhs_type) \ 00098 inline self_type& operator op (rhs_type rhs) 00099 00100 #define GG_MEMBER_ASSIGN_OP_OTHER_TYPE(op, self_type, rhs_type) \ 00101 GG_MEMBER_ASSIGN_OP_OTHER_TYPE_DECL(op, self_type, rhs_type) \ 00102 { \ 00103 m_value op Value(rhs); \ 00104 return *this; \ 00105 } 00106 00107 #define GG_MEMBER_OP_OTHER_TYPE_DECL(op, self_type, rhs_type) \ 00108 inline self_type& operator op (rhs_type rhs) const 00109 00110 #define GG_MEMBER_OP_OTHER_TYPE(op, self_type, rhs_type) \ 00111 GG_MEMBER_OP_OTHER_TYPE_DECL(op, self_type, rhs_type) \ 00112 { return self_type(m_value op Value(rhs)); } 00113 00114 #define GG_NONMEMBER_OP_SELF_TYPE(op, self_type) \ 00115 inline self_type operator op (self_type lhs, self_type rhs) \ 00116 { return lhs op ## = rhs; } 00117 00118 #define GG_NONMEMBER_OP_OTHER_TYPE(op, self_type, rhs_type) \ 00119 inline self_type operator op (self_type lhs, rhs_type rhs) \ 00120 { return lhs op ## = Value(rhs); } 00121 00122 #define GG_MEMBER_SELF_COMPARATORS(self_type) \ 00123 GG_MEMBER_BOOL_OP_SELF_TYPE(==, self_type); \ 00124 GG_MEMBER_BOOL_OP_SELF_TYPE(!=, self_type); \ 00125 GG_MEMBER_BOOL_OP_SELF_TYPE(<, self_type); \ 00126 GG_MEMBER_BOOL_OP_SELF_TYPE(>, self_type); \ 00127 GG_MEMBER_BOOL_OP_SELF_TYPE(<=, self_type); \ 00128 GG_MEMBER_BOOL_OP_SELF_TYPE(>=, self_type); 00129 00130 #define GG_MEMBER_OTHER_COMPARATORS(rhs_type) \ 00131 GG_MEMBER_BOOL_OP_OTHER_TYPE(==, rhs_type); \ 00132 GG_MEMBER_BOOL_OP_OTHER_TYPE(!=, rhs_type); \ 00133 GG_MEMBER_BOOL_OP_OTHER_TYPE(<, rhs_type); \ 00134 GG_MEMBER_BOOL_OP_OTHER_TYPE(>, rhs_type); \ 00135 GG_MEMBER_BOOL_OP_OTHER_TYPE(<=, rhs_type); \ 00136 GG_MEMBER_BOOL_OP_OTHER_TYPE(>=, rhs_type); 00137 00138 #define GG_MEMBER_ARITH_ASSIGN_OPS_SELF_TYPE(rhs_type) \ 00139 GG_MEMBER_ASSIGN_OP_SELF_TYPE(+=, rhs_type); \ 00140 GG_MEMBER_ASSIGN_OP_SELF_TYPE(-=, rhs_type); \ 00141 GG_MEMBER_ASSIGN_OP_SELF_TYPE(*=, rhs_type); \ 00142 GG_MEMBER_ASSIGN_OP_SELF_TYPE(/=, rhs_type); 00143 00144 #define GG_MEMBER_ARITH_ASSIGN_OPS_OTHER_TYPE(self_type, rhs_type) \ 00145 GG_MEMBER_ASSIGN_OP_OTHER_TYPE(+=, self_type, rhs_type); \ 00146 GG_MEMBER_ASSIGN_OP_OTHER_TYPE(-=, self_type, rhs_type); \ 00147 GG_MEMBER_ASSIGN_OP_OTHER_TYPE(*=, self_type, rhs_type); \ 00148 GG_MEMBER_ASSIGN_OP_OTHER_TYPE(/=, self_type, rhs_type); 00149 00150 #define GG_NONMEMBER_ARITH_OPS_SELF_TYPE(self_type) \ 00151 GG_NONMEMBER_OP_SELF_TYPE(+, self_type); \ 00152 GG_NONMEMBER_OP_SELF_TYPE(-, self_type); \ 00153 GG_NONMEMBER_OP_SELF_TYPE(*, self_type); \ 00154 GG_NONMEMBER_OP_SELF_TYPE(/, self_type); 00155 00156 #define GG_NONMEMBER_ARITH_OPS_OTHER_TYPE(self_type, rhs_type) \ 00157 GG_NONMEMBER_OP_OTHER_TYPE(+, self_type, rhs_type); \ 00158 GG_NONMEMBER_OP_OTHER_TYPE(-, self_type, rhs_type); \ 00159 GG_NONMEMBER_OP_OTHER_TYPE(*, self_type, rhs_type); \ 00160 GG_NONMEMBER_OP_OTHER_TYPE(/, self_type, rhs_type); 00161 00162 #define GG_NONMEMBER_REVERSED_BOOL_OP_SET(lhs_type, self_type) \ 00163 inline bool operator==(lhs_type x, self_type y) \ 00164 { return y == x; } \ 00165 inline bool operator!=(lhs_type x, self_type y) \ 00166 { return y != x; } \ 00167 inline bool operator<(lhs_type x, self_type y) \ 00168 { return !(y < x || y == x); } \ 00169 inline bool operator>(lhs_type x, self_type y) \ 00170 { return !(y > x || y == x); } \ 00171 inline bool operator<=(lhs_type x, self_type y) \ 00172 { return !(y < x); } \ 00173 inline bool operator>=(lhs_type x, self_type y) \ 00174 { return !(y > x); } 00175 00176 #define GG_NONMEMBER_REVERSED_ARITH_OP_SET(lhs_type, self_type) \ 00177 inline self_type operator+(lhs_type x, self_type y) \ 00178 { return y += x; } \ 00179 inline self_type operator-(lhs_type x, self_type y) \ 00180 { return -(y -= x); } \ 00181 inline self_type operator*(lhs_type x, self_type y) \ 00182 { return y *= x; } 00183 00184 00185 #define GG_STRONG_DOUBLE_TYPEDEF(name, type) \ 00186 class name; \ 00187 class name ## _d; \ 00188 type Value(name x); \ 00189 double Value(name ## _d x); \ 00190 \ 00191 class name ## _d \ 00192 { \ 00193 private: \ 00194 struct ConvertibleToBoolDummy {int _;}; \ 00195 \ 00196 public: \ 00197 name ## _d() : m_value(0.0) {} \ 00198 explicit name ## _d(double t) : m_value(t) {} \ 00199 \ 00200 GG_MEMBER_SELF_COMPARATORS(name ## _d); \ 00201 \ 00202 GG_MEMBER_OTHER_COMPARATORS(double); \ 00203 \ 00204 operator int ConvertibleToBoolDummy::* () const \ 00205 { return m_value ? &ConvertibleToBoolDummy::_ : 0; } \ 00206 \ 00207 GG_MEMBER_NEG_INCR_DECR(name ## _d); \ 00208 \ 00209 GG_MEMBER_ARITH_ASSIGN_OPS_SELF_TYPE(name ## _d); \ 00210 \ 00211 GG_MEMBER_ARITH_ASSIGN_OPS_OTHER_TYPE(name ## _d, double); \ 00212 \ 00213 GG_MEMBER_ASSIGN_OP_OTHER_TYPE_DECL(+=, name ## _d, name); \ 00214 GG_MEMBER_ASSIGN_OP_OTHER_TYPE_DECL(-=, name ## _d, name); \ 00215 GG_MEMBER_ASSIGN_OP_OTHER_TYPE_DECL(*=, name ## _d, name); \ 00216 GG_MEMBER_ASSIGN_OP_OTHER_TYPE_DECL(/=, name ## _d, name); \ 00217 \ 00218 private: \ 00219 double m_value; \ 00220 \ 00221 friend class boost::serialization::access; \ 00222 template <class Archive> \ 00223 void serialize(Archive& ar, const unsigned int version) \ 00224 { ar & BOOST_SERIALIZATION_NVP(m_value); } \ 00225 \ 00226 friend double Value(name ## _d x); \ 00227 }; \ 00228 \ 00229 GG_NONMEMBER_ARITH_OPS_SELF_TYPE(name ## _d); \ 00230 \ 00231 GG_NONMEMBER_ARITH_OPS_OTHER_TYPE(name ## _d, double); \ 00232 \ 00233 GG_NONMEMBER_REVERSED_BOOL_OP_SET(double, name ## _d); \ 00234 \ 00235 GG_NONMEMBER_REVERSED_ARITH_OP_SET(double, name ## _d); \ 00236 \ 00237 inline double Value(name ## _d x) \ 00238 { return x.m_value; } \ 00239 \ 00240 inline std::ostream& operator<<(std::ostream& os, name ## _d x) \ 00241 { os << Value(x); return os; } \ 00242 \ 00243 inline std::istream& operator>>(std::istream& os, name ## _d& x) \ 00244 { \ 00245 double t; \ 00246 os >> t; \ 00247 x = name ## _d(t); \ 00248 return os; \ 00249 } \ 00250 \ 00251 void dummy_function_to_force_semicolon() 00252 00261 #define GG_STRONG_INTEGRAL_TYPEDEF(name, type) \ 00262 GG_STRONG_DOUBLE_TYPEDEF(name, type); \ 00263 \ 00264 type Value(name x); \ 00265 \ 00266 class name \ 00267 { \ 00268 private: \ 00269 struct ConvertibleToBoolDummy {int _;}; \ 00270 \ 00271 public: \ 00272 BOOST_STATIC_ASSERT((boost::is_integral<type>::value)); \ 00273 \ 00274 name() : m_value(0) {} \ 00275 explicit name(type t) : m_value(t) {} \ 00276 explicit name(name ## _d t) : \ 00277 m_value(static_cast<type>(Value(t))) \ 00278 {} \ 00279 \ 00280 name& operator=(name ## _d t) \ 00281 { m_value = static_cast<type>(Value(t)); return *this; } \ 00282 \ 00283 GG_MEMBER_SELF_COMPARATORS(name); \ 00284 \ 00285 GG_MEMBER_OTHER_COMPARATORS(type); \ 00286 GG_MEMBER_OTHER_COMPARATORS(name ## _d); \ 00287 GG_MEMBER_OTHER_COMPARATORS(double); \ 00288 \ 00289 operator int ConvertibleToBoolDummy::* () const \ 00290 { return m_value ? &ConvertibleToBoolDummy::_ : 0; } \ 00291 \ 00292 GG_MEMBER_NEG_INCR_DECR(name); \ 00293 \ 00294 GG_MEMBER_ARITH_ASSIGN_OPS_SELF_TYPE(name); \ 00295 GG_MEMBER_ASSIGN_OP_SELF_TYPE(%=, name); \ 00296 \ 00297 GG_MEMBER_ARITH_ASSIGN_OPS_OTHER_TYPE(name, type); \ 00298 GG_MEMBER_ASSIGN_OP_OTHER_TYPE(%=, name, type); \ 00299 \ 00300 GG_MEMBER_ARITH_ASSIGN_OPS_OTHER_TYPE(name, name ## _d); \ 00301 GG_MEMBER_ARITH_ASSIGN_OPS_OTHER_TYPE(name, double); \ 00302 \ 00303 private: \ 00304 type m_value; \ 00305 \ 00306 friend class boost::serialization::access; \ 00307 template <class Archive> \ 00308 void serialize(Archive& ar, const unsigned int version) \ 00309 { ar & BOOST_SERIALIZATION_NVP(m_value); } \ 00310 \ 00311 friend class name ## _d; \ 00312 friend type Value(name x); \ 00313 }; \ 00314 \ 00315 GG_NONMEMBER_ARITH_OPS_SELF_TYPE(name); \ 00316 GG_NONMEMBER_OP_SELF_TYPE(%, name); \ 00317 \ 00318 GG_NONMEMBER_ARITH_OPS_OTHER_TYPE(name, type); \ 00319 GG_NONMEMBER_OP_OTHER_TYPE(%, name, type); \ 00320 \ 00321 GG_NONMEMBER_REVERSED_BOOL_OP_SET(type, name); \ 00322 GG_NONMEMBER_REVERSED_BOOL_OP_SET(name ## _d, name); \ 00323 GG_NONMEMBER_REVERSED_BOOL_OP_SET(double, name); \ 00324 \ 00325 GG_NONMEMBER_REVERSED_ARITH_OP_SET(type, name); \ 00326 \ 00327 inline name ## _d operator+(name x, double y) \ 00328 { return name ## _d(Value(x)) + y; } \ 00329 inline name ## _d operator-(name x, double y) \ 00330 { return name ## _d(Value(x)) - y; } \ 00331 inline name ## _d operator*(name x, double y) \ 00332 { return name ## _d(Value(x)) * y; } \ 00333 inline name ## _d operator/(name x, double y) \ 00334 { return name ## _d(Value(x)) / y; } \ 00335 \ 00336 inline name ## _d operator+(double x, name y) \ 00337 { return x + name ## _d(Value(y)); } \ 00338 inline name ## _d operator-(double x, name y) \ 00339 { return x - name ## _d(Value(y)); } \ 00340 inline name ## _d operator*(double x, name y) \ 00341 { return x * name ## _d(Value(y)); } \ 00342 \ 00343 inline type Value(name x) \ 00344 { return x.m_value; } \ 00345 \ 00346 inline std::ostream& operator<<(std::ostream& os, name x) \ 00347 { os << Value(x); return os; } \ 00348 \ 00349 inline std::istream& operator>>(std::istream& os, name& x) \ 00350 { \ 00351 type t; \ 00352 os >> t; \ 00353 x = name(t); \ 00354 return os; \ 00355 } \ 00356 \ 00357 inline name ## _d& name ## _d::operator+=(name rhs) \ 00358 { m_value += Value(rhs); return *this; } \ 00359 inline name ## _d& name ## _d::operator-=(name rhs) \ 00360 { m_value -= Value(rhs); return *this; } \ 00361 inline name ## _d& name ## _d::operator*=(name rhs) \ 00362 { m_value *= Value(rhs); return *this; } \ 00363 inline name ## _d& name ## _d::operator/=(name rhs) \ 00364 { m_value /= Value(rhs); return *this; } \ 00365 \ 00366 GG_NONMEMBER_ARITH_OPS_OTHER_TYPE(name ## _d, name); \ 00367 \ 00368 GG_NONMEMBER_REVERSED_ARITH_OP_SET(name, name ## _d); \ 00369 inline name ## _d operator/(name x, name ## _d y) \ 00370 { return name ## _d(Value(x) / Value(y)); } \ 00371 \ 00372 void dummy_function_to_force_semicolon() 00373 00379 #define GG_STRONG_SIZE_TYPEDEF(name) \ 00380 class name; \ 00381 std::size_t Value(name x); \ 00382 \ 00383 class name \ 00384 { \ 00385 private: \ 00386 struct ConvertibleToBoolDummy {int _;}; \ 00387 \ 00388 public: \ 00389 name() : m_value(0) {} \ 00390 explicit name(std::size_t t) : m_value(t) {} \ 00391 \ 00392 GG_MEMBER_SELF_COMPARATORS(name); \ 00393 \ 00394 GG_MEMBER_OTHER_COMPARATORS(std::size_t); \ 00395 \ 00396 operator int ConvertibleToBoolDummy::* () const \ 00397 { return m_value ? &ConvertibleToBoolDummy::_ : 0; } \ 00398 \ 00399 GG_MEMBER_NEG_INCR_DECR(name); \ 00400 \ 00401 GG_MEMBER_ARITH_ASSIGN_OPS_SELF_TYPE(name); \ 00402 GG_MEMBER_ASSIGN_OP_SELF_TYPE(%=, name); \ 00403 \ 00404 GG_MEMBER_ARITH_ASSIGN_OPS_OTHER_TYPE(name, std::size_t); \ 00405 GG_MEMBER_ASSIGN_OP_OTHER_TYPE(%=, name, std::size_t); \ 00406 \ 00407 private: \ 00408 std::size_t m_value; \ 00409 \ 00410 friend class boost::serialization::access; \ 00411 template <class Archive> \ 00412 void serialize(Archive& ar, const unsigned int version) \ 00413 { ar & BOOST_SERIALIZATION_NVP(m_value); } \ 00414 \ 00415 friend class name ## _d; \ 00416 friend std::size_t Value(name x); \ 00417 }; \ 00418 \ 00419 GG_NONMEMBER_ARITH_OPS_SELF_TYPE(name); \ 00420 GG_NONMEMBER_OP_SELF_TYPE(%, name); \ 00421 \ 00422 GG_NONMEMBER_ARITH_OPS_OTHER_TYPE(name, std::size_t); \ 00423 GG_NONMEMBER_OP_OTHER_TYPE(%, name, std::size_t); \ 00424 \ 00425 GG_NONMEMBER_REVERSED_BOOL_OP_SET(std::size_t, name); \ 00426 \ 00427 GG_NONMEMBER_REVERSED_ARITH_OP_SET(std::size_t, name); \ 00428 \ 00429 inline std::size_t Value(name x) \ 00430 { return x.m_value; } \ 00431 \ 00432 inline std::ostream& operator<<(std::ostream& os, name x) \ 00433 { os << Value(x); return os; } \ 00434 \ 00435 inline std::istream& operator>>(std::istream& os, name& x) \ 00436 { \ 00437 std::size_t t; \ 00438 os >> t; \ 00439 x = name(t); \ 00440 return os; \ 00441 } \ 00442 \ 00443 void dummy_function_to_force_semicolon() 00444 00445 #endif // _GG_StrongTypedef_h_