EnumWrapper.h

Go to the documentation of this file.
00001 /*
00002  * The information in this file is
00003  * Copyright(c) 2007 Ball Aerospace & Technologies Corporation
00004  * and is subject to the terms and conditions of the
00005  * GNU Lesser General Public License Version 2.1
00006  * The license text is available from   
00007  * http://www.gnu.org/licenses/lgpl.html
00008  */
00009 
00010 #ifndef ENUMWRAPPER_H
00011 #define ENUMWRAPPER_H
00012 
00013 /**
00014  * \page EnumWrapperHowTo How To Use EnumWrapper
00015  * The EnumWrapper is a templated class that
00016  * allows enumeration values to be used safely.
00017  * The EnumWrapper class contains both the enumerated
00018  * value being wrapped and a boolean that indicates
00019  * whether the contained enumerated value is valid and
00020  * can be used.  The following examples show usage
00021  * of the class:
00022  *
00023  * \code
00024  * enum TestEnumeration { ENUM_VALUE1, ENUM_VALUE2, ENUM_VALUE2 };
00025  * EnumWrapper<TestEnumeration> test1;
00026  * test1.isValid(); //this will return false
00027  * //The following line is bad, it will convert EnumWrapper to TestEnumeration
00028  * //but the enumVal1 value will be undefined since the EnumWrapper.isValid()
00029  * //method returns false.
00030  * TestEnumeration enumVal1 = test1;
00031  *
00032  * test1 < ENUM_VALUE1; //false because test1 is invalid
00033  * ENUM_VALUE1 < test1; //true because test1 is invalid
00034  *
00035  * test1 == ENUM_VALUE1; //false because test1 is invalid
00036  * ENUM_VALUE1 == test1; //false because test1 is invalid
00037  *
00038  * EnumWrapper<TestEnumeration> test2(ENUM_VALUE1);
00039  * test2.isValid(); //this will return true
00040  * TestEnumeration enumVal2 = test2; //enumVal2 == ENUM_VALUE1;
00041  *
00042  * EnumWrapper<TestEnumeration> test3(test2);
00043  * TestEnumeration enumVal3 = test3; //enumVal3 == ENUM_VALUE1;
00044  *
00045  * EnumWrapper<TestEnumeration> test4;
00046  * EnumWrapper<TestEnumeration> test5 = ENUM_VALUE2;
00047  * TestEnumeration enumVal4 = test5; //enumVal4 == ENUM_VALUE2;
00048  * test4.isValid(); //this will return false
00049  * test4 = test5;
00050  * test4.isValid(); //this will return true
00051  * TestEnumeration enumVal5 = test4; //enumVal5 = ENUM_VALUE2;
00052  *
00053  * //It is generally recommended to create a typedef for your specific
00054  * //usage of EnumWrapper, as shown below
00055  *
00056  * typedef EnumWrapper<TestEnumeration> TestEnum;
00057  *
00058  * //You can then do the following:
00059  *
00060  * bool testEnumValue(TestEnum val)
00061  * {
00062  *    if (!val.isValid())
00063  *    {
00064  *       return false;
00065  *    }
00066  *    if ((val == ENUM_VALUE1) || (val == ENUM_VALUE3))
00067  *    {
00068  *       return true;
00069  *    }
00070  *    return false;
00071  * }
00072  *
00073  * TestEnum getValue()
00074  * {
00075  *    return ENUM_VALUE2;
00076  * }
00077  *
00078  * TestEnum getInvalidValue()
00079  * {
00080  *    TestEnum retVal;
00081  *    return retVal;
00082  * }
00083  *
00084  * testEnumValue(ENUM_VALUE1); //the function returns true
00085  * testEnumValue(ENUM_VALUE2); //the function returns false
00086  * TestEnum test6 = ENUM_VALUE3;
00087  * testEnumValue(test6); //the function returns true
00088  * TestEnum test7;
00089  * testEnumValue(test7); //the function returns false because test7.isValid() returns false
00090  *
00091  * TestEnum test8 = getValue();
00092  * (test8 == ENUM_VALUE2); //evaluates to true
00093  * test8.isValid(); //returns true
00094  *
00095  * TestEnum test9 = getInvalidValue();
00096  * test9.isValid(); //returns false
00097  * TestEnumeration enumVal6 = test9; //DON'T DO THIS.  The value of enumVal6 is undefined.
00098  *
00099  * \endcode
00100  */
00101 
00102 /**
00103  * \cond INTERNAL
00104  * This class is protected by the INTERNAL condition which hides the documentation of this class.
00105  * This is being done because in version 1.5.1-p1 of Doxygen any links to typedefs using
00106  * this templated class would point directly to the documentation of this class, but would
00107  * not show the template argument used in the typedef.  For instance, if the following
00108  * typedef were present:
00109  *
00110  * typedef EnumWrapper<SymbolTypeEnum> SymbolType
00111  *
00112  * Then when a user clicked on SymbolType in the doxygen generated documentation they
00113  * would be taken to the EnumWrapper class documentation, but with no indicator that
00114  * SymbolTypeEnum was the template argument.  In order to fix, this the documentation
00115  * of this class is hidden using the condition support of Doxygen.  When this is done
00116  * when clicking on SymbolType, the user will be taken to the documentation of the typedef
00117  * statement which does show the user both the use of the EnumWrapper class and the
00118  * template argument to the EnumWrapper class.
00119  */
00120 template<typename EnumValue>
00121 class EnumWrapper
00122 {
00123 public:
00124    /**
00125     * The enumerated type this EnumWapper is wrapping.  Use this when
00126     * the raw enumerated type is required.
00127     */
00128    typedef EnumValue EnumType;
00129 
00130    /**
00131     * Default construct so that isValid() will return false.
00132     */
00133    EnumWrapper() : mIsValid(false), mValue()
00134    {
00135    }
00136 
00137    /**
00138     * Construct an instance with the given wrapped enumeration value.
00139     * Calling isValid() will return true.
00140     *
00141     * @param value
00142     *        the enumerated value to be wrapped.
00143     */
00144    EnumWrapper(const EnumValue& value) : mIsValid(true), mValue(value)
00145    {
00146    }
00147 
00148    /**
00149     * Destructor.
00150     */
00151    ~EnumWrapper()
00152    {}
00153 
00154    /**
00155     * Queries whether the contained enum value is
00156     * valid and can be used.
00157     * 
00158     * @return Returns true if the enumeration value being
00159     * wrapped is valid.  Returns false otherwise.
00160     * 
00161     * @see EnumWrapper()
00162     */
00163    bool isValid() const
00164    {
00165       return mIsValid;
00166    }
00167 
00168    /**
00169     * Converts the contained value to the
00170     * given enum type.
00171     *
00172     * @return Returns the wrapped enum value if isValid() would return true.
00173     *         Returns an undefined value if isValid() would return false.
00174     *
00175     * @warning UNDER NO CIRCUMSTANCES should you rely on a defined value being returned
00176     *          if isValid() would return false.
00177     */
00178    operator EnumValue() const
00179    {
00180       if (mIsValid)
00181       {
00182          return mValue;
00183       }
00184       else
00185       {
00186          //We are returning a value if the EnumWrapper is invalid
00187          //that is highly unlikely to be a valid value for all
00188          //enums.  This is to in the general case cause switch()
00189          //statements using an EnumWrapper to fall into the
00190          //default case if a call on isValid() was not made.
00191          //Without this, an invalid EnumWrapper would most likely
00192          //return 0 on a variety of compilers which would hide
00193          //the problem in a switch statement.
00194          return static_cast<EnumValue>(-1);
00195       }
00196    }
00197 
00198    /**
00199     * Determines if this EnumWrapper is equal to another.
00200     *
00201     * @param rhs
00202     *        The object being compared.
00203     * 
00204     * @return Returns true if both EnumWrappers are
00205     *         valid and their wrapped enum values are equal. Returns
00206     *         true if both EnumWrappers are invalid regardless of
00207     *         their wrapped (ie. undefined) values. Returns false in all other
00208     *         cases.
00209     */
00210    bool operator==(const EnumWrapper& rhs) const
00211    {
00212       return ( (mIsValid && rhs.mIsValid && mValue == rhs.mValue) ||
00213                (!mIsValid && !rhs.mIsValid) );
00214    }
00215 
00216    /**
00217     * Determines if this EnumWrapper is equal to an enum value.
00218     *
00219     * @param enumVal
00220     *        The value being compared.
00221     *
00222     * @return Returns true if the EnumWrapper is valid
00223     *         and the wrapped enum value is equal to enumVal, false
00224     *         otherwise.
00225     */
00226    bool operator==(const EnumValue& enumVal) const
00227    {
00228       return (mIsValid && mValue == enumVal);
00229    }
00230 
00231    /**
00232     * Determines if this EnumWrapper is not equal to another.
00233     *
00234     * @param rhs
00235     *        The object being compared.
00236     *
00237     * @return Returns true if the EnumWrappers are not
00238     * equal, false otherwise.
00239     *
00240     * @see operator==()
00241     */
00242    bool operator!=(const EnumWrapper& rhs) const
00243    {
00244       return !(operator==(rhs));
00245    }
00246 
00247    /**
00248     * Determines if this EnumWrapper is not equal to an enum value.
00249     *
00250     * @param enumVal
00251     *        The value being compared.
00252     *
00253     * @return Returns true if the EnumWrapper is valid
00254     *         and the wrapped enum value is not equal to than enumVal, false
00255     *         otherwise.
00256     */
00257    bool operator!=(const EnumValue& enumVal) const
00258    {
00259       return !(operator==(enumVal));
00260    }
00261 
00262    /**
00263     * Determines if this EnumWrapper is less than another.
00264     *
00265     * @param rhs
00266     *        The object being compared.
00267     * 
00268     * @return Returns true if both EnumWrappers are
00269     *         valid and the wrapped enum value is less than the
00270     *         wrapped enum value of rhs.  Returns true
00271     *         if this EnumWrapper is valid, but the rhs is invalid.
00272     *         Returns false otherwise.
00273     */
00274    bool operator<(const EnumWrapper& rhs) const
00275    {
00276       if (mIsValid)
00277       {
00278          if (rhs.mIsValid)
00279          {
00280             return mValue < rhs.mValue;
00281          }
00282          else
00283          {
00284             return true; //valid < invalid == true
00285          }
00286       }
00287       else
00288       {
00289          if (rhs.mIsValid)
00290          {
00291             return false; //invalid < valid == false
00292          }
00293          else
00294          {
00295             return false; //invalid < invalid == false
00296          }
00297       }
00298    }
00299 
00300    /**
00301     * Determines if this EnumWrapper is less than an enum value.
00302     *
00303     * @param enumVal
00304     *        The value being compared.
00305     *
00306     * @return Returns true if the EnumWrapper is valid
00307     *         and the wrapped enum value is less than enumVal, false
00308     *         otherwise.
00309     */
00310    bool operator<(const EnumValue& enumVal) const
00311    {
00312       if (mIsValid)
00313       {
00314          return mValue < enumVal;
00315       }
00316       else
00317       {
00318          return false;
00319       }
00320    }
00321 
00322    /**
00323     * Determines if this EnumWrapper is less than or equal to another.
00324     *
00325     * @param rhs
00326     *        The object being compared.
00327     *
00328     * @return Returns true if the EnumWrappers are less than or
00329     * equal, false otherwise. 
00330     *
00331     * @see operator==(), operator<()
00332     */
00333    bool operator<=(const EnumWrapper& rhs) const
00334    {
00335       return operator<(rhs) || operator==(rhs);
00336    }
00337 
00338    /**
00339     * Determines if this EnumWrapper is less than or equal to an enum value.
00340     *
00341     * @param enumVal
00342     *        The value being compared.
00343     *
00344     * @return Returns true if the EnumWrapper is valid
00345     *         and the wrapped enum value is less than or equal to enumVal,
00346     *         false otherwise.
00347     */
00348    bool operator<=(const EnumValue& enumVal) const
00349    {
00350       return operator<(enumVal) || operator==(enumVal);
00351    }
00352 
00353    /**
00354     * Determines if this EnumWrapper is greater than another.
00355     *
00356     * @param rhs
00357     *        The object being compared.
00358     *
00359     * @return Returns true if the EnumWrappers are greater than
00360     * each other, false otherwise.
00361     *
00362     * @see operator==(), operator<()
00363     */
00364    bool operator>(const EnumWrapper& rhs) const
00365    {
00366       return !(operator<=(rhs));
00367    }
00368 
00369    /**
00370     * Determines if this EnumWrapper is greater than an enum value.
00371     *
00372     * @param enumVal
00373     *        The value being compared.
00374     *
00375     * @return Returns true if the EnumWrapper is valid
00376     *         and the wrapped enum value is greater than enumVal,
00377     *         false otherwise.
00378     */
00379    bool operator>(const EnumValue& enumVal) const
00380    {
00381       return !(operator<=(enumVal));
00382    }
00383 
00384    /**
00385     * Determines if this EnumWrapper is greater than or equal to another.
00386     *
00387     * @param rhs
00388     *        The object being compared.
00389     *
00390     * @return Returns true if the EnumWrappers are greater than or
00391     * equal, false otherwise. 
00392     *
00393     * @see operator==(), operator<()
00394     */
00395    bool operator>=(const EnumWrapper& rhs) const
00396    {
00397       return !(operator<(rhs));
00398    }
00399 
00400    /**
00401     * Determines if this EnumWrapper is greater than or equal to an enum value.
00402     *
00403     * @param enumVal
00404     *        The value being compared.
00405     *
00406     * @return Returns true if the EnumWrapper is valid
00407     *         and the wrapped enum value is greater than or equal to enumVal,
00408     *         false otherwise.
00409     */
00410    bool operator>=(const EnumValue& enumVal) const
00411    {
00412       return !(operator<(enumVal));
00413    }
00414 
00415 private:
00416    bool mIsValid;
00417    EnumValue mValue;
00418 };
00419 
00420 /**
00421  * Determines if a enum value and EnumWrapper are equal.
00422  *
00423  * @param lhs
00424  *        The value being compared.
00425  * @param rhs
00426  *        The object being compared.
00427  *
00428  * @return Returns true if the enum value and EnumWrapper are equal.
00429  *
00430  * @see EnumWrapper::operator==()
00431  */
00432 template <typename T>
00433 bool operator==(const T& lhs, const EnumWrapper<T>& rhs)
00434 {
00435    return EnumWrapper<T>(lhs) == rhs;
00436 }
00437 
00438 /**
00439  * Determines if a enum value and EnumWrapper are not equal.
00440  *
00441  * @param lhs
00442  *        The value being compared.
00443  * @param rhs
00444  *        The object being compared.
00445  *
00446  * @return Returns true if the enum value and EnumWrapper are not equal.
00447  *
00448  * @see EnumWrapper::operator!=()
00449  */
00450 template <typename T>
00451 bool operator!=(const T& lhs, const EnumWrapper<T>& rhs)
00452 {
00453    return EnumWrapper<T>(lhs) != rhs;
00454 }
00455 
00456 /**
00457  * Determines if a enum value is less than the EnumWrapper.
00458  *
00459  * @param lhs
00460  *        The value being compared.
00461  * @param rhs
00462  *        The object being compared.
00463  *
00464  * @return Returns true if the enum value is less than the EnumWrapper.
00465  *
00466  * @see EnumWrapper::operator<()
00467  */
00468 template <typename T>
00469 bool operator<(const T& lhs, const EnumWrapper<T>& rhs)
00470 {
00471    return EnumWrapper<T>(lhs) < rhs;
00472 }
00473 
00474 /**
00475  * Determines if a enum value is less than or equal to the EnumWrapper.
00476  *
00477  * @param lhs
00478  *        The value being compared.
00479  * @param rhs
00480  *        The object being compared.
00481  *
00482  * @return Returns true if the enum value is less than or equal to the EnumWrapper.
00483  *
00484  * @see EnumWrapper::operator<=()
00485  */
00486 template <typename T>
00487 bool operator<=(const T& lhs, const EnumWrapper<T>& rhs)
00488 {
00489    return EnumWrapper<T>(lhs) <= rhs;
00490 }
00491 
00492 /**
00493  * Determines if a enum value is greater than the EnumWrapper.
00494  *
00495  * @param lhs
00496  *        The value being compared.
00497  * @param rhs
00498  *        The object being compared.
00499  *
00500  * @return Returns true if the enum value is greater than the EnumWrapper.
00501  *
00502  * @see EnumWrapper::operator>()
00503  */
00504 template <typename T>
00505 bool operator>(const T& lhs, const EnumWrapper<T>& rhs)
00506 {
00507    return EnumWrapper<T>(lhs) > rhs;
00508 }
00509 
00510 /**
00511  * Determines if a enum value is greater than or equal to the EnumWrapper.
00512  *
00513  * @param lhs
00514  *        The value being compared.
00515  * @param rhs
00516  *        The object being compared.
00517  *
00518  * @return Returns true if the enum value is greater than or equal to the EnumWrapper.
00519  *
00520  * @see EnumWrapper::operator>=()
00521  */
00522 template <typename T>
00523 bool operator>=(const T& lhs, const EnumWrapper<T>& rhs)
00524 {
00525    return EnumWrapper<T>(lhs) >= rhs;
00526 }
00527 
00528 /// \endcond
00529 
00530 #endif

Software Development Kit - Opticks 4.9.0 Build 16218