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