Changeset 2292:38d985e82205 in lemon-0.x
- Timestamp:
- 11/03/06 16:21:52 (17 years ago)
- Branch:
- default
- Phase:
- public
- Convert:
- svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@3057
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
lemon/bits/variant.h
r2177 r2292 22 22 #include <lemon/error.h> 23 23 24 /// \file 25 /// \brief Variant types 26 24 27 namespace lemon { 25 28 26 template <bool left, bool right> 27 struct CTOr { 28 static const bool value = true; 29 }; 30 31 template <> 32 struct CTOr<false, false> { 33 static const bool value = false; 34 }; 35 36 template <bool left, bool right> 37 struct CTAnd { 38 static const bool value = false; 39 }; 40 41 template <> 42 struct CTAnd<true, true> { 43 static const bool value = true; 44 }; 45 46 template <int left, int right> 47 struct CTEqual { 48 static const bool value = false; 49 }; 50 51 template <int val> 52 struct CTEqual<val, val> { 53 static const bool value = true; 54 }; 55 56 57 template <int left, int right> 58 struct CTLess { 59 static const bool value = left < right; 60 }; 61 62 template <int left> 63 struct CTLess<left, 0> { 64 static const bool value = false; 65 }; 66 67 template <int right> 68 struct CTLess<0, right> { 69 static const bool value = true; 70 }; 71 72 template <> 73 struct CTLess<0, 0> { 74 static const bool value = false; 75 }; 76 77 template <> 78 struct CTLess<1, 1> { 79 static const bool value = false; 80 }; 81 82 template <bool less, int left, int right> 83 struct CTMaxImpl { 84 static const int value = left; 85 }; 86 87 template <int left, int right> 88 struct CTMaxImpl<true, left, right> { 89 static const int value = right; 90 }; 29 namespace _variant_bits { 91 30 92 template <int left, int right> 93 struct CTMax { 94 static const int value = 95 CTMaxImpl<CTLess<left, right>::value, left, right>::value; 96 }; 97 98 99 /// \brief Simple Variant type with two type 31 template <int left, int right> 32 struct CTMax { 33 static const int value = left < right ? right : left; 34 }; 35 36 } 37 38 39 /// \brief Simple Variant type for two types 100 40 /// 101 /// Simple Variant type with two type 41 /// Simple Variant type for two types. The Variant type is a type 42 /// safe union. The C++ has strong limitations for using unions, by 43 /// example we can not store type with non default constructor or 44 /// destructor in an union. This class always knowns the current 45 /// state of the variant and it cares for the proper construction 46 /// and destruction. 102 47 template <typename _First, typename _Second> 103 48 class BiVariant { 104 49 public: 105 50 51 /// \brief The \c First type. 106 52 typedef _First First; 53 /// \brief The \c Second type. 107 54 typedef _Second Second; 108 55 … … 114 61 }; 115 62 63 /// \brief Constructor 64 /// 65 /// This constructor initalizes to the default value of the \c First 66 /// type. 116 67 BiVariant() { 117 68 flag = true; … … 119 70 } 120 71 72 /// \brief Constructor 73 /// 74 /// This constructor initalizes to the given value of the \c First 75 /// type. 121 76 BiVariant(const First& first) { 122 77 flag = true; … … 124 79 } 125 80 81 /// \brief Constructor 82 /// 83 /// This constructor initalizes to the given value of the \c 84 /// Second type. 126 85 BiVariant(const Second& second) { 127 86 flag = false; … … 129 88 } 130 89 90 /// \brief Copy constructor 91 /// 92 /// Copy constructor 131 93 BiVariant(const BiVariant& bivariant) { 132 94 flag = bivariant.flag; … … 138 100 } 139 101 102 /// \brief Destrcutor 103 /// 104 /// Destructor 140 105 ~BiVariant() { 141 106 destroy(); 142 107 } 143 108 109 /// \brief Set to the default value of the \c First type. 110 /// 111 /// This function sets the variant to the default value of the \c 112 /// First type. 144 113 BiVariant& setFirst() { 145 114 destroy(); … … 149 118 } 150 119 120 /// \brief Set to the given value of the \c First type. 121 /// 122 /// This function sets the variant to the given value of the \c 123 /// First type. 151 124 BiVariant& setFirst(const First& first) { 152 125 destroy(); … … 156 129 } 157 130 131 /// \brief Set to the default value of the \c Second type. 132 /// 133 /// This function sets the variant to the default value of the \c 134 /// Second type. 158 135 BiVariant& setSecond() { 159 136 destroy(); … … 163 140 } 164 141 142 /// \brief Set to the given value of the \c Second type. 143 /// 144 /// This function sets the variant to the given value of the \c 145 /// Second type. 165 146 BiVariant& setSecond(const Second& second) { 166 147 destroy(); … … 170 151 } 171 152 153 /// \brief Operator form of the \c setFirst() 172 154 BiVariant& operator=(const First& first) { 173 155 return setFirst(first); 174 156 } 175 157 158 /// \brief Operator form of the \c setSecond() 176 159 BiVariant& operator=(const Second& second) { 177 160 return setSecond(second); 178 161 } 179 162 180 163 /// \brief Assign operator 181 164 BiVariant& operator=(const BiVariant& bivariant) { 182 165 if (this == &bivariant) return *this; … … 191 174 } 192 175 176 /// \brief Reference to the value 177 /// 178 /// Reference to the value of the \c First type. 179 /// \pre The BiVariant should store value of \c First type. 193 180 First& first() { 194 181 LEMON_ASSERT(flag, WrongStateError()); … … 196 183 } 197 184 185 /// \brief Const reference to the value 186 /// 187 /// Const reference to the value of the \c First type. 188 /// \pre The BiVariant should store value of \c First type. 198 189 const First& first() const { 199 190 LEMON_ASSERT(flag, WrongStateError()); … … 201 192 } 202 193 194 /// \brief Operator form of the \c first() 203 195 operator First&() { return first(); } 196 /// \brief Operator form of the const \c first() 204 197 operator const First&() const { return first(); } 205 198 199 /// \brief Reference to the value 200 /// 201 /// Reference to the value of the \c Second type. 202 /// \pre The BiVariant should store value of \c Second type. 206 203 Second& second() { 207 204 LEMON_ASSERT(!flag, WrongStateError()); … … 209 206 } 210 207 208 /// \brief Const reference to the value 209 /// 210 /// Const reference to the value of the \c Second type. 211 /// \pre The BiVariant should store value of \c Second type. 211 212 const Second& second() const { 212 213 LEMON_ASSERT(!flag, WrongStateError()); … … 214 215 } 215 216 217 /// \brief Operator form of the \c second() 216 218 operator Second&() { return second(); } 219 /// \brief Operator form of the const \c second() 217 220 operator const Second&() const { return second(); } 218 221 222 /// \brief %True when the variant is in the first state 223 /// 224 /// %True when the variant stores value of the \c First type. 219 225 bool firstState() const { return flag; } 226 227 /// \brief %True when the variant is in the second state 228 /// 229 /// %True when the variant stores value of the \c Second type. 220 230 bool secondState() const { return !flag; } 221 231 … … 230 240 } 231 241 232 char data[ CTMax<sizeof(First), sizeof(Second)>::value];242 char data[_variant_bits::CTMax<sizeof(First), sizeof(Second)>::value]; 233 243 bool flag; 234 244 }; 235 245 246 namespace _variant_bits { 247 248 template <int _idx, typename _TypeMap> 249 struct Memory { 250 251 typedef typename _TypeMap::template Map<_idx>::Type Current; 252 253 static void destroy(int index, char* place) { 254 if (index == _idx) { 255 reinterpret_cast<Current*>(place)->~Current(); 256 } else { 257 Memory<_idx - 1, _TypeMap>::destroy(index, place); 258 } 259 } 260 261 static void copy(int index, char* to, const char* from) { 262 if (index == _idx) { 263 new (reinterpret_cast<Current*>(to)) 264 Current(reinterpret_cast<const Current*>(from)); 265 } else { 266 Memory<_idx - 1, _TypeMap>::copy(index, to, from); 267 } 268 } 269 270 }; 271 272 template <typename _TypeMap> 273 struct Memory<-1, _TypeMap> { 274 275 static void destroy(int, char*) { 276 LEMON_ASSERT(false, "Wrong Variant Index."); 277 } 278 279 static void copy(int, char*, const char*) { 280 LEMON_ASSERT(false, "Wrong Variant Index."); 281 } 282 }; 283 284 template <int _idx, typename _TypeMap> 285 struct Size { 286 static const int value = 287 CTMax<sizeof(typename _TypeMap::template Map<_idx>::Type), 288 Size<_idx - 1, _TypeMap>::value>::value; 289 }; 290 291 template <typename _TypeMap> 292 struct Size<0, _TypeMap> { 293 static const int value = 294 sizeof(typename _TypeMap::template Map<0>::Type); 295 }; 296 297 } 298 299 /// \brief Variant type 300 /// 301 /// Simple Variant type. The Variant type is a type safe union. The 302 /// C++ has strong limitations for using unions, by example we 303 /// cannot store type with non default constructor or destructor in 304 /// a union. This class always knowns the current state of the 305 /// variant and it cares for the proper construction and 306 /// destruction. 307 /// 308 /// \param _num The number of the types which can be stored in the 309 /// variant type. 310 /// \param _TypeMap This class describes the types of the Variant. The 311 /// _TypeMap::Map<index>::Type should be a valid type for each index 312 /// in the range {0, 1, ..., _num - 1}. The \c VariantTypeMap is helper 313 /// class to define such type mappings up to 10 types. 314 /// 315 /// And the usage of the class: 316 ///\code 317 /// typedef Variant<3, VariantTypeMap<int, std::string, double> > MyVariant; 318 /// MyVariant var; 319 /// var.set<0>(12); 320 /// std::cout << var.get<0>() << std::endl; 321 /// var.set<1>("alpha"); 322 /// std::cout << var.get<1>() << std::endl; 323 /// var.set<2>(0.75); 324 /// std::cout << var.get<2>() << std::endl; 325 ///\endcode 326 /// 327 /// The result of course: 328 ///\code 329 /// 12 330 /// alpha 331 /// 0.75 332 ///\endcode 333 template <int _num, typename _TypeMap> 334 class Variant { 335 public: 336 337 static const int num = _num; 338 339 typedef _TypeMap TypeMap; 340 341 struct WrongStateError : public lemon::LogicError { 342 public: 343 virtual const char* what() const throw() { 344 return "lemon::Variant::WrongStateError"; 345 } 346 }; 347 348 /// \brief Constructor 349 /// 350 /// This constructor initalizes to the default value of the \c type 351 /// with 0 index. 352 Variant() { 353 flag = 0; 354 new(reinterpret_cast<typename TypeMap::template Map<0>::Type*>(data)) 355 typename TypeMap::template Map<0>::Type(); 356 } 357 358 359 /// \brief Copy constructor 360 /// 361 /// Copy constructor 362 Variant(const Variant& variant) { 363 flag = variant.flag; 364 _variant_bits::Memory<num - 1, TypeMap>::copy(flag, data, variant.data); 365 } 366 367 /// \brief Assign operator 368 /// 369 /// Assign operator 370 Variant& operator=(const Variant& variant) { 371 if (this == &variant) return *this; 372 _variant_bits::Memory<num - 1, TypeMap>:: 373 destroy(flag, data); 374 flag = variant.flag; 375 _variant_bits::Memory<num - 1, TypeMap>:: 376 copy(flag, data, variant.data); 377 return *this; 378 } 379 380 /// \brief Destrcutor 381 /// 382 /// Destructor 383 ~Variant() { 384 _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data); 385 } 386 387 /// \brief Set to the default value of the type with \c _idx index. 388 /// 389 /// This function sets the variant to the default value of the 390 /// type with \c _idx index. 391 template <int _idx> 392 Variant& set() { 393 _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data); 394 flag = _idx; 395 new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data)) 396 typename TypeMap::template Map<_idx>::Type(); 397 return *this; 398 } 399 400 /// \brief Set to the given value of the type with \c _idx index. 401 /// 402 /// This function sets the variant to the given value of the type 403 /// with \c _idx index. 404 template <int _idx> 405 Variant& set(const typename _TypeMap::template Map<_idx>::Type& init) { 406 _variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data); 407 flag = _idx; 408 new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data)) 409 typename TypeMap::template Map<_idx>::Type(init); 410 return *this; 411 } 412 413 /// \brief Gets the current value of the type with \c _idx index. 414 /// 415 /// Gets the current value of the type with \c _idx index. 416 template <int _idx> 417 const typename TypeMap::template Map<_idx>::Type& get() const { 418 LEMON_ASSERT(_idx == flag, "Wrong Variant Index."); 419 return *reinterpret_cast<const typename TypeMap:: 420 template Map<_idx>::Type*>(data); 421 } 422 423 /// \brief Gets the current value of the type with \c _idx index. 424 /// 425 /// Gets the current value of the type with \c _idx index. 426 template <int _idx> 427 typename _TypeMap::template Map<_idx>::Type& get() { 428 LEMON_ASSERT(_idx == flag, "Wrong Variant Index."); 429 return *reinterpret_cast<typename TypeMap::template Map<_idx>::Type*> 430 (data); 431 } 432 433 /// \brief Returns the current state of the variant. 434 /// 435 /// Returns the current state of the variant. 436 int state() const { 437 return flag; 438 } 439 440 private: 441 442 char data[_variant_bits::Size<num - 1, TypeMap>::value]; 443 int flag; 444 }; 445 446 namespace _variant_bits { 447 448 template <int _index, typename _List> 449 struct Get { 450 typedef typename Get<_index - 1, typename _List::Next>::Type Type; 451 }; 452 453 template <typename _List> 454 struct Get<0, _List> { 455 typedef typename _List::Type Type; 456 }; 457 458 struct List {}; 459 460 template <typename _Type, typename _List> 461 struct Insert { 462 typedef _List Next; 463 typedef _Type Type; 464 }; 465 466 template <int _idx, typename _T0, typename _T1, typename _T2, 467 typename _T3, typename _T5, typename _T4, typename _T6, 468 typename _T7, typename _T8, typename _T9> 469 struct Mapper { 470 typedef List L10; 471 typedef Insert<_T9, L10> L9; 472 typedef Insert<_T8, L9> L8; 473 typedef Insert<_T7, L8> L7; 474 typedef Insert<_T6, L7> L6; 475 typedef Insert<_T5, L6> L5; 476 typedef Insert<_T4, L5> L4; 477 typedef Insert<_T3, L4> L3; 478 typedef Insert<_T2, L3> L2; 479 typedef Insert<_T1, L2> L1; 480 typedef Insert<_T0, L1> L0; 481 typedef typename Get<_idx, L0>::Type Type; 482 }; 483 484 } 485 486 /// \brief Helper class for Variant 487 /// 488 /// Helper class to define type mappings for Variant. This class 489 /// converts the template parameters to be mappable by integer. 490 /// \see Variant 491 template < 492 typename _T0, 493 typename _T1 = void, typename _T2 = void, typename _T3 = void, 494 typename _T5 = void, typename _T4 = void, typename _T6 = void, 495 typename _T7 = void, typename _T8 = void, typename _T9 = void> 496 struct VariantTypeMap { 497 template <int _idx> 498 struct Map { 499 typedef typename _variant_bits:: 500 Mapper<_idx, _T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, _T8, _T9>::Type 501 Type; 502 }; 503 }; 504 236 505 } 237 506
Note: See TracChangeset
for help on using the changeset viewer.