GG

StrongTypedef.h

Go to the documentation of this file.
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_