EnumSet.hxx

Go to the documentation of this file.
00001 #ifndef LIBSHERPA_ENUMSET_HXX
00002 #define LIBSHERPA_ENUMSET_HXX
00003 
00004 /**************************************************************************
00005  *
00006  * Copyright (C) 2010, The EROS Group, LLC.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or
00010  * without modification, are permitted provided that the following
00011  * conditions are met:
00012  *
00013  *   - Redistributions of source code must contain the above
00014  *     copyright notice, this list of conditions, and the following
00015  *     disclaimer.
00016  *
00017  *   - Redistributions in binary form must reproduce the above
00018  *     copyright notice, this list of conditions, and the following
00019  *     disclaimer in the documentation and/or other materials
00020  *     provided with the distribution.
00021  *
00022  *   - Neither the names of the copyright holders nor the names of any
00023  *     of any contributors may be used to endorse or promote products
00024  *     derived from this software without specific prior written
00025  *     permission.
00026  *
00027  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00028  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00029  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00030  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00031  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00032  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00033  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00034  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00035  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00036  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00037  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00038  *
00039  **************************************************************************/
00040 
00041 #include <boost/utility/enable_if.hpp>
00042 #include <boost/type_traits/is_enum.hpp>
00043 
00044 namespace sherpa {
00045 
00067 
00068   template <class T>
00069   class EnumSet {
00070 
00071     // Ensure that this class will only instantiate over enumeration
00072     // types.
00073     //
00074     // If this is being instantiated over an enumeration type, the
00075     // following enable_if_c does the right thing by selecting the
00076     // underlying unsigned type.
00077     //
00078     // If this is being instantiated over a non-enumeral type, then we
00079     // need a construct that will select the repr type
00080     // conditionally. There are template metaprogramming techniques
00081     // for that, but I haven't had a chance to brush up on them. In
00082     // non-enumeration cases, it is imperative to disable the
00083     // top-level overloads on const T& at botom, which I am already
00084     // doing. See comments there.
00085     typename boost::enable_if_c<boost::is_enum<T>::value, unsigned long>::type repr;
00086 
00087     struct BoolConversionSupport {
00088       int dummy;
00089     };
00090 
00091   public:
00092     EnumSet()
00093       :repr((T)0)
00094     {
00095     }
00096 
00097     EnumSet(const EnumSet<T>& that)
00098     {
00099       repr = that.repr;
00100     }
00101 
00102     // Constructor from underlying repr type
00103     EnumSet(const T& that)
00104     {
00105       repr = that;
00106     }
00107 
00108     // Comparison operators
00109     bool
00110     operator==(const EnumSet<T>& that) const
00111     {
00112       return (repr == that.repr);
00113     }
00114 
00115     bool
00116     operator!=(const EnumSet<T>& that) const
00117     {
00118       return (repr != that.repr);
00119     }
00120 
00121     // Assignment operators
00122     EnumSet<T>&
00123     operator=(const EnumSet<T>& that)
00124     {
00125       repr = that.repr;
00126       return *this;
00127     }
00128 
00129     EnumSet<T>&
00130     operator |=(const EnumSet<T>& that)
00131     {
00132       repr |= that.repr;
00133       return *this;
00134     }
00135 
00136     EnumSet<T>&
00137     operator &=(const EnumSet<T>& that)
00138     {
00139       repr &= that.repr;
00140       return *this;
00141     }
00142 
00143     EnumSet<T>&
00144     operator ^=(const EnumSet<T>& that)
00145     {
00146       repr ^= that.repr;
00147       return *this;
00148     }
00149 
00150 
00151 
00152     // Set operators over EnumSet:
00153     EnumSet
00154     operator |(const EnumSet<T>& that) const
00155     {
00156       EnumSet b(*this);
00157       b |= that;
00158       return b;
00159     }
00160 
00161     EnumSet
00162     operator &(const EnumSet<T>& that) const
00163     {
00164       EnumSet b(*this);
00165       b &= that;
00166       return b;
00167     }
00168 
00169     EnumSet
00170     operator ^(const EnumSet<T>& that) const
00171     {
00172       EnumSet b(*this);
00173       b ^= that;
00174       return b;
00175     }
00176 
00177     // Set negation:
00178     EnumSet
00179     operator ~() const
00180     {
00181       EnumSet b(*this);
00182       b.repr = ~b.repr;
00183       return b;
00184     }
00185 
00186     bool
00187     lacks(const EnumSet<T>& that) const
00188     {
00189       if (repr & that.repr)
00190         return false;
00191       return true;
00192     }
00193 
00194 #if 0
00195     // Set sum:
00196     EnumSet
00197     operator +(const EnumSet<T>& that) const
00198     {
00199       EnumSet b(b.repr | that.repr);
00200       return b;
00201     }
00202 
00203     // Set difference:
00204     EnumSet
00205     operator -(const EnumSet<T>& that) const
00206     {
00207       EnumSet b(b.repr & ~that.repr);
00208       return b;
00209     }
00210 #endif
00211 
00212 #if 0
00213     // Set sum:
00214     EnumSet<T>&
00215     operator +=(const EnumSet<T>& that)
00216     {
00217       *this = (repr | that.repr);
00218       return *this;
00219     }
00220 
00221     // Set difference:
00222     EnumSet<T>&
00223     operator -=(const EnumSet<T>& that)
00224     {
00225       *this = (repr & ~that.repr);
00226       return *this;
00227     }
00228 #endif
00229 
00230     // Sleazy support for if(EnumSet):
00231     inline operator int BoolConversionSupport::*() const
00232     {
00233       return (repr == 0) ? 0 : &BoolConversionSupport::dummy;
00234     }
00235   };
00236 
00237 
00238   // Operators when RHS is a EnumSet:
00239   template <class T>
00240   inline EnumSet<T> operator | (const T& lhs, const EnumSet<T>& rhs)
00241   {
00242     return (rhs | EnumSet<T>(lhs));
00243   }
00244 
00245   template <class T>
00246   inline EnumSet<T> operator & (const T& lhs, const EnumSet<T>& rhs)
00247   {
00248     return (rhs & EnumSet<T>(lhs));
00249   }
00250 
00251   template <class T>
00252   inline EnumSet<T> operator ^ (const T& lhs, const EnumSet<T>& rhs)
00253   {
00254     return (rhs ^ EnumSet<T>(lhs));
00255   }
00256 
00257   // Combining operators when both sides are of underlying enumeral
00258   // type.
00259   //
00260   // These MUST NOT be expanded if the underlying type is some form of
00261   // integer type, because that will lead to a recursive expansion
00262   // error (or at least, it will when I fix the use of enable_if_c
00263   // properly above).
00264   template <class T>
00265   inline
00266   typename boost::enable_if_c<boost::is_enum<T>::value, EnumSet<T> >::type
00267   operator | (const T& lhs, const T& rhs)
00268   {
00269     return (EnumSet<T>(lhs) | EnumSet<T>(rhs));
00270   }
00271 
00272   template <class T>
00273   inline
00274   typename boost::enable_if_c<boost::is_enum<T>::value, EnumSet<T> >::type
00275   operator & (const T& lhs, const T& rhs)
00276   {
00277     return (EnumSet<T>(lhs) & EnumSet<T>(rhs));
00278   }
00279 
00280   template <class T>
00281   inline
00282   typename boost::enable_if_c<boost::is_enum<T>::value, EnumSet<T> >::type
00283   operator ^ (const T& lhs, const T& rhs)
00284   {
00285     return (EnumSet<T>(lhs) ^ EnumSet<T>(rhs));
00286   }
00287 
00288   // Unary bitwise negate on underlying type:
00289   template <class T>
00290   inline
00291   typename boost::enable_if_c<boost::is_enum<T>::value, EnumSet<T> >::type
00292   operator ~(const T& lhs)
00293   {
00294     return ~EnumSet<T>(lhs);
00295   }
00296 
00297 } /* namespace sherpa */
00298 
00299 #endif /* LIBSHERPA_ENUMSET_HXX */

Generated on Sat Feb 4 23:59:28 2012 for BitC Compiler by  doxygen 1.4.7