Changeset 2171 for code/trunk/src/util/Convert.h
- Timestamp:
- Nov 10, 2008, 12:05:03 AM (16 years ago)
- Location:
- code/trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk
- Property svn:mergeinfo changed
/code/branches/objecthierarchy merged: 2111-2115,2123,2132-2134,2143-2144,2153-2158,2160-2169
- Property svn:mergeinfo changed
-
code/trunk/src/util
- Property svn:mergeinfo changed
/code/branches/objecthierarchy/src/util merged: 2111,2114,2123,2155,2158,2161-2162
- Property svn:mergeinfo changed
-
code/trunk/src/util/Convert.h
r2087 r2171 68 68 #endif 69 69 70 template <class FromType, class ToType> 71 class ImplicitConversion 72 { 73 private: 74 ImplicitConversion(); ImplicitConversion(const ImplicitConversion&); ~ImplicitConversion(); 75 // Gets chosen only if there is an implicit conversion from FromType to ToType. 76 static char test(ToType); 77 // Accepts any argument. Why do we not use a template? The reason is that with templates, 78 // the function above is only taken iff it is an exact type match. But since we want to 79 // check for implicit conversion, we have to use the ellipsis. 80 static long long test(...); 81 static FromType object; // helper object to handle private c'tor and d'tor 82 public: 83 // test(object) only has 'long long' return type iff the compiler doesn't choose test(...) 84 enum { exists = (sizeof(test(object)) == sizeof(char)) }; 85 }; 70 namespace orxonox 71 { 72 template <class FromType, class ToType> 73 class ImplicitConversion 74 { 75 private: 76 ImplicitConversion(); ImplicitConversion(const ImplicitConversion&); ~ImplicitConversion(); 77 // Gets chosen only if there is an implicit conversion from FromType to ToType. 78 static char test(ToType); 79 // Accepts any argument. Why do we not use a template? The reason is that with templates, 80 // the function above is only taken iff it is an exact type match. But since we want to 81 // check for implicit conversion, we have to use the ellipsis. 82 static long long test(...); 83 static FromType object; // helper object to handle private c'tor and d'tor 84 public: 85 // test(object) only has 'long long' return type iff the compiler doesn't choose test(...) 86 enum { exists = (sizeof(test(object)) == sizeof(char)) }; 87 }; 88 } 86 89 87 90 #if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC … … 118 121 */ 119 122 120 namespace 121 { 122 //! Little template that maps integers to entire types (Alexandrescu 2001) 123 template <int I> 124 struct Int2Type { }; 123 namespace orxonox 124 { 125 namespace 126 { 127 //! Little template that maps integers to entire types (Alexandrescu 2001) 128 template <int I> 129 struct Int2Type { }; 130 } 131 132 133 /////////////////// 134 // No Conversion // 135 /////////////////// 136 137 // Default template. No conversion available at all. 138 template <class FromType, class ToType> 139 struct ConverterFallback 140 { 141 static bool convert(ToType* output, const FromType& input) 142 { 143 COUT(2) << "Could not convert value of type " << typeid(FromType).name() 144 << " to type " << typeid(ToType).name() << std::endl; 145 return false; 146 } 147 }; 148 149 // If all else fails, try a dynamic_cast for pointer types. 150 template <class FromType, class ToType> 151 struct ConverterFallback<FromType*, ToType*> 152 { 153 static bool convert(ToType** output, FromType* const input) 154 { 155 ToType* temp = dynamic_cast<ToType*>(input); 156 if (temp) 157 { 158 *output = temp; 159 return true; 160 } 161 else 162 return false; 163 } 164 }; 125 165 } 126 127 128 ///////////////////129 // No Conversion //130 ///////////////////131 132 // Default template. No conversion available at all.133 template <class FromType, class ToType>134 struct ConverterFallback135 {136 static bool convert(ToType* output, const FromType& input)137 {138 COUT(2) << "Could not convert value of type " << typeid(FromType).name()139 << " to type " << typeid(ToType).name() << std::endl;140 return false;141 }142 };143 144 // If all else fails, try a dynamic_cast for pointer types.145 template <class FromType, class ToType>146 struct ConverterFallback<FromType*, ToType*>147 {148 static bool convert(ToType** output, FromType* const input)149 {150 ToType* temp = dynamic_cast<ToType*>(input);151 if (temp)152 {153 *output = temp;154 return true;155 }156 else157 return false;158 }159 };160 166 161 167 … … 170 176 static bool convert(ToType* output, const FromType& input) 171 177 { 172 return ConverterFallback<FromType, ToType>::convert(output, input);178 return orxonox::ConverterFallback<FromType, ToType>::convert(output, input); 173 179 } 174 180 }; … … 185 191 { 186 192 std::string temp; 187 if ( ConverterFallback<FromType, std::string>::convert(&temp, input))193 if (orxonox::ConverterFallback<FromType, std::string>::convert(&temp, input)) 188 194 { 189 195 std::operator <<(outstream, temp); … … 224 230 inline bool operator >>(std::istream& instream, ToType& output) 225 231 { 226 return ConverterFallback<std::string, ToType>232 return orxonox::ConverterFallback<std::string, ToType> 227 233 ::convert(&output, static_cast<std::istringstream&>(instream).str()); 228 234 } … … 247 253 }; 248 254 249 250 /////////////////// 251 // Implicit Cast // 252 /////////////////// 253 254 // implicit cast not possible, try stringstream conversion next 255 template <class FromType, class ToType> 256 inline bool convertImplicitely(ToType* output, const FromType& input, ::Int2Type<false>) 257 { 258 return ConverterStringStream<FromType, ToType>::convert(output, input); 255 namespace orxonox 256 { 257 258 /////////////////// 259 // Implicit Cast // 260 /////////////////// 261 262 // implicit cast not possible, try stringstream conversion next 263 template <class FromType, class ToType> 264 inline bool convertImplicitely(ToType* output, const FromType& input, orxonox::Int2Type<false>) 265 { 266 return ConverterStringStream<FromType, ToType>::convert(output, input); 267 } 268 269 // We can cast implicitely 270 template <class FromType, class ToType> 271 inline bool convertImplicitely(ToType* output, const FromType& input, orxonox::Int2Type<true>) 272 { 273 (*output) = static_cast<ToType>(input); 274 return true; 275 } 276 277 278 //////////////////////////////// 279 // ConverterExplicit Fallback // 280 //////////////////////////////// 281 282 // Default template if no specialisation is available 283 template <class FromType, class ToType> 284 struct ConverterExplicit 285 { 286 static bool convert(ToType* output, const FromType& input) 287 { 288 // Try implict cast and probe first. If a simple cast is not possible, it will not compile 289 // We therefore have to out source it into another template function 290 const bool probe = ImplicitConversion<FromType, ToType>::exists; 291 return convertImplicitely(output, input, orxonox::Int2Type<probe>()); 292 } 293 }; 294 295 296 ////////////////////// 297 // Public Functions // 298 ////////////////////// 299 300 /** 301 @brief 302 Converts any value to any other as long as there exists a conversion. 303 Otherwise, the conversion will generate a runtime warning and return false. 304 For information about the different conversion methods (user defined too), see the section 305 'Actual conversion sequence' in this file above. 306 */ 307 template <class FromType, class ToType> 308 inline bool convertValue(ToType* output, const FromType& input) 309 { 310 return ConverterExplicit<FromType, ToType>::convert(output, input); 311 } 312 313 // For compatibility reasons. The same, but with capital ConvertValue 314 template<class FromType, class ToType> 315 inline bool ConvertValue(ToType* output, const FromType& input) 316 { 317 return convertValue(output, input); 318 } 319 320 // Calls convertValue and returns true if the conversion was successful. 321 // Otherwise the fallback is used. 322 /** 323 @brief 324 Converts any value to any other as long as there exists a conversion. 325 Otherwise, the conversion will generate a runtime warning and return false. 326 For information about the different conversion methods (user defined too), see the section 327 'Actual conversion sequence' in this file above. 328 If the conversion doesn't succeed, 'fallback' is written to '*output'. 329 @param fallback 330 A default value that gets written to '*output' if there is no conversion. 331 */ 332 template<class FromType, class ToType> 333 inline bool convertValue(ToType* output, const FromType& input, const ToType& fallback) 334 { 335 if (convertValue(output, input)) 336 return true; 337 else 338 { 339 (*output) = fallback; 340 return false; 341 } 342 } 343 344 // for compatibility reason. (capital 'c' in ConvertValue) 345 template<class FromType, class ToType> 346 inline bool ConvertValue(ToType* output, const FromType& input, const ToType& fallback) 347 { 348 return convertValue(output, input, fallback); 349 } 350 351 // Directly returns the converted value, even if the conversion was not successful. 352 template<class FromType, class ToType> 353 inline ToType getConvertedValue(const FromType& input) 354 { 355 ToType output; 356 convertValue(&output, input); 357 return output; 358 } 359 360 // Directly returns the converted value, but uses the fallback on failure. 361 template<class FromType, class ToType> 362 inline ToType getConvertedValue(const FromType& input, const ToType& fallback) 363 { 364 ToType output; 365 convertValue(&output, input, fallback); 366 return output; 367 } 368 369 // Like getConvertedValue, but the template argument order is in reverse. 370 // That means you can call it exactly like static_cast<ToType>(fromTypeValue). 371 template<class ToType, class FromType> 372 inline ToType omni_cast(const FromType& input) 373 { 374 ToType output; 375 convertValue(&output, input); 376 return output; 377 } 378 379 // convert to string Shortcut 380 template <class FromType> 381 inline std::string convertToString(FromType value) 382 { 383 return getConvertedValue<FromType, std::string>(value); 384 } 385 386 // convert from string Shortcut 387 template <class ToType> 388 inline ToType convertFromString(std::string str) 389 { 390 return getConvertedValue<std::string, ToType>(str); 391 } 392 393 //////////////////////////////// 394 // Special string conversions // 395 //////////////////////////////// 396 397 // Delegate conversion from const char* to std::string 398 template <class ToType> 399 struct ConverterExplicit<const char*, ToType> 400 { 401 static bool convert(ToType* output, const char* input) 402 { 403 return convertValue<std::string, ToType>(output, input); 404 } 405 }; 406 407 // These conversions would exhibit ambiguous << or >> operators when using stringstream 408 template <> 409 struct ConverterExplicit<char, std::string> 410 { 411 static bool convert(std::string* output, const char input) 412 { 413 *output = std::string(1, input); 414 return true; 415 } 416 }; 417 template <> 418 struct ConverterExplicit<unsigned char, std::string> 419 { 420 static bool convert(std::string* output, const unsigned char input) 421 { 422 *output = std::string(1, input); 423 return true; 424 } 425 }; 426 template <> 427 struct ConverterExplicit<std::string, char> 428 { 429 static bool convert(char* output, const std::string input) 430 { 431 if (input != "") 432 *output = input[0]; 433 else 434 *output = '\0'; 435 return true; 436 } 437 }; 438 template <> 439 struct ConverterExplicit<std::string, unsigned char> 440 { 441 static bool convert(unsigned char* output, const std::string input) 442 { 443 if (input != "") 444 *output = input[0]; 445 else 446 *output = '\0'; 447 return true; 448 } 449 }; 450 451 452 // bool to std::string 453 template <> 454 struct ConverterExplicit<bool, std::string> 455 { 456 static bool convert(std::string* output, const bool& input) 457 { 458 if (input) 459 *output = "true"; 460 else 461 *output = "false"; 462 return false; 463 } 464 }; 465 466 // std::string to bool 467 template <> 468 struct ConverterExplicit<std::string, bool> 469 { 470 static bool convert(bool* output, const std::string& input) 471 { 472 std::string stripped = getLowercase(removeTrailingWhitespaces(input)); 473 if (stripped == "true" || stripped == "on" || stripped == "yes") 474 { 475 *output = true; 476 return true; 477 } 478 else if (stripped == "false" || stripped == "off" || stripped == "no") 479 { 480 *output = false; 481 return true; 482 } 483 484 std::istringstream iss(input); 485 if (iss >> (*output)) 486 return true; 487 else 488 return false; 489 } 490 }; 259 491 } 260 492 261 // We can cast implicitely262 template <class FromType, class ToType>263 inline bool convertImplicitely(ToType* output, const FromType& input, ::Int2Type<true>)264 {265 (*output) = static_cast<ToType>(input);266 return true;267 }268 269 270 ////////////////////////////////271 // ConverterExplicit Fallback //272 ////////////////////////////////273 274 // Default template if no specialisation is available275 template <class FromType, class ToType>276 struct ConverterExplicit277 {278 static bool convert(ToType* output, const FromType& input)279 {280 // Try implict cast and probe first. If a simple cast is not possible, it will not compile281 // We therefore have to out source it into another template function282 const bool probe = ImplicitConversion<FromType, ToType>::exists;283 return convertImplicitely(output, input, ::Int2Type<probe>());284 }285 };286 287 288 //////////////////////289 // Public Functions //290 //////////////////////291 292 /**293 @brief294 Converts any value to any other as long as there exists a conversion.295 Otherwise, the conversion will generate a runtime warning and return false.296 For information about the different conversion methods (user defined too), see the section297 'Actual conversion sequence' in this file above.298 */299 template <class FromType, class ToType>300 inline bool convertValue(ToType* output, const FromType& input)301 {302 return ConverterExplicit<FromType, ToType>::convert(output, input);303 }304 305 // For compatibility reasons. The same, but with capital ConvertValue306 template<class FromType, class ToType>307 inline bool ConvertValue(ToType* output, const FromType& input)308 {309 return convertValue(output, input);310 }311 312 // Calls convertValue and returns true if the conversion was successful.313 // Otherwise the fallback is used.314 /**315 @brief316 Converts any value to any other as long as there exists a conversion.317 Otherwise, the conversion will generate a runtime warning and return false.318 For information about the different conversion methods (user defined too), see the section319 'Actual conversion sequence' in this file above.320 If the conversion doesn't succeed, 'fallback' is written to '*output'.321 @param fallback322 A default value that gets written to '*output' if there is no conversion.323 */324 template<class FromType, class ToType>325 inline bool convertValue(ToType* output, const FromType& input, const ToType& fallback)326 {327 if (convertValue(output, input))328 return true;329 else330 {331 (*output) = fallback;332 return false;333 }334 }335 336 // for compatibility reason. (capital 'c' in ConvertValue)337 template<class FromType, class ToType>338 inline bool ConvertValue(ToType* output, const FromType& input, const ToType& fallback)339 {340 return convertValue(output, input, fallback);341 }342 343 // Directly returns the converted value, even if the conversion was not successful.344 template<class FromType, class ToType>345 inline ToType getConvertedValue(const FromType& input)346 {347 ToType output;348 convertValue(&output, input);349 return output;350 }351 352 // Directly returns the converted value, but uses the fallback on failure.353 template<class FromType, class ToType>354 inline ToType getConvertedValue(const FromType& input, const ToType& fallback)355 {356 ToType output;357 convertValue(&output, input, fallback);358 return output;359 }360 361 // Like getConvertedValue, but the template argument order is in reverse.362 // That means you can call it exactly like static_cast<ToType>(fromTypeValue).363 template<class ToType, class FromType>364 inline ToType omni_cast(const FromType& input)365 {366 ToType output;367 convertValue(&output, input);368 return output;369 }370 371 // convert to string Shortcut372 template <class FromType>373 inline std::string convertToString(FromType value)374 {375 return getConvertedValue<FromType, std::string>(value);376 }377 378 // convert from string Shortcut379 template <class ToType>380 inline ToType convertFromString(std::string str)381 {382 return getConvertedValue<std::string, ToType>(str);383 }384 385 ////////////////////////////////386 // Special string conversions //387 ////////////////////////////////388 389 // Delegate conversion from const char* to std::string390 template <class ToType>391 struct ConverterExplicit<const char*, ToType>392 {393 static bool convert(ToType* output, const char* input)394 {395 return convertValue<std::string, ToType>(output, input);396 }397 };398 399 // These conversions would exhibit ambiguous << or >> operators when using stringstream400 template <>401 struct ConverterExplicit<char, std::string>402 {403 static bool convert(std::string* output, const char input)404 {405 *output = std::string(1, input);406 return true;407 }408 };409 template <>410 struct ConverterExplicit<unsigned char, std::string>411 {412 static bool convert(std::string* output, const unsigned char input)413 {414 *output = std::string(1, input);415 return true;416 }417 };418 template <>419 struct ConverterExplicit<std::string, char>420 {421 static bool convert(char* output, const std::string input)422 {423 if (input != "")424 *output = input[0];425 else426 *output = '\0';427 return true;428 }429 };430 template <>431 struct ConverterExplicit<std::string, unsigned char>432 {433 static bool convert(unsigned char* output, const std::string input)434 {435 if (input != "")436 *output = input[0];437 else438 *output = '\0';439 return true;440 }441 };442 443 444 // bool to std::string445 template <>446 struct ConverterExplicit<bool, std::string>447 {448 static bool convert(std::string* output, const bool& input)449 {450 if (input)451 *output = "true";452 else453 *output = "false";454 return false;455 }456 };457 458 // std::string to bool459 template <>460 struct ConverterExplicit<std::string, bool>461 {462 static bool convert(bool* output, const std::string& input)463 {464 std::string stripped = getLowercase(removeTrailingWhitespaces(input));465 if (stripped == "true" || stripped == "on" || stripped == "yes")466 {467 *output = true;468 return true;469 }470 else if (stripped == "false" || stripped == "off" || stripped == "no")471 {472 *output = false;473 return true;474 }475 476 std::istringstream iss(input);477 if (iss >> (*output))478 return true;479 else480 return false;481 }482 };483 484 493 #endif /* _Convert_H__ */
Note: See TracChangeset
for help on using the changeset viewer.