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/operators.hpp>
00035 #include <boost/type_traits/is_integral.hpp>
00036 #include <boost/serialization/nvp.hpp>
00037 
00038 #include <iostream>
00039 
00040 
00041 #define GG_STRONG_DOUBLE_TYPEDEF(name)                                  \
00042     class name;                                                         \
00043     class name ## _d;                                                   \
00044     double Value(name ## _d x);                                         \
00045                                                                         \
00046     class name ## _d :                                                  \
00047         boost::equality_comparable1<name ## _d                          \
00048       , boost::equality_comparable2<name ## _d, double                  \
00049       , boost::unit_steppable<name ## _d                                \
00050       , boost::integer_arithmetic1<name ## _d                           \
00051       , boost::integer_arithmetic2<name ## _d, double                   \
00052       , boost::subtractable2_left<name ## _d, double                    \
00053     > > > > > >                                                         \
00054     {                                                                   \
00055     private:                                                            \
00056         struct ConvertibleToBoolDummy {int _;};                         \
00057                                                                         \
00058     public:                                                             \
00059         name ## _d() {}                                                 \
00060         explicit name ## _d(double t) : m_value(t) {}                   \
00061                                                                         \
00062         bool operator<(name ## _d rhs) const                            \
00063         { return m_value < rhs.m_value; }                               \
00064         bool operator==(name ## _d rhs) const                           \
00065         { return m_value == rhs.m_value; }                              \
00066                                                                         \
00067         bool operator<(double rhs) const                                \
00068         { return m_value < rhs; }                                       \
00069         bool operator==(double rhs) const                               \
00070         { return m_value == rhs; }                                      \
00071                                                                         \
00072         operator int ConvertibleToBoolDummy::* () const                 \
00073         { return m_value ? &ConvertibleToBoolDummy::_ : 0; }            \
00074                                                                         \
00075         name ## _d operator-() const                                    \
00076         { return name ## _d(-m_value); }                                \
00077                                                                         \
00078         name ## _d& operator++()                                        \
00079         { ++m_value; return *this; }                                    \
00080         name ## _d& operator--()                                        \
00081         { --m_value; return *this; }                                    \
00082                                                                         \
00083         name ## _d& operator+=(name ## _d rhs)                          \
00084         { m_value += rhs.m_value; return *this; }                       \
00085         name ## _d& operator-=(name ## _d rhs)                          \
00086         { m_value -= rhs.m_value; return *this; }                       \
00087         name ## _d& operator*=(name ## _d rhs)                          \
00088         { m_value *= rhs.m_value; return *this; }                       \
00089         name ## _d& operator/=(name ## _d rhs)                          \
00090         { m_value /= rhs.m_value; return *this; }                       \
00091                                                                         \
00092         name ## _d& operator+=(double rhs)                              \
00093         { m_value += rhs; return *this; }                               \
00094         name ## _d& operator-=(double rhs)                              \
00095         { m_value -= rhs; return *this; }                               \
00096         name ## _d& operator*=(double rhs)                              \
00097         { m_value *= rhs; return *this; }                               \
00098         name ## _d& operator/=(double rhs)                              \
00099         { m_value /= rhs; return *this; }                               \
00100                                                                         \
00101         name ## _d& operator+=(name rhs);                               \
00102         name ## _d& operator-=(name rhs);                               \
00103         name ## _d& operator*=(name rhs);                               \
00104         name ## _d& operator/=(name rhs);                               \
00105                                                                         \
00106         name ## _d operator+(name rhs);                                 \
00107         name ## _d operator-(name rhs);                                 \
00108         name ## _d operator*(name rhs);                                 \
00109         name ## _d operator/(name rhs);                                 \
00110                                                                         \
00111     private:                                                            \
00112         double m_value;                                                 \
00113                                                                         \
00114         friend class boost::serialization::access;                      \
00115         template <class Archive>                                        \
00116         void serialize(Archive& ar, const unsigned int version)         \
00117         { ar & BOOST_SERIALIZATION_NVP(m_value); }                      \
00118                                                                         \
00119         friend double Value(name ## _d x);                              \
00120     };                                                                  \
00121                                                                         \
00122     inline bool operator>(name ## _d x, name ## _d y)                   \
00123     { return y < x; }                                                   \
00124     inline bool operator<=(name ## _d x, name ## _d y)                  \
00125     { return x < y || x == y; }                                         \
00126     inline bool operator>=(name ## _d x, name ## _d y)                  \
00127     { return y < x || x == y; }                                         \
00128                                                                         \
00129     inline bool operator>(name ## _d x, double y)                       \
00130     { return !(x < y || x == y); }                                      \
00131     inline bool operator<=(name ## _d x, double y)                      \
00132     { return x < y || x == y; }                                         \
00133     inline bool operator>=(name ## _d x, double y)                      \
00134     { return !(x < y); }                                                \
00135     inline bool operator>(double x, name ## _d y)                       \
00136     { return y < x; }                                                   \
00137     inline bool operator<(double x, name ## _d y)                       \
00138     { return !(y < x || y == x); }                                      \
00139     inline bool operator<=(double x, name ## _d y)                      \
00140     { return !(y < x); }                                                \
00141     inline bool operator>=(double x, name ## _d y)                      \
00142     { return y < x || x == y; }                                         \
00143                                                                         \
00144     inline double Value(name ## _d x)                                   \
00145     { return x.m_value; }                                               \
00146                                                                         \
00147     inline std::ostream& operator<<(std::ostream& os, name ## _d x)     \
00148     { os << Value(x); return os; }                                      \
00149                                                                         \
00150     inline std::istream& operator>>(std::istream& os, name ## _d& x)    \
00151     {                                                                   \
00152         double t;                                                       \
00153         os >> t;                                                        \
00154         x = name ## _d(t);                                              \
00155         return os;                                                      \
00156     }                                                                   \
00157                                                                         \
00158     void dummy_function_to_force_semicolon()
00159 
00168 #define GG_STRONG_INTEGRAL_TYPEDEF(name, type)                          \
00169     GG_STRONG_DOUBLE_TYPEDEF(name);                                     \
00170                                                                         \
00171     type Value(name x);                                                 \
00172                                                                         \
00173     class name :                                                        \
00174         boost::equality_comparable1<name                                \
00175       , boost::equality_comparable2<name, type                          \
00176       , boost::equality_comparable2<name, name ## _d                    \
00177       , boost::equality_comparable2<name, double                        \
00178       , boost::unit_steppable<name                                      \
00179       , boost::integer_arithmetic1<name                                 \
00180       , boost::integer_arithmetic2<name, type                           \
00181       , boost::subtractable2_left<name, type                            \
00182     > > > > > > > >                                                     \
00183     {                                                                   \
00184     private:                                                            \
00185         struct ConvertibleToBoolDummy {int _;};                         \
00186                                                                         \
00187     public:                                                             \
00188         BOOST_STATIC_ASSERT((boost::is_integral<type>::value));         \
00189                                                                         \
00190         name() {}                                                       \
00191         explicit name(type t) : m_value(t) {}                           \
00192         explicit name(name ## _d t) :                                   \
00193             m_value(static_cast<type>(Value(t)))                        \
00194         {}                                                              \
00195                                                                         \
00196         name& operator=(name ## _d t)                                   \
00197         { m_value = static_cast<type>(Value(t)); return *this; }        \
00198                                                                         \
00199         bool operator<(name rhs) const                                  \
00200         { return m_value < rhs.m_value; }                               \
00201         bool operator==(name rhs) const                                 \
00202         { return m_value == rhs.m_value; }                              \
00203                                                                         \
00204         bool operator<(type rhs) const                                  \
00205         { return m_value < rhs; }                                       \
00206         bool operator==(type rhs) const                                 \
00207         { return m_value == rhs; }                                      \
00208                                                                         \
00209         bool operator<(name ## _d rhs) const                            \
00210         { return m_value < Value(rhs); }                                \
00211         bool operator==(name ## _d rhs) const                           \
00212         { return m_value == Value(rhs); }                               \
00213                                                                         \
00214         bool operator<(double rhs) const                                \
00215         { return m_value < rhs; }                                       \
00216         bool operator==(double rhs) const                               \
00217         { return m_value == rhs; }                                      \
00218                                                                         \
00219         operator int ConvertibleToBoolDummy::* () const                 \
00220         { return m_value ? &ConvertibleToBoolDummy::_ : 0; }            \
00221                                                                         \
00222         name operator-() const                                          \
00223         { return name(-m_value); }                                      \
00224                                                                         \
00225         name& operator++()                                              \
00226         { ++m_value; return *this; }                                    \
00227         name& operator--()                                              \
00228         { --m_value; return *this; }                                    \
00229                                                                         \
00230         name& operator+=(name rhs)                                      \
00231         { m_value += rhs.m_value; return *this; }                       \
00232         name& operator-=(name rhs)                                      \
00233         { m_value -= rhs.m_value; return *this; }                       \
00234         name& operator*=(name rhs)                                      \
00235         { m_value *= rhs.m_value; return *this; }                       \
00236         name& operator/=(name rhs)                                      \
00237         { m_value /= rhs.m_value; return *this; }                       \
00238         name& operator%=(name rhs)                                      \
00239         { m_value %= rhs.m_value; return *this; }                       \
00240                                                                         \
00241         name& operator+=(type rhs)                                      \
00242         { m_value += rhs; return *this; }                               \
00243         name& operator-=(type rhs)                                      \
00244         { m_value -= rhs; return *this; }                               \
00245         name& operator*=(type rhs)                                      \
00246         { m_value *= rhs; return *this; }                               \
00247         name& operator/=(type rhs)                                      \
00248         { m_value /= rhs; return *this; }                               \
00249         name& operator%=(type rhs)                                      \
00250         { m_value %= rhs; return *this; }                               \
00251                                                                         \
00252         name& operator+=(name ## _d rhs)                                \
00253         { return operator+=(Value(rhs)); }                              \
00254         name& operator-=(name ## _d rhs)                                \
00255         { return operator-=(Value(rhs)); }                              \
00256         name& operator*=(name ## _d rhs)                                \
00257         { return operator*=(Value(rhs)); }                              \
00258         name& operator/=(name ## _d rhs)                                \
00259         { return operator/=(Value(rhs)); }                              \
00260                                                                         \
00261         name& operator+=(double rhs)                                    \
00262         { m_value = static_cast<type>(m_value + rhs); return *this; }   \
00263         name& operator-=(double rhs)                                    \
00264         { m_value = static_cast<type>(m_value - rhs); return *this; }   \
00265         name& operator*=(double rhs)                                    \
00266         { m_value = static_cast<type>(m_value * rhs); return *this; }   \
00267         name& operator/=(double rhs)                                    \
00268         { m_value = static_cast<type>(m_value / rhs); return *this; }   \
00269                                                                         \
00270     private:                                                            \
00271         type m_value;                                                   \
00272                                                                         \
00273         friend class boost::serialization::access;                      \
00274         template <class Archive>                                        \
00275         void serialize(Archive& ar, const unsigned int version)         \
00276         { ar & BOOST_SERIALIZATION_NVP(m_value); }                      \
00277                                                                         \
00278         friend class name ## _d;                                        \
00279         friend type Value(name x);                                      \
00280     };                                                                  \
00281                                                                         \
00282     inline name ## _d operator+(name x, double y)                       \
00283     { return name ## _d(Value(x)) + y; }                                \
00284     inline name ## _d operator+(double x, name y)                       \
00285     { return x + name ## _d(Value(y)); }                                \
00286                                                                         \
00287     inline name ## _d operator-(name x, double y)                       \
00288     { return name ## _d(Value(x)) - y; }                                \
00289     inline name ## _d operator-(double x, name y)                       \
00290     { return x - name ## _d(Value(y)); }                                \
00291                                                                         \
00292     inline name ## _d operator*(name x, double y)                       \
00293     { return name ## _d(Value(x)) * y; }                                \
00294     inline name ## _d operator*(double x, name y)                       \
00295     { return x * name ## _d(Value(y)); }                                \
00296                                                                         \
00297     inline name ## _d operator/(name x, double y)                       \
00298     { return name ## _d(Value(x)) / y; }                                \
00299                                                                         \
00300     inline bool operator>(name x, name y)                               \
00301     { return y < x; }                                                   \
00302     inline bool operator<=(name x, name y)                              \
00303     { return x < y || x == y; }                                         \
00304     inline bool operator>=(name x, name y)                              \
00305     { return y < x || x == y; }                                         \
00306                                                                         \
00307     inline bool operator>(name x, type y)                               \
00308     { return !(x < y || x == y); }                                      \
00309     inline bool operator<=(name x, type y)                              \
00310     { return x < y || x == y; }                                         \
00311     inline bool operator>=(name x, type y)                              \
00312     { return !(x < y); }                                                \
00313     inline bool operator>(type x, name y)                               \
00314     { return y < x; }                                                   \
00315     inline bool operator<(type x, name y)                               \
00316     { return !(y < x || y == x); }                                      \
00317     inline bool operator<=(type x, name y)                              \
00318     { return !(y < x); }                                                \
00319     inline bool operator>=(type x, name y)                              \
00320     { return y < x || x == y; }                                         \
00321                                                                         \
00322     inline bool operator>(name x, name ## _d y)                         \
00323     { return !(x < y || x == y); }                                      \
00324     inline bool operator<=(name x, name ## _d y)                        \
00325     { return x < y || x == y; }                                         \
00326     inline bool operator>=(name x, name ## _d y)                        \
00327     { return !(x < y); }                                                \
00328     inline bool operator>(name ## _d x, name y)                         \
00329     { return y < x; }                                                   \
00330     inline bool operator<(name ## _d x, name y)                         \
00331     { return !(y < x || y == x); }                                      \
00332     inline bool operator<=(name ## _d x, name y)                        \
00333     { return !(y < x); }                                                \
00334     inline bool operator>=(name ## _d x, name y)                        \
00335     { return y < x || x == y; }                                         \
00336                                                                         \
00337     inline bool operator>(name x, double y)                             \
00338     { return !(x < y || x == y); }                                      \
00339     inline bool operator<=(name x, double y)                            \
00340     { return x < y || x == y; }                                         \
00341     inline bool operator>=(name x, double y)                            \
00342     { return !(x < y); }                                                \
00343     inline bool operator>(double x, name y)                             \
00344     { return y < x; }                                                   \
00345     inline bool operator<(double x, name y)                             \
00346     { return !(y < x || y == x); }                                      \
00347     inline bool operator<=(double x, name y)                            \
00348     { return !(y < x); }                                                \
00349     inline bool operator>=(double x, name y)                            \
00350     { return y < x || x == y; }                                         \
00351                                                                         \
00352     inline type Value(name x)                                           \
00353     { return x.m_value; }                                               \
00354                                                                         \
00355     inline std::ostream& operator<<(std::ostream& os, name x)           \
00356     { os << Value(x); return os; }                                      \
00357                                                                         \
00358     inline std::istream& operator>>(std::istream& os, name& x)          \
00359     {                                                                   \
00360         type t;                                                         \
00361         os >> t;                                                        \
00362         x = name(t);                                                    \
00363         return os;                                                      \
00364     }                                                                   \
00365                                                                         \
00366     inline name ## _d& name ## _d::operator+=(name rhs)                 \
00367     { m_value += rhs.m_value; return *this; }                           \
00368     inline name ## _d& name ## _d::operator-=(name rhs)                 \
00369     { m_value -= rhs.m_value; return *this; }                           \
00370     inline name ## _d& name ## _d::operator*=(name rhs)                 \
00371     { m_value *= rhs.m_value; return *this; }                           \
00372     inline name ## _d& name ## _d::operator/=(name rhs)                 \
00373     { m_value /= rhs.m_value; return *this; }                           \
00374                                                                         \
00375     inline name ## _d operator+(name lhs, name ## _d rhs)               \
00376     { return rhs += lhs; }                                              \
00377     inline name ## _d operator-(name lhs, name ## _d rhs)               \
00378     { return lhs - Value(rhs); }                                        \
00379     inline name ## _d operator*(name lhs, name ## _d rhs)               \
00380     { return rhs *= lhs; }                                              \
00381     inline name ## _d operator/(name lhs, name ## _d rhs)               \
00382     { return lhs / Value(rhs); }                                        \
00383                                                                         \
00384     inline name ## _d name ## _d::operator+(name rhs)                   \
00385     { return name ## _d(m_value + rhs.m_value); }                       \
00386     inline name ## _d name ## _d::operator-(name rhs)                   \
00387     { return name ## _d(m_value - rhs.m_value); }                       \
00388     inline name ## _d name ## _d::operator*(name rhs)                   \
00389     { return name ## _d(m_value * rhs.m_value); }                       \
00390     inline name ## _d name ## _d::operator/(name rhs)                   \
00391     { return name ## _d(m_value / rhs.m_value); }                       \
00392                                                                         \
00393     void dummy_function_to_force_semicolon()
00394 
00400 #define GG_STRONG_SIZE_TYPEDEF(name)                                    \
00401     class name;                                                         \
00402     std::size_t Value(name x);                                          \
00403                                                                         \
00404     class name :                                                        \
00405         boost::equality_comparable1<name                                \
00406       , boost::equality_comparable2<name, std::size_t                   \
00407       , boost::unit_steppable<name                                      \
00408       , boost::integer_arithmetic1<name                                 \
00409       , boost::integer_arithmetic2<name, std::size_t                    \
00410       , boost::subtractable2_left<name, std::size_t                     \
00411     > > > > > >                                                         \
00412     {                                                                   \
00413     private:                                                            \
00414         struct ConvertibleToBoolDummy {int _;};                         \
00415                                                                         \
00416     public:                                                             \
00417         name() {}                                                       \
00418         explicit name(std::size_t t) : m_value(t) {}                    \
00419                                                                         \
00420         bool operator<(name rhs) const                                  \
00421         { return m_value < rhs.m_value; }                               \
00422         bool operator==(name rhs) const                                 \
00423         { return m_value == rhs.m_value; }                              \
00424                                                                         \
00425         bool operator<(std::size_t rhs) const                           \
00426         { return m_value < rhs; }                                       \
00427         bool operator==(std::size_t rhs) const                          \
00428         { return m_value == rhs; }                                      \
00429                                                                         \
00430         operator int ConvertibleToBoolDummy::* () const                 \
00431         { return m_value ? &ConvertibleToBoolDummy::_ : 0; }            \
00432                                                                         \
00433         name operator-() const                                          \
00434         { return name(-m_value); }                                      \
00435                                                                         \
00436         name& operator++()                                              \
00437         { ++m_value; return *this; }                                    \
00438         name& operator--()                                              \
00439         { --m_value; return *this; }                                    \
00440                                                                         \
00441         name& operator+=(name rhs)                                      \
00442         { m_value += rhs.m_value; return *this; }                       \
00443         name& operator-=(name rhs)                                      \
00444         { m_value -= rhs.m_value; return *this; }                       \
00445         name& operator*=(name rhs)                                      \
00446         { m_value *= rhs.m_value; return *this; }                       \
00447         name& operator/=(name rhs)                                      \
00448         { m_value /= rhs.m_value; return *this; }                       \
00449         name& operator%=(name rhs)                                      \
00450         { m_value %= rhs.m_value; return *this; }                       \
00451                                                                         \
00452         name& operator+=(std::size_t rhs)                               \
00453         { m_value += rhs; return *this; }                               \
00454         name& operator-=(std::size_t rhs)                               \
00455         { m_value -= rhs; return *this; }                               \
00456         name& operator*=(std::size_t rhs)                               \
00457         { m_value *= rhs; return *this; }                               \
00458         name& operator/=(std::size_t rhs)                               \
00459         { m_value /= rhs; return *this; }                               \
00460         name& operator%=(std::size_t rhs)                               \
00461         { m_value %= rhs; return *this; }                               \
00462                                                                         \
00463     private:                                                            \
00464         std::size_t m_value;                                            \
00465                                                                         \
00466         friend class boost::serialization::access;                      \
00467         template <class Archive>                                        \
00468         void serialize(Archive& ar, const unsigned int version)         \
00469         { ar & BOOST_SERIALIZATION_NVP(m_value); }                      \
00470                                                                         \
00471         friend class name ## _d;                                        \
00472         friend std::size_t Value(name x);                               \
00473     };                                                                  \
00474                                                                         \
00475     inline bool operator>(name x, name y)                               \
00476     { return y < x; }                                                   \
00477     inline bool operator<=(name x, name y)                              \
00478     { return x < y || x == y; }                                         \
00479     inline bool operator>=(name x, name y)                              \
00480     { return y < x || x == y; }                                         \
00481                                                                         \
00482     inline bool operator>(name x, std::size_t y)                        \
00483     { return !(x < y || x == y); }                                      \
00484     inline bool operator<=(name x, std::size_t y)                       \
00485     { return x < y || x == y; }                                         \
00486     inline bool operator>=(name x, std::size_t y)                       \
00487     { return !(x < y); }                                                \
00488     inline bool operator>(std::size_t x, name y)                        \
00489     { return y < x; }                                                   \
00490     inline bool operator<(std::size_t x, name y)                        \
00491     { return !(y < x || y == x); }                                      \
00492     inline bool operator<=(std::size_t x, name y)                       \
00493     { return !(y < x); }                                                \
00494     inline bool operator>=(std::size_t x, name y)                       \
00495     { return y < x || x == y; }                                         \
00496                                                                         \
00497     inline std::size_t Value(name x)                                    \
00498     { return x.m_value; }                                               \
00499                                                                         \
00500     inline std::ostream& operator<<(std::ostream& os, name x)           \
00501     { os << Value(x); return os; }                                      \
00502                                                                         \
00503     inline std::istream& operator>>(std::istream& os, name& x)          \
00504     {                                                                   \
00505         std::size_t t;                                                  \
00506         os >> t;                                                        \
00507         x = name(t);                                                    \
00508         return os;                                                      \
00509     }                                                                   \
00510                                                                         \
00511     void dummy_function_to_force_semicolon()
00512 
00513 #endif // _GG_StrongTypedef_h_

Generated on Sat Mar 26 07:08:37 2011 for GG by  doxygen 1.5.9