Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
variant.h
00001 ///\file 00002 00003 /****************************************************************************** 00004 The MIT License(MIT) 00005 00006 Embedded Template Library. 00007 https://github.com/ETLCPP/etl 00008 https://www.etlcpp.com 00009 00010 Copyright(c) 2014 jwellbelove 00011 00012 Permission is hereby granted, free of charge, to any person obtaining a copy 00013 of this software and associated documentation files(the "Software"), to deal 00014 in the Software without restriction, including without limitation the rights 00015 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell 00016 copies of the Software, and to permit persons to whom the Software is 00017 furnished to do so, subject to the following conditions : 00018 00019 The above copyright notice and this permission notice shall be included in all 00020 copies or substantial portions of the Software. 00021 00022 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00023 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00024 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE 00025 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00026 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00027 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00028 SOFTWARE. 00029 ******************************************************************************/ 00030 00031 #ifndef __ETL_VARIANT__ 00032 #define __ETL_VARIANT__ 00033 00034 #include <stdint.h> 00035 00036 #include "platform.h " 00037 #include "array.h " 00038 #include "largest.h " 00039 #include "exception.h " 00040 #include "type_traits.h " 00041 #include "integral_limits.h " 00042 #include "static_assert.h" 00043 #include "alignment.h " 00044 #include "error_handler.h " 00045 00046 #if defined(ETL_COMPILER_KEIL) 00047 #pragma diag_suppress 940 00048 #pragma diag_suppress 111 00049 #endif 00050 00051 #undef ETL_FILE 00052 #define ETL_FILE "24" 00053 00054 //***************************************************************************** 00055 ///\defgroup variant variant 00056 /// A class that can contain one a several specified types in a type safe manner. 00057 ///\ingroup containers 00058 //***************************************************************************** 00059 00060 namespace etl 00061 { 00062 namespace __private_variant__ 00063 { 00064 //************************************************************************* 00065 /// Placeholder for unused template parameters. 00066 /// This class is never instantiated. 00067 //************************************************************************* 00068 template <const size_t ID> 00069 struct no_type 00070 { 00071 }; 00072 } 00073 00074 //*************************************************************************** 00075 /// Base exception for the variant class. 00076 ///\ingroup variant 00077 //*************************************************************************** 00078 class variant_exception : public exception 00079 { 00080 public: 00081 variant_exception(string_type reason_, string_type file_name_, numeric_type line_number_) 00082 : exception(reason_, file_name_, line_number_) 00083 { 00084 } 00085 }; 00086 00087 //*************************************************************************** 00088 /// 'Unsupported type' exception for the variant class. 00089 ///\ingroup variant 00090 //*************************************************************************** 00091 class variant_incorrect_type_exception : public variant_exception 00092 { 00093 public: 00094 variant_incorrect_type_exception(string_type file_name_, numeric_type line_number_) 00095 : variant_exception(ETL_ERROR_TEXT("variant: unsupported type", ETL_FILE"A"), file_name_, line_number_) 00096 { 00097 } 00098 }; 00099 00100 //*************************************************************************** 00101 /// A template class that can store any of the types defined in the template parameter list. 00102 /// Supports up to 8 types. 00103 ///\ingroup variant 00104 //*************************************************************************** 00105 template <typename T1, 00106 typename T2 = __private_variant__::no_type<2>, 00107 typename T3 = __private_variant__::no_type<3>, 00108 typename T4 = __private_variant__::no_type<4>, 00109 typename T5 = __private_variant__::no_type<5>, 00110 typename T6 = __private_variant__::no_type<6>, 00111 typename T7 = __private_variant__::no_type<7>, 00112 typename T8 = __private_variant__::no_type<8> > 00113 class variant 00114 { 00115 private: 00116 00117 // All types of variant are friends. 00118 template <typename U1, typename U2, typename U3, typename U4, typename U5, typename U6, typename U7, typename U8> 00119 friend class variant; 00120 00121 //*************************************************************************** 00122 /// The largest type. 00123 //*************************************************************************** 00124 typedef typename largest_type<T1, T2, T3, T4, T5, T6, T7, T8>::type largest_t; 00125 00126 //*************************************************************************** 00127 /// The largest size. 00128 //*************************************************************************** 00129 static const size_t SIZE = sizeof(largest_t); 00130 00131 //*************************************************************************** 00132 /// The largest alignment. 00133 //*************************************************************************** 00134 static const size_t ALIGNMENT = etl::largest_alignment<T1, T2, T3, T4, T5, T6, T7, T8>::value; 00135 00136 //*************************************************************************** 00137 /// The type used for ids. 00138 //*************************************************************************** 00139 typedef uint_least8_t type_id_t; 00140 00141 //*************************************************************************** 00142 /// The id a unsupported types. 00143 //*************************************************************************** 00144 static const type_id_t UNSUPPORTED_TYPE_ID = integral_limits<type_id_t>::max; 00145 00146 //*************************************************************************** 00147 /// Short form of no_type placeholders. 00148 //*************************************************************************** 00149 typedef __private_variant__::no_type<2> no_type2; 00150 typedef __private_variant__::no_type<3> no_type3; 00151 typedef __private_variant__::no_type<4> no_type4; 00152 typedef __private_variant__::no_type<5> no_type5; 00153 typedef __private_variant__::no_type<6> no_type6; 00154 typedef __private_variant__::no_type<7> no_type7; 00155 typedef __private_variant__::no_type<8> no_type8; 00156 00157 //*************************************************************************** 00158 /// Lookup the id of type. 00159 //*************************************************************************** 00160 template <typename T> 00161 struct Type_Id_Lookup 00162 { 00163 static const uint_least8_t type_id = etl::is_same<T, T1>::value ? 0 : 00164 etl::is_same<T, T2>::value ? 1 : 00165 etl::is_same<T, T3>::value ? 2 : 00166 etl::is_same<T, T4>::value ? 3 : 00167 etl::is_same<T, T5>::value ? 4 : 00168 etl::is_same<T, T6>::value ? 5 : 00169 etl::is_same<T, T7>::value ? 6 : 00170 etl::is_same<T, T8>::value ? 7 : 00171 UNSUPPORTED_TYPE_ID; 00172 }; 00173 00174 //*************************************************************************** 00175 /// Lookup for the id of type. 00176 //*************************************************************************** 00177 template <typename T> 00178 struct Type_Is_Supported : public integral_constant<bool, 00179 is_same<T, T1>::value || 00180 is_same<T, T2>::value || 00181 is_same<T, T3>::value || 00182 is_same<T, T4>::value || 00183 is_same<T, T5>::value || 00184 is_same<T, T6>::value || 00185 is_same<T, T7>::value || 00186 is_same<T, T8>::value> 00187 { 00188 }; 00189 00190 public: 00191 00192 //*************************************************************************** 00193 /// Destructor. 00194 //*************************************************************************** 00195 ~variant() 00196 { 00197 destruct_current(); 00198 } 00199 00200 //************************************************************************* 00201 //**** Reader types ******************************************************* 00202 //************************************************************************* 00203 00204 //************************************************************************* 00205 /// Base reader type functor class. 00206 /// Allows for typesafe access to the stored value types. 00207 /// Define the reader type for 8 types. 00208 //************************************************************************* 00209 template <typename R1, typename R2 = no_type2, typename R3 = no_type3, typename R4 = no_type4, typename R5 = no_type5, typename R6 = no_type6, typename R7 = no_type7, typename R8 = no_type8> 00210 class reader_type 00211 { 00212 public: 00213 00214 friend class variant; 00215 00216 virtual void read(typename etl::parameter_type<R1>::type value) = 0; 00217 virtual void read(typename etl::parameter_type<R2>::type value) = 0; 00218 virtual void read(typename etl::parameter_type<R3>::type value) = 0; 00219 virtual void read(typename etl::parameter_type<R4>::type value) = 0; 00220 virtual void read(typename etl::parameter_type<R5>::type value) = 0; 00221 virtual void read(typename etl::parameter_type<R6>::type value) = 0; 00222 virtual void read(typename etl::parameter_type<R7>::type value) = 0; 00223 virtual void read(typename etl::parameter_type<R8>::type value) = 0; 00224 }; 00225 00226 //************************************************************************* 00227 /// Define the reader type for 7 types. 00228 //************************************************************************* 00229 template <typename R1, typename R2, typename R3, typename R4, typename R5, typename R6, typename R7> 00230 class reader_type<R1, R2, R3, R4, R5, R6, R7, no_type8> 00231 { 00232 public: 00233 00234 friend class variant; 00235 00236 virtual void read(typename etl::parameter_type<R1>::type value) = 0; 00237 virtual void read(typename etl::parameter_type<R2>::type value) = 0; 00238 virtual void read(typename etl::parameter_type<R3>::type value) = 0; 00239 virtual void read(typename etl::parameter_type<R4>::type value) = 0; 00240 virtual void read(typename etl::parameter_type<R5>::type value) = 0; 00241 virtual void read(typename etl::parameter_type<R6>::type value) = 0; 00242 virtual void read(typename etl::parameter_type<R7>::type value) = 0; 00243 00244 private: 00245 00246 void read(no_type8&) {}; 00247 }; 00248 00249 //************************************************************************* 00250 /// Define the reader type for 6 types. 00251 //************************************************************************* 00252 template <typename R1, typename R2, typename R3, typename R4, typename R5, typename R6> 00253 class reader_type<R1, R2, R3, R4, R5, R6, no_type7, no_type8> 00254 { 00255 public: 00256 00257 friend class variant; 00258 00259 virtual void read(typename etl::parameter_type<R1>::type value) = 0; 00260 virtual void read(typename etl::parameter_type<R2>::type value) = 0; 00261 virtual void read(typename etl::parameter_type<R3>::type value) = 0; 00262 virtual void read(typename etl::parameter_type<R4>::type value) = 0; 00263 virtual void read(typename etl::parameter_type<R5>::type value) = 0; 00264 virtual void read(typename etl::parameter_type<R6>::type value) = 0; 00265 00266 private: 00267 00268 void read(no_type7&) {}; 00269 void read(no_type8&) {}; 00270 }; 00271 00272 //************************************************************************* 00273 /// Define the reader type for 5 types. 00274 //************************************************************************* 00275 template <typename R1, typename R2, typename R3, typename R4, typename R5> 00276 class reader_type<R1, R2, R3, R4, R5, no_type6, no_type7, no_type8> 00277 { 00278 public: 00279 00280 friend class variant; 00281 00282 virtual void read(typename etl::parameter_type<R1>::type value) = 0; 00283 virtual void read(typename etl::parameter_type<R2>::type value) = 0; 00284 virtual void read(typename etl::parameter_type<R3>::type value) = 0; 00285 virtual void read(typename etl::parameter_type<R4>::type value) = 0; 00286 virtual void read(typename etl::parameter_type<R5>::type value) = 0; 00287 00288 private: 00289 00290 void read(no_type6&) {}; 00291 void read(no_type7&) {}; 00292 void read(no_type8&) {}; 00293 }; 00294 00295 //************************************************************************* 00296 /// Define the reader type for 4 types. 00297 //************************************************************************* 00298 template <typename R1, typename R2, typename R3, typename R4> 00299 class reader_type<R1, R2, R3, R4, no_type5, no_type6, no_type7, no_type8> 00300 { 00301 public: 00302 00303 friend class variant; 00304 00305 virtual void read(typename etl::parameter_type<R1>::type value) = 0; 00306 virtual void read(typename etl::parameter_type<R2>::type value) = 0; 00307 virtual void read(typename etl::parameter_type<R3>::type value) = 0; 00308 virtual void read(typename etl::parameter_type<R4>::type value) = 0; 00309 00310 private: 00311 00312 void read(no_type5&) {}; 00313 void read(no_type6&) {}; 00314 void read(no_type7&) {}; 00315 void read(no_type8&) {}; 00316 }; 00317 00318 //************************************************************************* 00319 /// Define the reader type for 3 types. 00320 //************************************************************************* 00321 template <typename R1, typename R2, typename R3> 00322 class reader_type<R1, R2, R3, no_type4, no_type5, no_type6, no_type7, no_type8> 00323 { 00324 public: 00325 00326 friend class variant; 00327 00328 virtual void read(typename etl::parameter_type<R1>::type value) = 0; 00329 virtual void read(typename etl::parameter_type<R2>::type value) = 0; 00330 virtual void read(typename etl::parameter_type<R3>::type value) = 0; 00331 00332 private: 00333 00334 void read(no_type4&) {}; 00335 void read(no_type5&) {}; 00336 void read(no_type6&) {}; 00337 void read(no_type7&) {}; 00338 void read(no_type8&) {}; 00339 }; 00340 00341 //************************************************************************* 00342 /// Define the reader type for 2 types. 00343 //************************************************************************* 00344 template <typename R1, typename R2> 00345 class reader_type<R1, R2, no_type3, no_type4, no_type5, no_type6, no_type7, no_type8> 00346 { 00347 public: 00348 00349 friend class variant; 00350 00351 virtual void read(typename etl::parameter_type<R1>::type value) = 0; 00352 virtual void read(typename etl::parameter_type<R2>::type value) = 0; 00353 00354 private: 00355 00356 void read(no_type3&) {}; 00357 void read(no_type4&) {}; 00358 void read(no_type5&) {}; 00359 void read(no_type6&) {}; 00360 void read(no_type7&) {}; 00361 void read(no_type8&) {}; 00362 }; 00363 00364 //************************************************************************* 00365 /// Define the reader type for 1 type. 00366 //************************************************************************* 00367 template <typename R1> 00368 class reader_type<R1, no_type2, no_type3, no_type4, no_type5, no_type6, no_type7, no_type8> 00369 { 00370 public: 00371 00372 friend class variant; 00373 00374 virtual void read(typename etl::parameter_type<R1>::type value) = 0; 00375 00376 private: 00377 00378 void read(no_type2&) {}; 00379 void read(no_type3&) {}; 00380 void read(no_type4&) {}; 00381 void read(no_type5&) {}; 00382 void read(no_type6&) {}; 00383 void read(no_type7&) {}; 00384 void read(no_type8&) {}; 00385 }; 00386 00387 //************************************************************************* 00388 //**** Up-cast functors *************************************************** 00389 //************************************************************************* 00390 00391 //************************************************************************* 00392 /// Base upcast_functor for eight types. 00393 //************************************************************************* 00394 template <typename TBase, typename U1, typename U2 = no_type2, typename U3 = no_type3, typename U4 = no_type4, typename U5 = no_type5, typename U6 = no_type6, typename U7 = no_type7, typename U8 = no_type8> 00395 class upcast_functor 00396 { 00397 public: 00398 00399 TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) 00400 { 00401 switch (typeId) 00402 { 00403 case 0: return reinterpret_cast<U1&>(*p_data); 00404 case 1: return reinterpret_cast<U2&>(*p_data); 00405 case 2: return reinterpret_cast<U3&>(*p_data); 00406 case 3: return reinterpret_cast<U4&>(*p_data); 00407 case 4: return reinterpret_cast<U5&>(*p_data); 00408 case 5: return reinterpret_cast<U6&>(*p_data); 00409 case 6: return reinterpret_cast<U7&>(*p_data); 00410 case 7: return reinterpret_cast<U8&>(*p_data); 00411 default: return reinterpret_cast<TBase&>(*reinterpret_cast<TBase*>(0)); 00412 } 00413 } 00414 00415 const TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) const 00416 { 00417 switch (typeId) 00418 { 00419 case 0: return reinterpret_cast<const U1&>(*p_data); 00420 case 1: return reinterpret_cast<const U2&>(*p_data); 00421 case 2: return reinterpret_cast<const U3&>(*p_data); 00422 case 3: return reinterpret_cast<const U4&>(*p_data); 00423 case 4: return reinterpret_cast<const U5&>(*p_data); 00424 case 5: return reinterpret_cast<const U6&>(*p_data); 00425 case 6: return reinterpret_cast<const U7&>(*p_data); 00426 case 7: return reinterpret_cast<const U8&>(*p_data); 00427 default: return reinterpret_cast<const TBase&>(*reinterpret_cast<const TBase*>(0)); 00428 } 00429 } 00430 }; 00431 00432 //************************************************************************* 00433 /// Upcast_functor for seven types. 00434 //************************************************************************* 00435 template <typename TBase, typename U1, typename U2, typename U3, typename U4, typename U5, typename U6, typename U7> 00436 class upcast_functor<TBase, U1, U2, U3, U4, U5, U6, U7, no_type8> 00437 { 00438 public: 00439 00440 TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) 00441 { 00442 switch (typeId) 00443 { 00444 case 0: return reinterpret_cast<U1&>(*p_data); 00445 case 1: return reinterpret_cast<U2&>(*p_data); 00446 case 2: return reinterpret_cast<U3&>(*p_data); 00447 case 3: return reinterpret_cast<U4&>(*p_data); 00448 case 4: return reinterpret_cast<U5&>(*p_data); 00449 case 5: return reinterpret_cast<U6&>(*p_data); 00450 case 6: return reinterpret_cast<U7&>(*p_data); 00451 default: return reinterpret_cast<TBase&>(*reinterpret_cast<TBase*>(0)); 00452 } 00453 } 00454 00455 const TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) const 00456 { 00457 switch (typeId) 00458 { 00459 case 0: return reinterpret_cast<const U1&>(*p_data); 00460 case 1: return reinterpret_cast<const U2&>(*p_data); 00461 case 2: return reinterpret_cast<const U3&>(*p_data); 00462 case 3: return reinterpret_cast<const U4&>(*p_data); 00463 case 4: return reinterpret_cast<const U5&>(*p_data); 00464 case 5: return reinterpret_cast<const U6&>(*p_data); 00465 case 6: return reinterpret_cast<const U7&>(*p_data); 00466 default: return reinterpret_cast<const TBase&>(*reinterpret_cast<const TBase*>(0)); 00467 } 00468 } 00469 }; 00470 00471 //************************************************************************* 00472 /// Upcast_functor for six types. 00473 //************************************************************************* 00474 template <typename TBase, typename U1, typename U2, typename U3, typename U4, typename U5, typename U6> 00475 class upcast_functor<TBase, U1, U2, U3, U4, U5, U6, no_type7, no_type8> 00476 { 00477 public: 00478 00479 TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) 00480 { 00481 switch (typeId) 00482 { 00483 case 0: return reinterpret_cast<U1&>(*p_data); 00484 case 1: return reinterpret_cast<U2&>(*p_data); 00485 case 2: return reinterpret_cast<U3&>(*p_data); 00486 case 3: return reinterpret_cast<U4&>(*p_data); 00487 case 4: return reinterpret_cast<U5&>(*p_data); 00488 case 5: return reinterpret_cast<U6&>(*p_data); 00489 default: return reinterpret_cast<TBase&>(*reinterpret_cast<TBase*>(0)); 00490 } 00491 } 00492 00493 const TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) const 00494 { 00495 switch (typeId) 00496 { 00497 case 0: return reinterpret_cast<const U1&>(*p_data); 00498 case 1: return reinterpret_cast<const U2&>(*p_data); 00499 case 2: return reinterpret_cast<const U3&>(*p_data); 00500 case 3: return reinterpret_cast<const U4&>(*p_data); 00501 case 4: return reinterpret_cast<const U5&>(*p_data); 00502 case 5: return reinterpret_cast<const U6&>(*p_data); 00503 default: return reinterpret_cast<const TBase&>(*reinterpret_cast<const TBase*>(0)); 00504 } 00505 } 00506 }; 00507 00508 //************************************************************************* 00509 /// Upcast_functor for five types. 00510 //************************************************************************* 00511 template <typename TBase, typename U1, typename U2, typename U3, typename U4, typename U5> 00512 class upcast_functor<TBase, U1, U2, U3, U4, U5, no_type6, no_type7, no_type8> 00513 { 00514 public: 00515 00516 TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) 00517 { 00518 switch (typeId) 00519 { 00520 case 0: return reinterpret_cast<U1&>(*p_data); 00521 case 1: return reinterpret_cast<U2&>(*p_data); 00522 case 2: return reinterpret_cast<U3&>(*p_data); 00523 case 3: return reinterpret_cast<U4&>(*p_data); 00524 case 4: return reinterpret_cast<U5&>(*p_data); 00525 default: return reinterpret_cast<TBase&>(*reinterpret_cast<TBase*>(0)); 00526 } 00527 } 00528 00529 const TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) const 00530 { 00531 switch (typeId) 00532 { 00533 case 0: return reinterpret_cast<const U1&>(*p_data); 00534 case 1: return reinterpret_cast<const U2&>(*p_data); 00535 case 2: return reinterpret_cast<const U3&>(*p_data); 00536 case 3: return reinterpret_cast<const U4&>(*p_data); 00537 case 4: return reinterpret_cast<const U5&>(*p_data); 00538 default: return reinterpret_cast<const TBase&>(*reinterpret_cast<const TBase*>(0)); 00539 } 00540 } 00541 }; 00542 00543 //************************************************************************* 00544 /// Upcast_functor for four types. 00545 //************************************************************************* 00546 template <typename TBase, typename U1, typename U2, typename U3, typename U4> 00547 class upcast_functor<TBase, U1, U2, U3, U4, no_type5, no_type6, no_type7, no_type8> 00548 { 00549 public: 00550 00551 TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) 00552 { 00553 switch (typeId) 00554 { 00555 case 0: return reinterpret_cast<U1&>(*p_data); 00556 case 1: return reinterpret_cast<U2&>(*p_data); 00557 case 2: return reinterpret_cast<U3&>(*p_data); 00558 case 3: return reinterpret_cast<U4&>(*p_data); 00559 default: return reinterpret_cast<TBase&>(*reinterpret_cast<TBase*>(0)); 00560 } 00561 } 00562 00563 const TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) const 00564 { 00565 switch (typeId) 00566 { 00567 case 0: return reinterpret_cast<const U1&>(*p_data); 00568 case 1: return reinterpret_cast<const U2&>(*p_data); 00569 case 2: return reinterpret_cast<const U3&>(*p_data); 00570 case 3: return reinterpret_cast<const U4&>(*p_data); 00571 default: return reinterpret_cast<const TBase&>(*reinterpret_cast<const TBase*>(0)); 00572 } 00573 } 00574 }; 00575 00576 //************************************************************************* 00577 /// Upcast_functor for three types. 00578 //************************************************************************* 00579 template <typename TBase, typename U1, typename U2, typename U3> 00580 class upcast_functor<TBase, U1, U2, U3, no_type4, no_type5, no_type6, no_type7, no_type8> 00581 { 00582 public: 00583 00584 TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) 00585 { 00586 switch (typeId) 00587 { 00588 case 0: return reinterpret_cast<U1&>(*p_data); 00589 case 1: return reinterpret_cast<U2&>(*p_data); 00590 case 2: return reinterpret_cast<U3&>(*p_data); 00591 default: return reinterpret_cast<TBase&>(*reinterpret_cast<TBase*>(0)); 00592 } 00593 } 00594 00595 const TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) const 00596 { 00597 switch (typeId) 00598 { 00599 case 0: return reinterpret_cast<const U1&>(*p_data); 00600 case 1: return reinterpret_cast<const U2&>(*p_data); 00601 case 2: return reinterpret_cast<const U3&>(*p_data); 00602 default: return reinterpret_cast<const TBase&>(*reinterpret_cast<const TBase*>(0)); 00603 } 00604 } 00605 }; 00606 00607 //************************************************************************* 00608 /// Upcast_functor for two types. 00609 //************************************************************************* 00610 template <typename TBase, typename U1, typename U2> 00611 class upcast_functor<TBase, U1, U2, no_type3, no_type4, no_type5, no_type6, no_type7, no_type8> 00612 { 00613 public: 00614 00615 TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) 00616 { 00617 switch (typeId) 00618 { 00619 case 0: return reinterpret_cast<U1&>(*p_data); 00620 case 1: return reinterpret_cast<U2&>(*p_data); 00621 default: return reinterpret_cast<TBase&>(*reinterpret_cast<TBase*>(0)); 00622 } 00623 } 00624 00625 const TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) const 00626 { 00627 switch (typeId) 00628 { 00629 case 0: return reinterpret_cast<const U1&>(*p_data); 00630 case 1: return reinterpret_cast<const U2&>(*p_data); 00631 default: return reinterpret_cast<const TBase&>(*reinterpret_cast<const TBase*>(0)); 00632 } 00633 } 00634 }; 00635 00636 //************************************************************************* 00637 /// Upcast_functor for one type. 00638 //************************************************************************* 00639 template <typename TBase, typename U1> 00640 class upcast_functor<TBase, U1, no_type2, no_type3, no_type4, no_type5, no_type6, no_type7, no_type8> 00641 { 00642 public: 00643 00644 TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) 00645 { 00646 return reinterpret_cast<U1&>(*p_data); 00647 } 00648 00649 const TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) const 00650 { 00651 return reinterpret_cast<const U1&>(*p_data); 00652 } 00653 }; 00654 00655 //*************************************************************************** 00656 /// The base type for derived readers. 00657 //*************************************************************************** 00658 typedef reader_type<T1, T2, T3, T4, T5, T6, T7, T8> reader; 00659 00660 //*************************************************************************** 00661 /// Default constructor. 00662 /// Sets the state of the instance to containing no valid data. 00663 //*************************************************************************** 00664 variant() 00665 : type_id(UNSUPPORTED_TYPE_ID) 00666 { 00667 } 00668 00669 //*************************************************************************** 00670 /// Constructor that catches any types that are not supported. 00671 /// Forces a STATIC_ASSERT. 00672 //*************************************************************************** 00673 template <typename T> 00674 variant(const T& value) 00675 { 00676 STATIC_ASSERT(Type_Is_Supported<T>::value, "Unsupported type"); 00677 00678 ::new (static_cast<T*>(data)) T(value); 00679 type_id = Type_Id_Lookup<T>::type_id; 00680 } 00681 00682 //*************************************************************************** 00683 /// Copy constructor. 00684 ///\param other The other variant object to copy. 00685 //*************************************************************************** 00686 variant(const variant& other) 00687 { 00688 switch (other.type_id) 00689 { 00690 case 0: ::new (static_cast<T1*>(data)) T1(other.get<T1>()); break; 00691 case 1: ::new (static_cast<T2*>(data)) T2(other.get<T2>()); break; 00692 case 2: ::new (static_cast<T3*>(data)) T3(other.get<T3>()); break; 00693 case 3: ::new (static_cast<T4*>(data)) T4(other.get<T4>()); break; 00694 case 4: ::new (static_cast<T5*>(data)) T5(other.get<T5>()); break; 00695 case 5: ::new (static_cast<T6*>(data)) T6(other.get<T6>()); break; 00696 case 6: ::new (static_cast<T7*>(data)) T7(other.get<T7>()); break; 00697 case 7: ::new (static_cast<T8*>(data)) T8(other.get<T8>()); break; 00698 default: break; 00699 } 00700 00701 type_id = other.type_id; 00702 } 00703 00704 //*************************************************************************** 00705 /// Assignment operator for T1 type. 00706 ///\param value The value to assign. 00707 //*************************************************************************** 00708 template <typename T> 00709 variant& operator =(const T& value) 00710 { 00711 STATIC_ASSERT(Type_Is_Supported<T>::value, "Unsupported type"); 00712 00713 destruct_current(); 00714 ::new (static_cast<T*>(data)) T(value); 00715 type_id = Type_Id_Lookup<T>::type_id; 00716 00717 return *this; 00718 } 00719 00720 //*************************************************************************** 00721 /// Assignment operator for variant type. 00722 ///\param other The variant to assign. 00723 //*************************************************************************** 00724 variant& operator =(const variant& other) 00725 { 00726 if (this != &other) 00727 { 00728 destruct_current(); 00729 00730 switch (other.type_id) 00731 { 00732 case 0: ::new (static_cast<T1*>(data)) T1(other.get<T1>()); break; 00733 case 1: ::new (static_cast<T2*>(data)) T2(other.get<T2>()); break; 00734 case 2: ::new (static_cast<T3*>(data)) T3(other.get<T3>()); break; 00735 case 3: ::new (static_cast<T4*>(data)) T4(other.get<T4>()); break; 00736 case 4: ::new (static_cast<T5*>(data)) T5(other.get<T5>()); break; 00737 case 5: ::new (static_cast<T6*>(data)) T6(other.get<T6>()); break; 00738 case 6: ::new (static_cast<T7*>(data)) T7(other.get<T7>()); break; 00739 case 7: ::new (static_cast<T8*>(data)) T8(other.get<T8>()); break; 00740 default: break; 00741 } 00742 00743 type_id = other.type_id; 00744 } 00745 00746 return *this; 00747 } 00748 00749 //*************************************************************************** 00750 /// Checks if the type is the same as the current stored type. 00751 /// For variants with the same type declarations. 00752 ///\return <b>true</b> if the types are the same, otherwise <b>false</b>. 00753 //*************************************************************************** 00754 bool is_same_type(const variant& other) const 00755 { 00756 return type_id == other.type_id; 00757 } 00758 00759 //*************************************************************************** 00760 /// Checks if the type is the same as the current stored type. 00761 /// For variants with differing declarations. 00762 ///\return <b>true</b> if the types are the same, otherwise <b>false</b>. 00763 //*************************************************************************** 00764 template <typename U1, typename U2, typename U3, typename U4, typename U5, typename U6, typename U7, typename U8> 00765 bool is_same_type(const variant<U1, U2, U3, U4, U5, U6, U7, U8>& other) const 00766 { 00767 bool is_same = false; 00768 00769 switch (other.type_id) 00770 { 00771 case 0: is_same = (type_id == Type_Id_Lookup<U1>::type_id); break; 00772 case 1: is_same = (type_id == Type_Id_Lookup<U2>::type_id); break; 00773 case 2: is_same = (type_id == Type_Id_Lookup<U3>::type_id); break; 00774 case 3: is_same = (type_id == Type_Id_Lookup<U4>::type_id); break; 00775 case 4: is_same = (type_id == Type_Id_Lookup<U5>::type_id); break; 00776 case 5: is_same = (type_id == Type_Id_Lookup<U6>::type_id); break; 00777 case 6: is_same = (type_id == Type_Id_Lookup<U7>::type_id); break; 00778 case 7: is_same = (type_id == Type_Id_Lookup<U8>::type_id); break; 00779 default: break; 00780 } 00781 00782 return is_same; 00783 } 00784 00785 //*************************************************************************** 00786 /// Calls the supplied reader instance. 00787 /// The 'read' function appropriate to the current type is called with the stored value. 00788 //*************************************************************************** 00789 void call(reader& reader) 00790 { 00791 switch (type_id) 00792 { 00793 case 0: reader.read(static_cast<T1&>(data)); break; 00794 case 1: reader.read(static_cast<T2&>(data)); break; 00795 case 2: reader.read(static_cast<T3&>(data)); break; 00796 case 3: reader.read(static_cast<T4&>(data)); break; 00797 case 4: reader.read(static_cast<T5&>(data)); break; 00798 case 5: reader.read(static_cast<T6&>(data)); break; 00799 case 6: reader.read(static_cast<T7&>(data)); break; 00800 case 7: reader.read(static_cast<T8&>(data)); break; 00801 default: break; 00802 } 00803 } 00804 00805 //*************************************************************************** 00806 /// Checks whether a valid value is currently stored. 00807 ///\return <b>true</b> if the value is valid, otherwise <b>false</b>. 00808 //*************************************************************************** 00809 bool is_valid() const 00810 { 00811 return type_id != UNSUPPORTED_TYPE_ID; 00812 } 00813 00814 //*************************************************************************** 00815 /// Checks to see if the type currently stored is the same as that specified in the template parameter. 00816 ///\return <b>true</b> if it is the specified type, otherwise <b>false</b>. 00817 //*************************************************************************** 00818 template <typename T> 00819 bool is_type() const 00820 { 00821 return type_id == Type_Id_Lookup<T>::type_id; 00822 } 00823 00824 //*************************************************************************** 00825 /// Clears the value to 'no valid stored value'. 00826 //*************************************************************************** 00827 void clear() 00828 { 00829 destruct_current(); 00830 } 00831 00832 //*************************************************************************** 00833 /// Gets the value stored as the specified template type. 00834 /// Throws a variant_incorrect_type_exception if the actual type is not that specified. 00835 ///\return A reference to the value. 00836 //*************************************************************************** 00837 template <typename T> 00838 T& get() 00839 { 00840 STATIC_ASSERT(Type_Is_Supported<T>::value, "Unsupported type"); 00841 ETL_ASSERT(is_type<T>(), ETL_ERROR(variant_incorrect_type_exception)); 00842 00843 return static_cast<T&>(data); 00844 } 00845 00846 //*************************************************************************** 00847 /// Gets the value stored as the specified template type. 00848 /// Throws a variant_incorrect_type_exception if the actual type is not that specified. 00849 ///\return A const reference to the value. 00850 //*************************************************************************** 00851 template <typename T> 00852 const T& get() const 00853 { 00854 STATIC_ASSERT(Type_Is_Supported<T>::value, "Unsupported type"); 00855 ETL_ASSERT(is_type<T>(), ETL_ERROR(variant_incorrect_type_exception)); 00856 00857 return static_cast<const T&>(data); 00858 } 00859 00860 //*************************************************************************** 00861 /// Gets the value stored as the specified template type. 00862 ///\return A reference to the value. 00863 //*************************************************************************** 00864 template <typename TBase> 00865 TBase& upcast() 00866 { 00867 return upcast_functor<TBase, T1, T2, T3, T4, T5, T6, T7, T8>()(data, type_id); 00868 } 00869 00870 //*************************************************************************** 00871 /// Gets the value stored as the specified template type. 00872 ///\return A const reference to the value. 00873 //*************************************************************************** 00874 template <typename TBase> 00875 const TBase& upcast() const 00876 { 00877 return upcast_functor<TBase, T1, T2, T3, T4, T5, T6, T7, T8>()(data, type_id); 00878 } 00879 00880 //*************************************************************************** 00881 /// Conversion operators for each type. 00882 //*************************************************************************** 00883 operator T1&() { return get<T1>(); } 00884 operator T2&() { return get<T2>(); } 00885 operator T3&() { return get<T3>(); } 00886 operator T4&() { return get<T4>(); } 00887 operator T5&() { return get<T5>(); } 00888 operator T6&() { return get<T6>(); } 00889 operator T7&() { return get<T7>(); } 00890 operator T8&() { return get<T8>(); } 00891 00892 //*************************************************************************** 00893 /// Checks if the template type is supported by the implementation of variant.. 00894 ///\return <b>true</b> if the type is supported, otherwise <b>false</b>. 00895 //*************************************************************************** 00896 template <typename T> 00897 static bool is_supported_type() 00898 { 00899 return Type_Is_Supported<T>::value; 00900 } 00901 00902 private: 00903 00904 //*************************************************************************** 00905 /// Destruct the current occupant of the variant. 00906 //*************************************************************************** 00907 void destruct_current() 00908 { 00909 switch (type_id) 00910 { 00911 case 0: { static_cast<T1*>(data)->~T1(); break; } 00912 case 1: { static_cast<T2*>(data)->~T2(); break; } 00913 case 2: { static_cast<T3*>(data)->~T3(); break; } 00914 case 3: { static_cast<T4*>(data)->~T4(); break; } 00915 case 4: { static_cast<T5*>(data)->~T5(); break; } 00916 case 5: { static_cast<T6*>(data)->~T6(); break; } 00917 case 6: { static_cast<T7*>(data)->~T7(); break; } 00918 case 7: { static_cast<T8*>(data)->~T8(); break; } 00919 default: { break; } 00920 } 00921 00922 type_id = UNSUPPORTED_TYPE_ID; 00923 } 00924 00925 //*************************************************************************** 00926 /// The internal storage. 00927 /// Aligned on a suitable boundary, which should be good for all types. 00928 //*************************************************************************** 00929 typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; 00930 00931 //*************************************************************************** 00932 /// The id of the current stored type. 00933 //*************************************************************************** 00934 type_id_t type_id; 00935 }; 00936 } 00937 00938 #undef ETL_FILE 00939 00940 #endif 00941
Generated on Tue Jul 12 2022 14:05:46 by
