Embedded Template Library  1.0
 All Classes Files Functions Variables Typedefs Friends Modules Pages
variant.h
Go to the documentation of this file.
1 
3 /******************************************************************************
4 The MIT License(MIT)
5 
6 Embedded Template Library.
7 
8 Copyright(c) 2014 jwellbelove
9 
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files(the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions :
16 
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 SOFTWARE.
27 ******************************************************************************/
28 
29 #ifndef __ETL_VARIANT__
30 #define __ETL_VARIANT__
31 
32 #include <stdint.h>
33 
34 #include "array.h"
35 #include "largest.h"
36 #include "exception.h"
37 #include "type_traits.h"
38 #include "integral_limits.h"
39 #include "static_assert.h"
40 #include "alignment.h"
41 
42 #if defined(COMPILER_KEIL)
43  #pragma diag_suppress 940
44 #endif
45 
46 //*****************************************************************************
50 //*****************************************************************************
51 
52 namespace etl
53 {
54  namespace __private_variant__
55  {
56  //*************************************************************************
59  //*************************************************************************
60  template <const size_t ID>
61  struct no_type
62  {
63  };
64  }
65 
66  //***************************************************************************
69  //***************************************************************************
71  {
72  public:
73  variant_exception(const char* what)
74  : exception(what)
75  {
76  }
77  };
78 
79  //***************************************************************************
82  //***************************************************************************
84  {
85  public:
87  : variant_exception("variant: unsupported type")
88  {
89  }
90  };
91 
92  //***************************************************************************
95  //***************************************************************************
97  {
98  public:
100  : variant_exception("variant: invalid type id")
101  {
102  }
103  };
104 
105  //***************************************************************************
109  //***************************************************************************
110  template <typename T1,
111  typename T2 = __private_variant__::no_type<2>,
112  typename T3 = __private_variant__::no_type<3>,
113  typename T4 = __private_variant__::no_type<4>,
114  typename T5 = __private_variant__::no_type<5>,
115  typename T6 = __private_variant__::no_type<6>,
116  typename T7 = __private_variant__::no_type<7>,
117  typename T8 = __private_variant__::no_type<8> >
118  class variant
119  {
120  private:
121 
122  // All types of variant are friends.
123  template <typename U1, typename U2, typename U3, typename U4, typename U5, typename U6, typename U7, typename U8>
124  friend class variant;
125 
126  //***************************************************************************
128  //***************************************************************************
129  typedef typename largest_type<T1, T2, T3, T4, T5, T6, T7, T8>::type largest_t;
130 
131  //***************************************************************************
133  //***************************************************************************
135 
136  //***************************************************************************
138  //***************************************************************************
139  typedef uint8_t type_id_t;
140 
141  //***************************************************************************
143  //***************************************************************************
144  static const type_id_t UNSUPPORTED_TYPE_ID = integral_limits<type_id_t>::max;
145 
146  //***************************************************************************
148  //***************************************************************************
149  template <typename T>
150  struct pass_by_value : integral_constant<bool, etl::is_fundamental<T>::value || etl::is_pointer<T>::value>
151  {
152  };
153 
154  //***************************************************************************
156  //***************************************************************************
157  template <typename T, bool>
158  struct type_definition;
159 
160  //***************************************************************************
162  //***************************************************************************
163  template <typename T>
164  struct type_definition<T, true>
165  {
166  typedef T type;
167  };
168 
169  //***************************************************************************
171  //***************************************************************************
172  template <typename T>
173  struct type_definition<T, false>
174  {
175  typedef const T& type;
176  };
177 
178  //***************************************************************************
180  //***************************************************************************
181  template <typename T>
182  struct parameter_type : public type_definition<T, pass_by_value<T>::value>
183  {
184  };
185 
186  //***************************************************************************
188  //***************************************************************************
196 
197  //***************************************************************************
199  //***************************************************************************
200  template <typename T>
201  struct Type_Id_Lookup
202  {
203  static const uint8_t type_id = etl::is_same<T, T1>::value ? 0 :
211  UNSUPPORTED_TYPE_ID;
212  };
213 
214  //***************************************************************************
216  //***************************************************************************
217  template <typename T>
218  struct Type_Is_Supported : public integral_constant<bool,
219  is_same<T, T1>::value ||
220  is_same<T, T2>::value ||
221  is_same<T, T3>::value ||
222  is_same<T, T4>::value ||
223  is_same<T, T5>::value ||
224  is_same<T, T6>::value ||
225  is_same<T, T7>::value ||
226  is_same<T, T8>::value>
227  {
228  };
229 
230  public:
231 
232  //*************************************************************************
233  //**** Reader types *******************************************************
234  //*************************************************************************
235 
236  //*************************************************************************
240  //*************************************************************************
241  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>
243  {
244  public:
245 
246  friend class variant;
247 
248  virtual void read(typename parameter_type<R1>::type value) = 0;
249  virtual void read(typename parameter_type<R2>::type value) = 0;
250  virtual void read(typename parameter_type<R3>::type value) = 0;
251  virtual void read(typename parameter_type<R4>::type value) = 0;
252  virtual void read(typename parameter_type<R5>::type value) = 0;
253  virtual void read(typename parameter_type<R6>::type value) = 0;
254  virtual void read(typename parameter_type<R7>::type value) = 0;
255  virtual void read(typename parameter_type<R8>::type value) = 0;
256  };
257 
258  //*************************************************************************
260  //*************************************************************************
261  template <typename R1, typename R2, typename R3, typename R4, typename R5, typename R6, typename R7>
262  class reader_type<R1, R2, R3, R4, R5, R6, R7, no_type8>
263  {
264  public:
265 
266  friend class variant;
267 
268  virtual void read(typename parameter_type<R1>::type value) = 0;
269  virtual void read(typename parameter_type<R2>::type value) = 0;
270  virtual void read(typename parameter_type<R3>::type value) = 0;
271  virtual void read(typename parameter_type<R4>::type value) = 0;
272  virtual void read(typename parameter_type<R5>::type value) = 0;
273  virtual void read(typename parameter_type<R6>::type value) = 0;
274  virtual void read(typename parameter_type<R7>::type value) = 0;
275 
276  private:
277 
278  void read(no_type8&) {};
279  };
280 
281  //*************************************************************************
283  //*************************************************************************
284  template <typename R1, typename R2, typename R3, typename R4, typename R5, typename R6>
285  class reader_type<R1, R2, R3, R4, R5, R6, no_type7, no_type8>
286  {
287  public:
288 
289  friend class variant;
290 
291  virtual void read(typename parameter_type<R1>::type value) = 0;
292  virtual void read(typename parameter_type<R2>::type value) = 0;
293  virtual void read(typename parameter_type<R3>::type value) = 0;
294  virtual void read(typename parameter_type<R4>::type value) = 0;
295  virtual void read(typename parameter_type<R5>::type value) = 0;
296  virtual void read(typename parameter_type<R6>::type value) = 0;
297 
298  private:
299 
300  void read(no_type7&) {};
301  void read(no_type8&) {};
302  };
303 
304  //*************************************************************************
306  //*************************************************************************
307  template <typename R1, typename R2, typename R3, typename R4, typename R5>
308  class reader_type<R1, R2, R3, R4, R5, no_type6, no_type7, no_type8>
309  {
310  public:
311 
312  friend class variant;
313 
314  virtual void read(typename parameter_type<R1>::type value) = 0;
315  virtual void read(typename parameter_type<R2>::type value) = 0;
316  virtual void read(typename parameter_type<R3>::type value) = 0;
317  virtual void read(typename parameter_type<R4>::type value) = 0;
318  virtual void read(typename parameter_type<R5>::type value) = 0;
319 
320  private:
321 
322  void read(no_type6&) {};
323  void read(no_type7&) {};
324  void read(no_type8&) {};
325  };
326 
327  //*************************************************************************
329  //*************************************************************************
330  template <typename R1, typename R2, typename R3, typename R4>
331  class reader_type<R1, R2, R3, R4, no_type5, no_type6, no_type7, no_type8>
332  {
333  public:
334 
335  friend class variant;
336 
337  virtual void read(typename parameter_type<R1>::type value) = 0;
338  virtual void read(typename parameter_type<R2>::type value) = 0;
339  virtual void read(typename parameter_type<R3>::type value) = 0;
340  virtual void read(typename parameter_type<R4>::type value) = 0;
341 
342  private:
343 
344  void read(no_type5&) {};
345  void read(no_type6&) {};
346  void read(no_type7&) {};
347  void read(no_type8&) {};
348  };
349 
350  //*************************************************************************
352  //*************************************************************************
353  template <typename R1, typename R2, typename R3>
354  class reader_type<R1, R2, R3, no_type4, no_type5, no_type6, no_type7, no_type8>
355  {
356  public:
357 
358  friend class variant;
359 
360  virtual void read(typename parameter_type<R1>::type value) = 0;
361  virtual void read(typename parameter_type<R2>::type value) = 0;
362  virtual void read(typename parameter_type<R3>::type value) = 0;
363 
364  private:
365 
366  void read(no_type4&) {};
367  void read(no_type5&) {};
368  void read(no_type6&) {};
369  void read(no_type7&) {};
370  void read(no_type8&) {};
371  };
372 
373  //*************************************************************************
375  //*************************************************************************
376  template <typename R1, typename R2>
377  class reader_type<R1, R2, no_type3, no_type4, no_type5, no_type6, no_type7, no_type8>
378  {
379  public:
380 
381  friend class variant;
382 
383  virtual void read(typename parameter_type<R1>::type value) = 0;
384  virtual void read(typename parameter_type<R2>::type value) = 0;
385 
386  private:
387 
388  void read(no_type3&) {};
389  void read(no_type4&) {};
390  void read(no_type5&) {};
391  void read(no_type6&) {};
392  void read(no_type7&) {};
393  void read(no_type8&) {};
394  };
395 
396  //*************************************************************************
398  //*************************************************************************
399  template <typename R1>
400  class reader_type<R1, no_type2, no_type3, no_type4, no_type5, no_type6, no_type7, no_type8>
401  {
402  public:
403 
404  friend class variant;
405 
406  virtual void read(typename parameter_type<R1>::type value) = 0;
407 
408  private:
409 
410  void read(no_type2&) {};
411  void read(no_type3&) {};
412  void read(no_type4&) {};
413  void read(no_type5&) {};
414  void read(no_type6&) {};
415  void read(no_type7&) {};
416  void read(no_type8&) {};
417  };
418 
419  //*************************************************************************
420  //**** Up-cast functors ***************************************************
421  //*************************************************************************
422 
423  //*************************************************************************
425  //*************************************************************************
426  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>
428  {
429  public:
430 
431  TBase& operator()(uint8_t* p_data, uint8_t typeId)
432  {
433  switch (typeId)
434  {
435  case 0: return reinterpret_cast<U1&>(*p_data);
436  case 1: return reinterpret_cast<U2&>(*p_data);
437  case 2: return reinterpret_cast<U3&>(*p_data);
438  case 3: return reinterpret_cast<U4&>(*p_data);
439  case 4: return reinterpret_cast<U5&>(*p_data);
440  case 5: return reinterpret_cast<U6&>(*p_data);
441  case 6: return reinterpret_cast<U7&>(*p_data);
442  case 7: return reinterpret_cast<U8&>(*p_data);
443  default:
444 #ifdef ETL_THROW_EXCEPTIONS
446 #endif
447  break;
448  }
449  }
450 
451  const TBase& operator()(uint8_t* p_data, uint8_t typeId) const
452  {
453  switch (typeId)
454  {
455  case 0: return reinterpret_cast<const U1&>(*p_data);
456  case 1: return reinterpret_cast<const U2&>(*p_data);
457  case 2: return reinterpret_cast<const U3&>(*p_data);
458  case 3: return reinterpret_cast<const U4&>(*p_data);
459  case 4: return reinterpret_cast<const U5&>(*p_data);
460  case 5: return reinterpret_cast<const U6&>(*p_data);
461  case 6: return reinterpret_cast<const U7&>(*p_data);
462  case 7: return reinterpret_cast<const U8&>(*p_data);
463  default:
464 #ifdef ETL_THROW_EXCEPTIONS
466 #endif
467  break;
468  }
469  }
470  };
471 
472  //*************************************************************************
474  //*************************************************************************
475  template <typename TBase, typename U1, typename U2, typename U3, typename U4, typename U5, typename U6, typename U7>
476  class upcast_functor<TBase, U1, U2, U3, U4, U5, U6, U7, no_type8>
477  {
478  public:
479 
480  TBase& operator()(uint8_t* p_data, uint8_t typeId)
481  {
482  switch (typeId)
483  {
484  case 0: return reinterpret_cast<U1&>(*p_data);
485  case 1: return reinterpret_cast<U2&>(*p_data);
486  case 2: return reinterpret_cast<U3&>(*p_data);
487  case 3: return reinterpret_cast<U4&>(*p_data);
488  case 4: return reinterpret_cast<U5&>(*p_data);
489  case 5: return reinterpret_cast<U6&>(*p_data);
490  case 6: return reinterpret_cast<U7&>(*p_data);
491  default:
492 #ifdef ETL_THROW_EXCEPTIONS
494 #endif
495  break;
496  }
497  }
498 
499  const TBase& operator()(uint8_t* p_data, uint8_t typeId) const
500  {
501  switch (typeId)
502  {
503  case 0: return reinterpret_cast<const U1&>(*p_data);
504  case 1: return reinterpret_cast<const U2&>(*p_data);
505  case 2: return reinterpret_cast<const U3&>(*p_data);
506  case 3: return reinterpret_cast<const U4&>(*p_data);
507  case 4: return reinterpret_cast<const U5&>(*p_data);
508  case 5: return reinterpret_cast<const U6&>(*p_data);
509  case 6: return reinterpret_cast<const U7&>(*p_data);
510  default:
511 #ifdef ETL_THROW_EXCEPTIONS
513 #endif
514  break;
515  }
516  }
517  };
518 
519  //*************************************************************************
521  //*************************************************************************
522  template <typename TBase, typename U1, typename U2, typename U3, typename U4, typename U5, typename U6>
523  class upcast_functor<TBase, U1, U2, U3, U4, U5, U6, no_type7, no_type8>
524  {
525  public:
526 
527  TBase& operator()(uint8_t* p_data, uint8_t typeId)
528  {
529  switch (typeId)
530  {
531  case 0: return reinterpret_cast<U1&>(*p_data);
532  case 1: return reinterpret_cast<U2&>(*p_data);
533  case 2: return reinterpret_cast<U3&>(*p_data);
534  case 3: return reinterpret_cast<U4&>(*p_data);
535  case 4: return reinterpret_cast<U5&>(*p_data);
536  case 5: return reinterpret_cast<U6&>(*p_data);
537  default:
538 #ifdef ETL_THROW_EXCEPTIONS
540 #endif
541  break;
542  }
543  }
544 
545  const TBase& operator()(uint8_t* p_data, uint8_t typeId) const
546  {
547  switch (typeId)
548  {
549  case 0: return reinterpret_cast<const U1&>(*p_data);
550  case 1: return reinterpret_cast<const U2&>(*p_data);
551  case 2: return reinterpret_cast<const U3&>(*p_data);
552  case 3: return reinterpret_cast<const U4&>(*p_data);
553  case 4: return reinterpret_cast<const U5&>(*p_data);
554  case 5: return reinterpret_cast<const U6&>(*p_data);
555  default:
556 #ifdef ETL_THROW_EXCEPTIONS
558 #endif
559  break;
560  }
561  }
562  };
563 
564  //*************************************************************************
566  //*************************************************************************
567  template <typename TBase, typename U1, typename U2, typename U3, typename U4, typename U5>
568  class upcast_functor<TBase, U1, U2, U3, U4, U5, no_type6, no_type7, no_type8>
569  {
570  public:
571 
572  TBase& operator()(uint8_t* p_data, uint8_t typeId)
573  {
574  switch (typeId)
575  {
576  case 0: return reinterpret_cast<U1&>(*p_data);
577  case 1: return reinterpret_cast<U2&>(*p_data);
578  case 2: return reinterpret_cast<U3&>(*p_data);
579  case 3: return reinterpret_cast<U4&>(*p_data);
580  case 4: return reinterpret_cast<U5&>(*p_data);
581  default:
582 #ifdef ETL_THROW_EXCEPTIONS
584 #endif
585  break;
586  }
587  }
588 
589  const TBase& operator()(uint8_t* p_data, uint8_t typeId) const
590  {
591  switch (typeId)
592  {
593  case 0: return reinterpret_cast<const U1&>(*p_data);
594  case 1: return reinterpret_cast<const U2&>(*p_data);
595  case 2: return reinterpret_cast<const U3&>(*p_data);
596  case 3: return reinterpret_cast<const U4&>(*p_data);
597  case 4: return reinterpret_cast<const U5&>(*p_data);
598  default:
599 #ifdef ETL_THROW_EXCEPTIONS
601 #endif
602  break;
603  }
604  }
605  };
606 
607  //*************************************************************************
609  //*************************************************************************
610  template <typename TBase, typename U1, typename U2, typename U3, typename U4>
611  class upcast_functor<TBase, U1, U2, U3, U4, no_type5, no_type6, no_type7, no_type8>
612  {
613  public:
614 
615  TBase& operator()(uint8_t* p_data, uint8_t typeId)
616  {
617  switch (typeId)
618  {
619  case 0: return reinterpret_cast<U1&>(*p_data);
620  case 1: return reinterpret_cast<U2&>(*p_data);
621  case 2: return reinterpret_cast<U3&>(*p_data);
622  case 3: return reinterpret_cast<U4&>(*p_data);
623  default:
624 #ifdef ETL_THROW_EXCEPTIONS
626 #endif
627  break;
628  }
629  }
630 
631  const TBase& operator()(uint8_t* p_data, uint8_t typeId) const
632  {
633  switch (typeId)
634  {
635  case 0: return reinterpret_cast<const U1&>(*p_data);
636  case 1: return reinterpret_cast<const U2&>(*p_data);
637  case 2: return reinterpret_cast<const U3&>(*p_data);
638  case 3: return reinterpret_cast<const U4&>(*p_data);
639  default:
640 #ifdef ETL_THROW_EXCEPTIONS
642 #endif
643  break;
644  }
645  }
646  };
647 
648  //*************************************************************************
650  //*************************************************************************
651  template <typename TBase, typename U1, typename U2, typename U3>
652  class upcast_functor<TBase, U1, U2, U3, no_type4, no_type5, no_type6, no_type7, no_type8>
653  {
654  public:
655 
656  TBase& operator()(uint8_t* p_data, uint8_t typeId)
657  {
658  switch (typeId)
659  {
660  case 0: return reinterpret_cast<U1&>(*p_data);
661  case 1: return reinterpret_cast<U2&>(*p_data);
662  case 2: return reinterpret_cast<U3&>(*p_data);
663  default:
664 #ifdef ETL_THROW_EXCEPTIONS
666 #endif
667  break;
668  }
669  }
670 
671  const TBase& operator()(uint8_t* p_data, uint8_t typeId) const
672  {
673  switch (typeId)
674  {
675  case 0: return reinterpret_cast<const U1&>(*p_data);
676  case 1: return reinterpret_cast<const U2&>(*p_data);
677  case 2: return reinterpret_cast<const U3&>(*p_data);
678  default:
679 #ifdef ETL_THROW_EXCEPTIONS
681 #endif
682  break;
683  }
684  }
685  };
686 
687  //*************************************************************************
689  //*************************************************************************
690  template <typename TBase, typename U1, typename U2>
691  class upcast_functor<TBase, U1, U2, no_type3, no_type4, no_type5, no_type6, no_type7, no_type8>
692  {
693  public:
694 
695  TBase& operator()(uint8_t* p_data, uint8_t typeId)
696  {
697  switch (typeId)
698  {
699  case 0: return reinterpret_cast<U1&>(*p_data);
700  case 1: return reinterpret_cast<U2&>(*p_data);
701  default:
702 #ifdef ETL_THROW_EXCEPTIONS
704 #endif
705  break;
706  }
707  }
708 
709  const TBase& operator()(uint8_t* p_data, uint8_t typeId) const
710  {
711  switch (typeId)
712  {
713  case 0: return reinterpret_cast<const U1&>(*p_data);
714  case 1: return reinterpret_cast<const U2&>(*p_data);
715  default:
716 #ifdef ETL_THROW_EXCEPTIONS
718 #endif
719  break;
720  }
721  }
722  };
723 
724  //*************************************************************************
726  //*************************************************************************
727  template <typename TBase, typename U1>
728  class upcast_functor<TBase, U1, no_type2, no_type3, no_type4, no_type5, no_type6, no_type7, no_type8>
729  {
730  public:
731 
732  TBase& operator()(uint8_t* p_data, uint8_t typeId)
733  {
734  switch (typeId)
735  {
736  case 0: return reinterpret_cast<U1&>(*p_data);
737  default:
738 #ifdef ETL_THROW_EXCEPTIONS
740 #endif
741  break;
742  }
743  }
744 
745  const TBase& operator()(uint8_t* p_data, uint8_t typeId) const
746  {
747  switch (typeId)
748  {
749  case 0: return reinterpret_cast<const U1&>(*p_data);
750  default:
751 #ifdef ETL_THROW_EXCEPTIONS
753 #endif
754  break;
755  }
756  }
757  };
758 
759  //***************************************************************************
761  //***************************************************************************
763 
764  //***************************************************************************
767  //***************************************************************************
769  : type_id(UNSUPPORTED_TYPE_ID)
770  {
771  }
772 
773  //***************************************************************************
776  //***************************************************************************
777  template <typename T>
778  variant(T value)
779  {
780  STATIC_ASSERT(Type_Is_Supported<T>::value, "Unsupported type");
781 
782  new(&data.value[0]) T(value);
783  type_id = Type_Id_Lookup<T>::type_id;
784  }
785 
786  //***************************************************************************
789  //***************************************************************************
790  variant(const variant& other)
791  : data(other.data),
792  type_id(other.type_id)
793  {
794  }
795 
796  //***************************************************************************
799  //***************************************************************************
800  template <typename T>
801  variant& operator =(typename parameter_type<T>::type value)
802  {
803  STATIC_ASSERT(Type_Is_Supported<T>::value, "Unsupported type");
804 
805  new(&data.value[0]) T(value);
806  type_id = Type_Id_Lookup<T>::type_id;
807  return *this;
808  }
809 
810  //***************************************************************************
814  //***************************************************************************
815  bool is_same_type(const variant& other) const
816  {
817  return type_id == other.type_id;
818  }
819 
820  //***************************************************************************
824  //***************************************************************************
825  template <typename U1, typename U2, typename U3, typename U4, typename U5, typename U6, typename U7, typename U8>
827  {
828  bool is_same_type = false;
829 
830  switch (other.type_id)
831  {
832  case 0: is_same_type = type_id == Type_Id_Lookup<U1>::type_id; break;
833  case 1: is_same_type = type_id == Type_Id_Lookup<U2>::type_id; break;
834  case 2: is_same_type = type_id == Type_Id_Lookup<U3>::type_id; break;
835  case 3: is_same_type = type_id == Type_Id_Lookup<U4>::type_id; break;
836  case 4: is_same_type = type_id == Type_Id_Lookup<U5>::type_id; break;
837  case 5: is_same_type = type_id == Type_Id_Lookup<U6>::type_id; break;
838  case 6: is_same_type = type_id == Type_Id_Lookup<U7>::type_id; break;
839  case 7: is_same_type = type_id == Type_Id_Lookup<U8>::type_id; break;
840  default:
841 #ifdef ETL_THROW_EXCEPTIONS
843 #endif
844  break;
845  }
846 
847  return is_same_type;
848  }
849 
850  //***************************************************************************
853  //***************************************************************************
854  void call(reader& reader)
855  {
856  switch (type_id)
857  {
858  case 0: reader.read(reinterpret_cast<T1&>(*&data.value[0])); break;
859  case 1: reader.read(reinterpret_cast<T2&>(*&data.value[0])); break;
860  case 2: reader.read(reinterpret_cast<T3&>(*&data.value[0])); break;
861  case 3: reader.read(reinterpret_cast<T4&>(*&data.value[0])); break;
862  case 4: reader.read(reinterpret_cast<T5&>(*&data.value[0])); break;
863  case 5: reader.read(reinterpret_cast<T6&>(*&data.value[0])); break;
864  case 6: reader.read(reinterpret_cast<T7&>(*&data.value[0])); break;
865  case 7: reader.read(reinterpret_cast<T8&>(*&data.value[0])); break;
866  default:
867 #ifdef ETL_THROW_EXCEPTIONS
869 #endif
870  break;
871  }
872  }
873 
874  //***************************************************************************
877  //***************************************************************************
878  bool is_valid() const
879  {
880  return type_id != UNSUPPORTED_TYPE_ID;
881  }
882 
883  //***************************************************************************
886  //***************************************************************************
887  template <typename T>
888  bool is_type() const
889  {
890  return type_id == Type_Id_Lookup<T>::type_id;
891  }
892 
893  //***************************************************************************
895  //***************************************************************************
896  void clear()
897  {
898  type_id = UNSUPPORTED_TYPE_ID;
899  }
900 
901  //***************************************************************************
905  //***************************************************************************
906  template <typename T>
907  T& get()
908  {
909  STATIC_ASSERT(Type_Is_Supported<T>::value, "Unsupported type");
910 
911 #ifdef ETL_THROW_EXCEPTIONS
912  if (!is_type<T>())
913  {
915  }
916 #endif
917 
918  return reinterpret_cast<T&>(*&data.value[0]);
919  }
920 
921  //***************************************************************************
925  //***************************************************************************
926  template <typename T>
927  const T& get() const
928  {
929  STATIC_ASSERT(Type_Is_Supported<T>::value, "Unsupported type");
930 
931 #ifdef ETL_THROW_EXCEPTIONS
932  if (!is_type<T>())
933  {
935  }
936 #endif
937 
938  return reinterpret_cast<const T&>(*&data.value[0]);
939  }
940 
941  //***************************************************************************
944  //***************************************************************************
945  template <typename TBase>
946  TBase& upcast()
947  {
948  return upcast_functor<TBase, T1, T2, T3, T4, T5, T6, T7, T8>()(&data.value[0], type_id);
949  }
950 
951  //***************************************************************************
954  //***************************************************************************
955  template <typename TBase>
956  const TBase& upcast() const
957  {
958  return upcast_functor<TBase, T1, T2, T3, T4, T5, T6, T7, T8>()(&data.value[0], type_id);
959  }
960 
961  //***************************************************************************
963  //***************************************************************************
964  operator T1&() { return get<T1>(); }
965  operator T2&() { return get<T2>(); }
966  operator T3&() { return get<T3>(); }
967  operator T4&() { return get<T4>(); }
968  operator T5&() { return get<T5>(); }
969  operator T6&() { return get<T6>(); }
970  operator T7&() { return get<T7>(); }
971  operator T8&() { return get<T8>(); }
972 
973  //***************************************************************************
976  //***************************************************************************
977  template <typename T>
978  static bool is_supported_type()
979  {
980  return Type_Is_Supported<T>::value;
981  }
982 
983  private:
984 
985  //***************************************************************************
987  //***************************************************************************
988  template <typename TBase, typename T>
989  TBase& do_upcast(T& t)
990  {
991  return upcast_functor<TBase, T1, T2, T3, T4, T5, T6, T7, T8>()(t);
992  }
993 
994  //***************************************************************************
996  //***************************************************************************
997  template <typename TBase, typename T>
998  const TBase& do_upcast(const T& t) const
999  {
1000  return upcast_functor<TBase, T1, T2, T3, T4, T5, T6, T7, T8>()(t);
1001  }
1002 
1003  //***************************************************************************
1006  //***************************************************************************
1007  align_at<array<uint8_t, sizeof(largest_t)>, ALIGNMENT> data;
1008 
1009  //***************************************************************************
1011  //***************************************************************************
1012  type_id_t type_id;
1013  };
1014 }
1015 
1016 #endif
Definition: variant.h:70
const TBase & upcast() const
Definition: variant.h:956
reader_type< T1, T2, T3, T4, T5, T6, T7, T8 > reader
The base type for derived readers.
Definition: variant.h:762
static bool is_supported_type()
Definition: variant.h:978
variant & operator=(typename parameter_type< T >::type value)
Definition: variant.h:801
Definition: variant.h:118
bool is_valid() const
Definition: variant.h:878
bool is_same_type(const variant< U1, U2, U3, U4, U5, U6, U7, U8 > &other) const
Definition: variant.h:826
exception(value_type reason)
Constructor.
Definition: exception.h:51
Definition: largest.h:120
void clear()
Clears the value to 'no valid stored value'.
Definition: variant.h:896
Definition: variant.h:242
Definition: algorithm.h:43
TBase & upcast()
Definition: variant.h:946
Definition: integral_limits.h:54
bool is_type() const
Definition: variant.h:888
variant()
Definition: variant.h:768
variant(const variant &other)
Definition: variant.h:790
variant(T value)
Definition: variant.h:778
Definition: exception.h:42
Definition: type_traits.h:195
value_type what() const
Definition: exception.h:60
Definition: type_traits.h:45
Base upcast_functor for eight types.
Definition: variant.h:427
bool is_same_type(const variant &other) const
Definition: variant.h:815
void call(reader &reader)
Definition: variant.h:854
Definition: variant.h:61