- Timestamp:
- Sep 6, 2010, 2:30:12 PM (14 years ago)
- Location:
- code/branches/doc/src/libraries/util
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/doc/src/libraries/util/Convert.cc
r7163 r7364 32 32 namespace orxonox 33 33 { 34 //template <class FromType, class ToType>35 34 bool ConverterExplicit<std::string, bool>::convert(bool* output, const std::string& input) 36 35 { -
code/branches/doc/src/libraries/util/Convert.h
r7297 r7364 28 28 */ 29 29 30 /*! 31 @file 32 @brief Definition and Implementation of the Convert class. 30 /** Functions that convert values between different types. 31 @file 32 @par Usage 33 There are three ways to use the conversions depending on what you need. <br> 34 - For simply converting values without having to know whether the conversion 35 was successful (for instance float --> string), use orxonox::multi_cast 36 which effectively works exactly like static_cast, etc. 37 @code 38 float input = 42.0; 39 std::string output = multi_cast<std::string>(input); 40 @endcode 41 - If you care about whether the conversion was successful, 42 use orxonox::convertValue. 43 @code 44 std::string input("3.4"); 45 float output; 46 bool success = convertValue(&output, input); 47 @endcode 48 - If you care about success and if you can also feed a fallback value, 49 use orxonox::convertValue. 50 @code 51 std::string input("3.4"); 52 float output; 53 bool success = convertValue(&output, input, 0.0); 54 @endcode 55 - If success doesn't matter but you can feed a fallback value, 56 use orxonox::getConvertedValue. 57 @code 58 std::string input("3.4"); 59 float output = getConvertedValue(input, 0.0); 60 @endcode 61 @details 62 The back end of these functions are the actual implementations for the 63 specific conversions, for instance from Ogre::Vector3 to std::string and 64 vice versa. Some of them also use the iostream operators. <br> 65 The real deal is evaluating which function is needed for a conversion based 66 on the input and output type. But there are lots of catches in conjunction 67 with templates which explains why there are so many functions in this file. 68 <br> <br> 69 @par Search Order 70 Finding the right function is governed by priority rules: <br> 71 -# (Partial) template specialisation of orxonox::ConverterExplicit::convert() 72 -# An implicit conversion. This includes 'FooBar' to 'int' if FooBar 73 defines operator int() or float(). 74 -# Global or member operators for iostream when converting from or 75 to std::string (and FROM const char*) 76 -# (Partial) template specialisation of orxonox::ConverterFallback::convert() 77 -# Fallback function that displays "Could not convert value" with type 78 information obtained from typeid(). 79 @par Implementing conversion functions 80 To do that you probably need to know a thing or two about the types 81 involved. So, get ready with that. <br> 82 Usually the best way to do it is specialising of the orxonox::ConverterFallback 83 template, like this: 84 @code 85 template <> 86 struct _UtilExport ConverterFallback<std::string, MyType> 87 { 88 static bool convert(MyType* output, const std::string& input) 89 { 90 ... 91 return success; 92 } 93 }; 94 @endcode 95 This piece of code converts an std::string to MyType and returns whether the 96 conversion was successful. You can also use partial specialisation.<br> 97 The advantage with orxonox::ConverterFallback is that it has a low priority 98 meaning that when there is an implicit conversion or an iostream method, that 99 comes first and you don't have to deal with it (and the accompanying 100 function call ambiguity). <br> 101 However sometimes you would like to explicitely replace such a conversion. 102 That's where orxonox::ConverterExplicit comes in handy (for instance we 103 replaced the operator << conversions for Ogre::VectorX with our own functions). 104 @note 105 There has to be an exact type match when using template specialisations. <br> 106 Template specialisations can be defined after including this file. 107 But any implicit cast function or iostream operator has to be included 108 in this file! 109 @par Understanding the Code 110 In order to understand how the templates work, it is probably best to study 111 the functions in order of calling. There are lots of comments explaining 112 what happens, but you'll need to understand a deal about partial template 113 specialisation and function headers are matched in C++. 33 114 */ 34 115 … … 46 127 #include "TemplateUtils.h" 47 128 48 ////////////////////////////////////49 //// ACTUAL CONVERSION SEQUENCE ////50 ////////////////////////////////////51 /*52 There is a distinct priority when choosing the right conversion function:53 Overwrite:54 1. (Partial) template specialisation of ConverterExplicit::convert()55 Fallbacks:56 2. Any possible implicit conversion. This includes 'FooBar' --> 'int' if FooBar defines operator float().57 3. Global or member operators for stringstream when converting from or to std::string (or FROM const char*)58 4. (Partial) template specialisation of ConverterFallback::convert()59 5. Function that simply displays "Could not convert value" with type information obtained from typeid().60 61 Notes:62 There has to be an exact type match when using template specialisations.63 Template specialisations can be defined after including this file. Any implicit cast function or iostream64 operator has to be declared BEFORE this file gets parsed.65 66 Defining your own functions:67 There are obviously 4 ways to specify a user defined conversion. What should you use?68 69 Usually, ConverterFallback fits quite well. You won't have to deal with the conversion from70 'MyClass' to 'MyClass' by using another explicit template specialisation to avoid ambiguities.71 72 However if you want to overwrite an implicit conversion or an iostream operator, you really need to73 make use of ConverterExplicit. We have to do this for the Ogre classes for instance because they74 define stream operators we don't particulary like.75 */76 77 129 namespace orxonox 78 130 { … … 81 133 /////////////////// 82 134 83 // Default template. No conversion available at all.135 /// Default template. No conversion available at all. 84 136 template <class FromType, class ToType> 85 137 struct ConverterFallback … … 93 145 }; 94 146 95 // If all else fails, try a dynamic_cast for pointer types.147 /// If all else fails, try a dynamic_cast for pointer types. 96 148 template <class FromType, class ToType> 97 149 struct ConverterFallback<FromType*, ToType*> … … 144 196 /////////////////////// 145 197 146 // Default template for stringstream 198 /** Fallback template for stringstream 199 @details 200 Neither FromType nor ToType was std::string, therefore 201 delegate to orxonox::ConverterFallback 202 */ 147 203 template <class FromType, class ToType> 148 204 struct ConverterStringStream … … 159 215 ///////////// 160 216 217 /// Extra namespace to avoid exposing the iostream operators in it 161 218 namespace fallbackTemplates 162 219 { 220 /// Fallback operator <<() (delegates to orxonox::ConverterFallback) 163 221 template <class FromType> 164 222 FORCEINLINE bool operator <<(std::ostream& outstream, const FromType& input) … … 175 233 } 176 234 177 // template that evaluates whether we can convert to std::string via ostringstream235 /// Template that evaluates whether we can convert to std::string via ostringstream 178 236 template <class FromType> 179 237 struct ConverterStringStream<FromType, std::string> … … 182 240 { 183 241 using namespace fallbackTemplates; 184 // this operator call only chooses fallbackTemplates::operator<< if there's no other fitting function 242 // this operator call only chooses fallbackTemplates::operator<<() 243 // if there's no other fitting function 185 244 std::ostringstream oss; 245 // Note: std::ostream has operator!() to tell whether any error flag was set 186 246 if (oss << input) 187 247 { … … 201 261 namespace fallbackTemplates 202 262 { 263 /// Fallback operator >>() (delegates to orxonox::ConverterFallback) 203 264 template <class ToType> 204 265 FORCEINLINE bool operator >>(std::istream& instream, ToType& output) 205 266 { 206 return orxonox::ConverterFallback<std::string, ToType>207 ::convert(&output, static_cast<std::istringstream&>(instream).str());267 std::string input(static_cast<std::istringstream&>(instream).str()); 268 return orxonox::ConverterFallback<std::string, ToType>::convert(&output, input); 208 269 } 209 270 } 210 271 211 // template that evaluates whether we can convert from std::string via ostringstream272 /// Template that evaluates whether we can convert from std::string via istringstream 212 273 template <class ToType> 213 274 struct ConverterStringStream<std::string, ToType> … … 216 277 { 217 278 using namespace fallbackTemplates; 279 // this operator call chooses fallbackTemplates::operator>>() 280 // only if there's no other fitting function 218 281 std::istringstream iss(input); 219 // this operator call only chooses fallbackTemplates::operator>> if there's no other fitting function282 // Note: std::istream has operator!() to tell whether any error flag was set 220 283 if (iss >> (*output)) 221 284 { … … 229 292 namespace orxonox 230 293 { 231 232 294 /////////////////// 233 295 // Implicit Cast // 234 296 /////////////////// 235 297 236 // implicit cast not possible, try stringstream conversion next298 /// %Template delegates to ::ConverterStringStream 237 299 template <class FromType, class ToType> 238 300 FORCEINLINE bool convertImplicitely(ToType* output, const FromType& input, Loki::Int2Type<false>) … … 241 303 } 242 304 243 // We can cast implicitely305 /// Makes an implicit cast from \a FromType to \a ToType 244 306 template <class FromType, class ToType> 245 307 FORCEINLINE bool convertImplicitely(ToType* output, const FromType& input, Loki::Int2Type<true>) … … 254 316 //////////////////////////////// 255 317 256 // Default template if no specialisation is available 318 /** Default template if no orxonox::ConverterExplicit is available 319 @details 320 Evaluates whether \a FromType can be implicitly converted to \a ToType 321 by the use the ImplicitConversion magic. 322 */ 257 323 template <class FromType, class ToType> 258 324 struct ConverterExplicit … … 261 327 FORCEINLINE static bool convert(ToType* output, const FromType& input) 262 328 { 263 // Try implict cast and probe first. If a simple cast is not possible, it will not compile 264 // We therefore have to out source it into another template function 329 // Use the probe's value to delegate to the right function 265 330 return convertImplicitely(output, input, Loki::Int2Type<probe>()); 266 331 } … … 275 340 @brief 276 341 Converts any value to any other as long as there exists a conversion. 342 @details 277 343 Otherwise, the conversion will generate a runtime warning and return false. 278 For information about the different conversion methods (user defined too), see the section 279 'Actual conversion sequence' in this file above. 344 @see Convert.h 280 345 @param output 281 346 A pointer to the variable where the converted value will be stored … … 295 360 Converts any value to any other as long as there exists a conversion. 296 361 Otherwise, the conversion will generate a runtime warning and return false. 297 For information about the different conversion methods (user defined too), see the section 298 'Actual conversion sequence' in this file above. 299 If the conversion doesn't succeed, 'fallback' is written to '*output'. 362 If the conversion doesn't succeed, \a fallback is written to \a output. 363 @see Convert.h 300 364 @param output 301 365 A pointer to the variable where the converted value will be stored … … 317 381 } 318 382 319 // Directly returns the converted value, even if the conversion was not successful.320 383 template<class FromType, class ToType> 321 384 FORCEINLINE ToType getConvertedValue(const FromType& input) … … 326 389 } 327 390 328 // Directly returns the converted value, but uses the fallback on failure.391 /// Directly returns the converted value, but uses the fallback on failure. @see convertValue 329 392 template<class FromType, class ToType> 330 393 FORCEINLINE ToType getConvertedValue(const FromType& input, const ToType& fallback) … … 335 398 } 336 399 337 // Like getConvertedValue, but the template argument order is in reverse. 338 // That means you can call it exactly like static_cast<ToType>(fromTypeValue). 400 /** 401 @brief 402 Converts any value to any other as long as there exists a conversion. 403 @details 404 Use exactly the way you use static_cast, etc. <br> 405 A failed conversion will return a default instance of \a ToType 406 (possibly uninitialised) 407 @see Convert.h 408 @param input 409 The original value 410 */ 339 411 template<class ToType, class FromType> 340 412 FORCEINLINE ToType multi_cast(const FromType& input) … … 349 421 //////////////////////////////// 350 422 351 // Delegateconversion from const char* to std::string423 /// Delegates conversion from const char* to std::string 352 424 template <class ToType> 353 425 struct ConverterExplicit<const char*, ToType> … … 359 431 }; 360 432 361 // These conversions would exhibit ambiguous << or >> operators when using stringstream433 /// Conversion would exhibit ambiguous << or >> operators when using iostream 362 434 template <> 363 435 struct ConverterExplicit<char, std::string> … … 369 441 } 370 442 }; 443 /// Conversion would exhibit ambiguous << or >> operators when using iostream 444 template <> 371 445 template <> 372 446 struct ConverterExplicit<unsigned char, std::string> … … 378 452 } 379 453 }; 454 /// Conversion would exhibit ambiguous << or >> operators when using iostream 455 template <> 380 456 template <> 381 457 struct ConverterExplicit<std::string, char> … … 390 466 } 391 467 }; 468 /// Conversion would exhibit ambiguous << or >> operators when using iostream 392 469 template <> 393 470 struct ConverterExplicit<std::string, unsigned char> … … 404 481 405 482 406 // bool to std::string483 /// Conversion from bool to std::string 407 484 template <> 408 485 struct ConverterExplicit<bool, std::string> … … 418 495 }; 419 496 420 // std::string to bool497 /// Conversion from std::string to bool 421 498 template <> 422 499 struct _UtilExport ConverterExplicit<std::string, bool>
Note: See TracChangeset
for help on using the changeset viewer.