Stefan Scholz / ETL
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers variant.h Source File

variant.h

Go to the documentation of this file.
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