38#include "../static_assert.h"
41#include "../null_type.h"
47#if defined(ETL_COMPILER_KEIL)
48 #pragma diag_suppress 940
49 #pragma diag_suppress 111
59#if ETL_NOT_USING_LEGACY_VARIANT
63 namespace private_variant
88 variant_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
89 :
exception(reason_, file_name_, line_number_)
98 class variant_incorrect_type_exception :
public variant_exception
101 variant_incorrect_type_exception(string_type file_name_, numeric_type line_number_)
102 : variant_exception(ETL_ERROR_TEXT(
"variant:unsupported type", ETL_VARIANT_FILE_ID
"A"), file_name_, line_number_)
111 class bad_variant_access :
public variant_exception
114 bad_variant_access(string_type file_name_, numeric_type line_number_)
115 : variant_exception(ETL_ERROR_TEXT(
"variant:bad variant access", ETL_VARIANT_FILE_ID
"B"), file_name_, line_number_)
123 class variant_not_a_base_exception :
public variant_exception
126 variant_not_a_base_exception(string_type file_name_, numeric_type line_number_)
127 : variant_exception(ETL_ERROR_TEXT(
"variant:not_a base", ETL_VARIANT_FILE_ID
"C"), file_name_, line_number_)
137 template <
typename T1,
162 template <
typename V1,
typename V2,
typename V3,
typename V4,
typename V5,
typename V6,
typename V7,
typename V8>
163 friend class variant;
168 typedef typename etl::largest_type<T1, T2, T3, T4, T5, T6, T7, T8>::type largest_t;
173 static const size_t SIZE =
sizeof(largest_t);
178 static const size_t ALIGNMENT = etl::largest_alignment<T1, T2, T3, T4, T5, T6, T7, T8>::value;
194 template <
typename T>
195 struct Type_Id_Lookup
211 template <
typename T>
213 etl::is_same<T, T1>::value ||
214 etl::is_same<T, T2>::value ||
215 etl::is_same<T, T3>::value ||
216 etl::is_same<T, T4>::value ||
217 etl::is_same<T, T5>::value ||
218 etl::is_same<T, T6>::value ||
219 etl::is_same<T, T7>::value ||
220 etl::is_same<T, T8>::value>
243 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>
248 friend class variant;
267 template <
typename R1,
typename R2,
typename R3,
typename R4,
typename R5,
typename R6,
typename R7>
272 friend class variant;
288 void read(no_type8&) {};
294 template <
typename R1,
typename R2,
typename R3,
typename R4,
typename R5,
typename R6>
299 friend class variant;
314 void read(no_type7&) {};
315 void read(no_type8&) {};
321 template <
typename R1,
typename R2,
typename R3,
typename R4,
typename R5>
322 class reader_type<R1, R2, R3, R4, R5, no_type6, no_type7, no_type8>
326 friend class variant;
340 void read(no_type6&) {};
341 void read(no_type7&) {};
342 void read(no_type8&) {};
348 template <
typename R1,
typename R2,
typename R3,
typename R4>
349 class reader_type<R1, R2, R3, R4, no_type5, no_type6, no_type7, no_type8>
353 friend class variant;
366 void read(no_type5&) {};
367 void read(no_type6&) {};
368 void read(no_type7&) {};
369 void read(no_type8&) {};
375 template <
typename R1,
typename R2,
typename R3>
376 class reader_type<R1, R2, R3, no_type4, no_type5, no_type6, no_type7, no_type8>
380 friend class variant;
392 void read(no_type4&) {};
393 void read(no_type5&) {};
394 void read(no_type6&) {};
395 void read(no_type7&) {};
396 void read(no_type8&) {};
402 template <
typename R1,
typename R2>
403 class reader_type<R1, R2, no_type3, no_type4, no_type5, no_type6, no_type7, no_type8>
407 friend class variant;
418 void read(no_type3&) {};
419 void read(no_type4&) {};
420 void read(no_type5&) {};
421 void read(no_type6&) {};
422 void read(no_type7&) {};
423 void read(no_type8&) {};
429 template <
typename R1>
430 class reader_type<R1, no_type2, no_type3, no_type4, no_type5, no_type6, no_type7, no_type8>
434 friend class variant;
444 void read(no_type2&) {};
445 void read(no_type3&) {};
446 void read(no_type4&) {};
447 void read(no_type5&) {};
448 void read(no_type6&) {};
449 void read(no_type7&) {};
450 void read(no_type8&) {};
456 typedef reader_type<T1, T2, T3, T4, T5, T6, T7, T8>
reader;
473 template <
typename T>
476 ETL_STATIC_ASSERT(Type_Is_Supported<T>::value,
"Unsupported type");
478 ::new (
static_cast<T*
>(data)) T(value);
479 type_id = Type_Id_Lookup<T>::type_id;
486 template <
size_t Index,
typename T>
490 ETL_STATIC_ASSERT(Type_Id_Lookup<T>::type_id == Index,
"Missmatched type");
491 ::new (
static_cast<T*
>(data)) T(value);
502 switch (other.type_id)
504 case 0: ::new (
static_cast<T1*
>(data)) T1(other.
get<T1>());
break;
505 case 1: ::new (
static_cast<T2*
>(data)) T2(other.
get<T2>());
break;
506 case 2: ::new (
static_cast<T3*
>(data)) T3(other.
get<T3>());
break;
507 case 3: ::new (
static_cast<T4*
>(data)) T4(other.
get<T4>());
break;
508 case 4: ::new (
static_cast<T5*
>(data)) T5(other.
get<T5>());
break;
509 case 5: ::new (
static_cast<T6*
>(data)) T6(other.
get<T6>());
break;
510 case 6: ::new (
static_cast<T7*
>(data)) T7(other.
get<T7>());
break;
511 case 7: ::new (
static_cast<T8*
>(data)) T8(other.
get<T8>());
break;
515 type_id = other.type_id;
519#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_VARIANT_FORCE_CPP03_IMPLEMENTATION)
523 template <
typename T,
typename... Args>
524 T& emplace(Args&&... args)
526 ETL_STATIC_ASSERT(Type_Is_Supported<T>::value,
"Unsupported type");
529 ::new (
static_cast<T*
>(data)) T(etl::forward<Args>(args)...);
530 type_id = Type_Id_Lookup<T>::type_id;
532 return *
static_cast<T*
>(data);
538 template <
typename T>
541 ETL_STATIC_ASSERT(Type_Is_Supported<T>::value,
"Unsupported type");
544 ::new (
static_cast<T*
>(data)) T();
545 type_id = Type_Id_Lookup<T>::type_id;
547 return *
static_cast<T*
>(data);
553 template <
typename T,
typename TP1>
556 ETL_STATIC_ASSERT(Type_Is_Supported<T>::value,
"Unsupported type");
559 ::new (
static_cast<T*
>(data)) T(value1);
560 type_id = Type_Id_Lookup<T>::type_id;
562 return *
static_cast<T*
>(data);
568 template <
typename T,
typename TP1,
typename TP2>
569 T&
emplace(
const TP1& value1,
const TP2& value2)
571 ETL_STATIC_ASSERT(Type_Is_Supported<T>::value,
"Unsupported type");
574 ::new (
static_cast<T*
>(data)) T(value1, value2);
575 type_id = Type_Id_Lookup<T>::type_id;
577 return *
static_cast<T*
>(data);
583 template <
typename T,
typename TP1,
typename TP2,
typename TP3>
584 T&
emplace(
const TP1& value1,
const TP2& value2,
const TP3& value3)
586 ETL_STATIC_ASSERT(Type_Is_Supported<T>::value,
"Unsupported type");
589 ::new (
static_cast<T*
>(data)) T(value1, value2, value3);
590 type_id = Type_Id_Lookup<T>::type_id;
592 return *
static_cast<T*
>(data);
598 template <
typename T,
typename TP1,
typename TP2,
typename TP3,
typename TP4>
599 T&
emplace(
const TP1& value1,
const TP2& value2,
const TP3& value3,
const TP4& value4)
601 ETL_STATIC_ASSERT(Type_Is_Supported<T>::value,
"Unsupported type");
604 ::new (
static_cast<T*
>(data)) T(value1, value2, value3, value4);
605 type_id = Type_Id_Lookup<T>::type_id;
607 return *
static_cast<T*
>(data);
615 template <
typename T>
616 variant& operator =(
const T& value)
618 ETL_STATIC_ASSERT(Type_Is_Supported<T>::value,
"Unsupported type");
621 ::new (
static_cast<T*
>(data)) T(value);
622 type_id = Type_Id_Lookup<T>::type_id;
631 variant& operator =(
const variant& other)
637 switch (other.type_id)
639 case 0: ::new (
static_cast<T1*
>(data)) T1(other.
get<T1>());
break;
640 case 1: ::new (
static_cast<T2*
>(data)) T2(other.
get<T2>());
break;
641 case 2: ::new (
static_cast<T3*
>(data)) T3(other.
get<T3>());
break;
642 case 3: ::new (
static_cast<T4*
>(data)) T4(other.
get<T4>());
break;
643 case 4: ::new (
static_cast<T5*
>(data)) T5(other.
get<T5>());
break;
644 case 5: ::new (
static_cast<T6*
>(data)) T6(other.
get<T6>());
break;
645 case 6: ::new (
static_cast<T7*
>(data)) T7(other.
get<T7>());
break;
646 case 7: ::new (
static_cast<T8*
>(data)) T8(other.
get<T8>());
break;
650 type_id = other.type_id;
663 return type_id == other.type_id;
671 template <
typename V1,
typename V2,
typename V3,
typename V4,
typename V5,
typename V6,
typename V7,
typename V8>
672 bool is_same_type(
const variant<V1, V2, V3, V4, V5, V6, V7, V8>& other)
const
676 switch (other.type_id)
678 case 0:
is_same = (type_id == Type_Id_Lookup<V1>::type_id);
break;
679 case 1:
is_same = (type_id == Type_Id_Lookup<V2>::type_id);
break;
680 case 2:
is_same = (type_id == Type_Id_Lookup<V3>::type_id);
break;
681 case 3:
is_same = (type_id == Type_Id_Lookup<V4>::type_id);
break;
682 case 4:
is_same = (type_id == Type_Id_Lookup<V5>::type_id);
break;
683 case 5:
is_same = (type_id == Type_Id_Lookup<V6>::type_id);
break;
684 case 6:
is_same = (type_id == Type_Id_Lookup<V7>::type_id);
break;
685 case 7:
is_same = (type_id == Type_Id_Lookup<V8>::type_id);
break;
700 case 0: r.read(
static_cast<T1&
>(data));
break;
701 case 1: r.read(
static_cast<T2&
>(data));
break;
702 case 2: r.read(
static_cast<T3&
>(data));
break;
703 case 3: r.read(
static_cast<T4&
>(data));
break;
704 case 4: r.read(
static_cast<T5&
>(data));
break;
705 case 5: r.read(
static_cast<T6&
>(data));
break;
706 case 6: r.read(
static_cast<T7&
>(data));
break;
707 case 7: r.read(
static_cast<T8&
>(data));
break;
725 template <
typename T>
728 return type_id == Type_Id_Lookup<T>::type_id;
752 template <
typename T>
755 ETL_STATIC_ASSERT(Type_Is_Supported<T>::value,
"Unsupported type");
758 return static_cast<T&
>(data);
766 template <
typename T>
769 ETL_STATIC_ASSERT(Type_Is_Supported<T>::value,
"Unsupported type");
772 return static_cast<const T&
>(data);
779 template <
typename TBase>
784 return reinterpret_cast<TBase*
>(
static_cast<uint_least8_t*
>(data));
796 template <
typename TBase>
810 template <
typename TBase>
815 return reinterpret_cast<const TBase*
>(
static_cast<const uint_least8_t*
>(data));
827 template <
typename TBase>
840 template <
typename TBase>
855 default: is_base =
false;
break;
865 operator T2& () {
return get<T2>(); }
866 operator T3& () {
return get<T3>(); }
867 operator T4& () {
return get<T4>(); }
868 operator T5& () {
return get<T5>(); }
869 operator T6& () {
return get<T6>(); }
870 operator T7& () {
return get<T7>(); }
871 operator T8& () {
return get<T8>(); }
877 template <
typename T>
880 return Type_Is_Supported<T>::value;
888 void destruct_current()
892 case 0: {
static_cast<T1*
>(data)->~T1();
break; }
893 case 1: {
static_cast<T2*
>(data)->~T2();
break; }
894 case 2: {
static_cast<T3*
>(data)->~T3();
break; }
895 case 3: {
static_cast<T4*
>(data)->~T4();
break; }
896 case 4: {
static_cast<T5*
>(data)->~T5();
break; }
897 case 5: {
static_cast<T6*
>(data)->~T6();
break; }
898 case 6: {
static_cast<T7*
>(data)->~T7();
break; }
899 case 7: {
static_cast<T8*
>(data)->~T8();
break; }
903 type_id = UNSUPPORTED_TYPE_ID;
911 typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
919 namespace private_variant
921 template <
size_t,
typename>
923#define ETL_VARIANT_HELPER(INDEX, TYPE) \
924 template <typename T1, \
932 struct variant_alternative_helper<INDEX, variant<T1, T2, T3, T4, T5, T6, T7, T8> > \
936 ETL_VARIANT_HELPER(0, T1)
937 ETL_VARIANT_HELPER(1, T2)
938 ETL_VARIANT_HELPER(2, T3)
939 ETL_VARIANT_HELPER(3, T4)
940 ETL_VARIANT_HELPER(4, T5)
941 ETL_VARIANT_HELPER(5, T6)
942 ETL_VARIANT_HELPER(6, T7)
943 ETL_VARIANT_HELPER(7, T8)
944#undef ETL_VARIANT_HELPER
947 template <
size_t tIndex,
typename TVariant>
953 template <
size_t tIndex,
typename TVariant>
959 template <
size_t tIndex,
typename TVariant>
965 template <
size_t tIndex,
typename TVariant>
971 template <
typename T,
typename TVariant>
977 template <
typename T,
typename TVariant>
978 inline T
const& get(TVariant
const& variant)
980 return variant.template get<T>();
983 template <
size_t tIndex,
typename TVariant>
984 inline typename variant_alternative<tIndex, TVariant>::type&
get(TVariant& variant)
986 return get<typename variant_alternative<tIndex, TVariant>::type>(variant);
989 template <
size_t tIndex,
typename TVariant>
990 inline typename variant_alternative<tIndex, TVariant const>::type&
get(TVariant
const& variant)
992 return get<typename variant_alternative<tIndex, TVariant>::type>(variant);
995#define ETL_GEN_LEGACY_VISIT(VISITQUAL, VARIANTQUAL) \
996 template <typename TReturn, typename TVisitor, typename TVariant> \
997 static TReturn visit(TVisitor VISITQUAL visitor, TVariant VARIANTQUAL variant) \
999 switch (variant.index()) \
1001 case 0: return static_cast<TReturn>(visitor(get<0>(variant))); \
1002 case 1: return static_cast<TReturn>(visitor(get<1>(variant))); \
1003 case 2: return static_cast<TReturn>(visitor(get<2>(variant))); \
1004 case 3: return static_cast<TReturn>(visitor(get<3>(variant))); \
1005 case 4: return static_cast<TReturn>(visitor(get<4>(variant))); \
1006 case 5: return static_cast<TReturn>(visitor(get<5>(variant))); \
1007 case 6: return static_cast<TReturn>(visitor(get<6>(variant))); \
1008 case 7: return static_cast<TReturn>(visitor(get<7>(variant))); \
1009 default: ETL_ASSERT_FAIL_AND_RETURN_VALUE(ETL_ERROR(bad_variant_access), TReturn()); \
1013 ETL_GEN_LEGACY_VISIT(&, &)
1014 ETL_GEN_LEGACY_VISIT(const&, &)
1015 ETL_GEN_LEGACY_VISIT(&, const&)
1016 ETL_GEN_LEGACY_VISIT(const&, const&)
1018#undef ETL_GEN_LEGACY_VISIT
1020#if ETL_NOT_USING_LEGACY_VARIANT
Definition null_type.h:40
Definition variant_legacy.h:245
#define ETL_ASSERT(b, e)
Definition error_handler.h:356
ETL_CONSTEXPR exception(string_type reason_, string_type, numeric_type line_)
Constructor.
Definition exception.h:69
Definition exception.h:47
Definition integral_limits.h:516
integral_constant
Definition type_traits_generator.h:895
is_base_of
Definition type_traits_generator.h:1315
is_same
Definition type_traits_generator.h:1104
variant(const T &value)
Definition variant_legacy.h:474
static bool is_supported_type()
Definition variant_legacy.h:878
const T & get() const
Definition variant_legacy.h:767
~variant()
Destructor.
Definition variant_legacy.h:229
T & emplace(const TP1 &value1, const TP2 &value2, const TP3 &value3, const TP4 &value4)
Emplace with four constructor parameters.
Definition variant_legacy.h:599
bool is_same_type(const variant &other) const
Definition variant_legacy.h:661
T & emplace(const TP1 &value1, const TP2 &value2, const TP3 &value3)
Emplace with three constructor parameters.
Definition variant_legacy.h:584
void call(reader &r)
Definition variant_legacy.h:696
T & get()
Definition variant_legacy.h:753
bool is_base_of() const
Definition variant_legacy.h:841
variant(etl::in_place_index_t< Index >, T const &value)
Definition variant_legacy.h:487
uint_least8_t type_id_t
Definition variant_legacy.h:152
bool is_same_type(const variant< V1, V2, V3, V4, V5, V6, V7, V8 > &other) const
Definition variant_legacy.h:672
T & emplace(const TP1 &value1)
Emplace with one constructor parameter.
Definition variant_legacy.h:554
const TBase * upcast_ptr() const
Definition variant_legacy.h:811
reader_type< etl::monostate, value_type, error_type, etl::null_type< 4 >, etl::null_type< 5 >, etl::null_type< 6 >, etl::null_type< 7 >, etl::null_type< 8 > > reader
Definition variant_legacy.h:456
bool is_type() const
Definition variant_legacy.h:726
void clear()
Clears the value to 'no valid stored value'.
Definition variant_legacy.h:742
T & emplace(const TP1 &value1, const TP2 &value2)
Emplace with two constructor parameters.
Definition variant_legacy.h:569
TBase * upcast_ptr()
Definition variant_legacy.h:780
T & emplace()
Emplace with one constructor parameter.
Definition variant_legacy.h:539
size_t index() const
Gets the index of the type currently stored or UNSUPPORTED_TYPE_ID.
Definition variant_legacy.h:734
TBase & upcast()
Definition variant_legacy.h:797
static const type_id_t UNSUPPORTED_TYPE_ID
Definition variant_legacy.h:157
const TBase & upcast() const
Definition variant_legacy.h:828
bool is_valid() const
Definition variant_legacy.h:716
Definition variant_legacy.h:146
Definition variant_legacy.h:99
Definition variant_legacy.h:124
bitset_ext
Definition absolute.h:39
T & get(array< T, Size > &a)
Definition array.h:1216
A 'no-value' placeholder.
Definition monostate.h:42
etl::conditional< etl::is_fundamental< T >::value||etl::is_pointer< T >::value, T, constT & >::type type
By default fundamental and pointer types are passed by value.
Definition parameter_type.h:48
Definition variant_legacy.h:71
Definition variant_legacy.h:922
Definition variant_legacy.h:949