41#include "../nth_type.h"
43#include "../static_assert.h"
44#include "../type_list.h"
51#if defined(ETL_COMPILER_KEIL)
52 #pragma diag_suppress 940
53 #pragma diag_suppress 111
56#if ETL_CPP11_NOT_SUPPORTED
57 #if !defined(ETL_IN_UNIT_TEST)
58 #error NOT SUPPORTED FOR C++03 OR BELOW
70 namespace private_variant
75 static constexpr bool Copyable =
true;
76 static constexpr bool Non_Copyable =
false;
77 static constexpr bool Moveable =
true;
78 static constexpr bool Non_Moveable =
false;
83 static constexpr int Copy = 0;
84 static constexpr int Move = 1;
85 static constexpr int Destroy = 2;
90 template <
typename T,
bool IsCopyable,
bool IsMoveable>
91 struct operation_type;
96 struct operation_type<void, Non_Copyable, Non_Moveable>
98 static void do_operation(
int,
char*,
const char*)
101 #if defined(ETL_IN_UNIT_TEST)
109 template <
typename T>
110 struct operation_type<T, Non_Copyable, Non_Moveable>
112 static void do_operation(
int operation,
char* pstorage,
const char* )
118 reinterpret_cast<const T*
>(pstorage)->~T();
125 #if defined(ETL_IN_UNIT_TEST)
136 template <
typename T>
137 struct operation_type<T, Non_Copyable, Moveable>
139 static void do_operation(
int operation,
char* pstorage,
const char* pvalue)
145 ::new (pstorage) T(etl::move(*
reinterpret_cast<T*
>(
const_cast<char*
>(pvalue))));
151 reinterpret_cast<const T*
>(pstorage)->~T();
158 #if defined(ETL_IN_UNIT_TEST)
169 template <
typename T>
170 struct operation_type<T, Copyable, Non_Moveable>
172 static void do_operation(
int operation,
char* pstorage,
const char* pvalue)
178 ::new (pstorage) T(*
reinterpret_cast<const T*
>(pvalue));
184 reinterpret_cast<const T*
>(pstorage)->~T();
191 #if defined(ETL_IN_UNIT_TEST)
202 template <
typename T>
203 struct operation_type<T, Copyable, Moveable>
205 static void do_operation(
int operation,
char* pstorage,
const char* pvalue)
211 ::new (pstorage) T(*
reinterpret_cast<const T*
>(pvalue));
217 ::new (pstorage) T(etl::move(*
reinterpret_cast<T*
>(
const_cast<char*
>(pvalue))));
223 reinterpret_cast<const T*
>(pstorage)->~T();
230 #if defined(ETL_IN_UNIT_TEST)
241 constexpr size_t variant_npos = etl::integral_limits<size_t>::max;
245 template <
typename... TTypes>
251 template <
size_t Index,
typename T>
254 template <
size_t Index,
typename... TTypes>
257 using type = etl::nth_type_t<Index, TTypes...>;
260 template <
size_t Index,
typename T>
263 using type =
typename variant_alternative<Index, T>::type;
266 template <
size_t Index,
typename T>
267 using variant_alternative_t =
typename variant_alternative<Index, T>::type;
271 template <
typename T,
typename... TTypes>
272 ETL_CONSTEXPR14
bool holds_alternative(
const etl::variant<TTypes...>& v) ETL_NOEXCEPT;
276 template <
size_t Index,
typename... VTypes>
277 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...> >&
get(etl::variant<VTypes...>& v);
279 template <
size_t Index,
typename... VTypes>
280 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...> >&&
get(etl::variant<VTypes...>&& v);
282 template <
size_t Index,
typename... VTypes>
283 ETL_CONSTEXPR14
const etl::variant_alternative_t<Index,
const etl::variant<VTypes...> >&
get(
const etl::variant<VTypes...>& v);
285 template <
size_t Index,
typename... VTypes>
286 ETL_CONSTEXPR14
const etl::variant_alternative_t<Index,
const etl::variant<VTypes...> >&&
get(
const etl::variant<VTypes...>&& v);
288 template <
typename T,
typename... VTypes>
289 ETL_CONSTEXPR14 T&
get(etl::variant<VTypes...>& v);
291 template <
typename T,
typename... VTypes>
292 ETL_CONSTEXPR14 T&&
get(etl::variant<VTypes...>&& v);
294 template <
typename T,
typename... VTypes>
295 ETL_CONSTEXPR14
const T&
get(
const etl::variant<VTypes...>& v);
297 template <
typename T,
typename... VTypes>
298 ETL_CONSTEXPR14
const T&&
get(
const etl::variant<VTypes...>&& v);
300 #if ETL_NOT_USING_CPP17
301 #include "variant_select_do_operator.h"
302 #include "variant_select_do_visitor.h"
329 #if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
332 return std::strong_ordering::equal;
336 #if ETL_NOT_USING_STL && !defined(ETL_USE_TYPE_TRAITS_BUILTINS)
338 struct is_copy_constructible<etl::
monostate> :
public etl::true_type
343 struct is_move_constructible<etl::
monostate> :
public etl::true_type
356 variant_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
357 :
exception(reason_, file_name_, line_number_)
370 variant_incorrect_type_exception(string_type file_name_, numeric_type line_number_)
371 : variant_exception(ETL_ERROR_TEXT(
"variant:unsupported type", ETL_VARIANT_FILE_ID
"A"), file_name_, line_number_)
384 bad_variant_access(string_type file_name_, numeric_type line_number_)
385 : variant_exception(ETL_ERROR_TEXT(
"variant:bad variant access", ETL_VARIANT_FILE_ID
"B"), file_name_, line_number_)
395 template <
typename... TTypes>
400 using type_list = etl::type_list<TTypes...>;
405 template <
size_t Index,
typename... VTypes>
406 friend ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...> >&
get(etl::variant<VTypes...>& v);
408 template <
size_t Index,
typename... VTypes>
409 friend ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...> >&&
get(etl::variant<VTypes...>&& v);
411 template <
size_t Index,
typename... VTypes>
412 friend ETL_CONSTEXPR14
const etl::variant_alternative_t< Index,
const etl::variant<VTypes...> >&
get(
const etl::variant<VTypes...>& v);
414 template <
size_t Index,
typename... VTypes>
415 friend ETL_CONSTEXPR14
const etl::variant_alternative_t< Index,
const etl::variant<VTypes...> >&&
get(
const etl::variant<VTypes...>&& v);
417 template <
typename T,
typename... VTypes>
418 friend ETL_CONSTEXPR14 T&
get(etl::variant<VTypes...>& v);
420 template <
typename T,
typename... VTypes>
421 friend ETL_CONSTEXPR14 T&&
get(etl::variant<VTypes...>&& v);
423 template <
typename T,
typename... VTypes>
424 friend ETL_CONSTEXPR14
const T&
get(
const etl::variant<VTypes...>& v);
426 template <
typename T,
typename... VTypes>
427 friend ETL_CONSTEXPR14
const T&&
get(
const etl::variant<VTypes...>&& v);
429 template <
class T,
typename... VTypes >
430 friend ETL_CONSTEXPR14 etl::add_pointer_t<T> get_if(etl::variant<VTypes...>* pv) ETL_NOEXCEPT;
432 template <
class T,
typename... VTypes >
433 friend ETL_CONSTEXPR14 etl::add_pointer_t<const T> get_if(
const etl::variant<VTypes...>* pv) ETL_NOEXCEPT;
438 template <
typename... UTypes>
439 friend class variant;
444 using largest_t =
typename largest_type<TTypes...>::type;
449 static const size_t Size =
sizeof(largest_t);
454 static const size_t Alignment = etl::largest_alignment<TTypes...>::value;
459 template <
typename T,
bool IsCopyable,
bool IsMoveable>
460 using operation_type = private_variant::operation_type<T, IsCopyable, IsMoveable>;
465 static constexpr int Copy = private_variant::Copy;
466 static constexpr int Move = private_variant::Move;
467 static constexpr int Destroy = private_variant::Destroy;
472 template <
typename T>
473 using index_of_type = etl::type_list_index_of_type<etl::type_list<TTypes...>, etl::remove_cvref_t<T> >;
478 template <
size_t Index>
479 using type_from_index =
typename etl::type_list_type_at_index<etl::type_list<TTypes...>, Index>::type;
489 ETL_CONSTEXPR14 variant()
491 using type = type_from_index<0U>;
493 default_construct_in_place<type>(data);
494 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
503 template <
typename T, etl::enable_if_t< !etl::is_same<etl::remove_cvref_t<T>, variant>::value,
int> = 0>
504 ETL_CONSTEXPR14 variant(T&& value)
505 : operation(operation_type< etl::remove_cvref_t<T>, etl::is_copy_constructible<etl::remove_cvref_t<T> >::value,
506 etl::is_move_constructible<etl::remove_cvref_t<T> >::value>::do_operation)
507 , type_id(index_of_type<T>::value)
509 static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value,
"Unsupported type");
511 construct_in_place<etl::remove_cvref_t<T> >(data, etl::forward<T>(value));
519 template <
typename T,
typename... TArgs>
520 ETL_CONSTEXPR14
explicit variant(etl::in_place_type_t<T>, TArgs&&... args)
521 : operation(operation_type< etl::remove_cvref_t<T>, etl::is_copy_constructible<etl::remove_cvref_t<T> >::value,
522 etl::is_move_constructible<etl::remove_cvref_t<T> >::value>::do_operation)
523 , type_id(index_of_type<T>::value)
525 static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value,
"Unsupported type");
527 construct_in_place_args<etl::remove_cvref_t<T> >(data, etl::forward<TArgs>(args)...);
535 template <
size_t Index,
typename... TArgs>
536 ETL_CONSTEXPR14
explicit variant(etl::in_place_index_t<Index>, TArgs&&... args)
539 using type = type_from_index<Index>;
540 static_assert(etl::is_one_of<type, TTypes...>::value,
"Unsupported type");
542 construct_in_place_args<type>(data, etl::forward<TArgs>(args)...);
544 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
548 #if ETL_HAS_INITIALIZER_LIST
553 template <
typename T,
typename U,
typename... TArgs >
554 ETL_CONSTEXPR14
explicit variant(etl::in_place_type_t<T>, std::initializer_list<U> init, TArgs&&... args)
555 : operation(operation_type< etl::remove_cvref_t<T>, etl::is_copy_constructible<etl::remove_cvref_t<T> >::value,
556 etl::is_move_constructible<etl::remove_cvref_t<T> >::value>::do_operation)
557 , type_id(index_of_type<T>::value)
559 static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value,
"Unsupported type");
561 construct_in_place_args<etl::remove_cvref_t<T> >(data, init, etl::forward<TArgs>(args)...);
569 template <
size_t Index,
typename U,
typename... TArgs >
570 ETL_CONSTEXPR14
explicit variant(etl::in_place_index_t<Index>, std::initializer_list<U> init, TArgs&&... args)
573 using type = type_from_index<Index>;
574 static_assert(etl::is_one_of<type, TTypes...>::value,
"Unsupported type");
576 construct_in_place_args<type>(data, init, etl::forward<TArgs>(args)...);
578 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
588 ETL_CONSTEXPR14 variant(
const variant& other)
589 : operation(other.operation)
590 , type_id(other.type_id)
592 if (other.valueless_by_exception())
594 type_id = variant_npos;
598 operation(private_variant::Copy, data, other.data);
608 ETL_CONSTEXPR14 variant(variant&& other)
609 : operation(other.operation)
610 , type_id(other.type_id)
612 if (other.valueless_by_exception())
614 type_id = variant_npos;
618 operation(private_variant::Move, data, other.data);
628 if (!valueless_by_exception())
630 operation(private_variant::Destroy, data,
nullptr);
633 operation = operation_type<void, false, false>::do_operation;
634 type_id = variant_npos;
640 template <
typename T,
typename... TArgs>
643 static_assert(etl::is_one_of<T, TTypes...>::value,
"Unsupported type");
645 using type = etl::remove_cvref_t<T>;
647 if (!valueless_by_exception())
649 operation(private_variant::Destroy, data,
nullptr);
652 construct_in_place_args<type>(data, etl::forward<TArgs>(args)...);
654 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
656 type_id = index_of_type<T>::value;
658 return *
static_cast<T*
>(data);
661 #if ETL_HAS_INITIALIZER_LIST
665 template <
typename T,
typename U,
typename... TArgs>
666 T&
emplace(std::initializer_list<U> il, TArgs&&... args)
668 static_assert(etl::is_one_of<T, TTypes...>::value,
"Unsupported type");
670 using type = etl::remove_cvref_t<T>;
672 if (!valueless_by_exception())
674 operation(private_variant::Destroy, data,
nullptr);
677 construct_in_place_args<type>(data, il, etl::forward<TArgs>(args)...);
679 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
681 type_id = index_of_type<T>::value;
683 return *
static_cast<T*
>(data);
690 template <
size_t Index,
typename... TArgs>
691 typename etl::variant_alternative_t<Index, variant<TTypes...> >&
emplace(TArgs&&... args)
693 static_assert(Index <
sizeof...(TTypes),
"Index out of range");
695 using type = type_from_index<Index>;
697 if (!valueless_by_exception())
699 operation(private_variant::Destroy, data,
nullptr);
702 construct_in_place_args<type>(data, etl::forward<TArgs>(args)...);
704 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
708 return *
static_cast<type*
>(data);
711 #if ETL_HAS_INITIALIZER_LIST
715 template <
size_t Index,
typename U,
typename... TArgs>
716 typename etl::variant_alternative_t<Index, variant<TTypes...> >&
emplace(std::initializer_list<U> il, TArgs&&... args)
718 static_assert(Index <
sizeof...(TTypes),
"Index out of range");
720 using type = type_from_index<Index>;
722 if (!valueless_by_exception())
724 operation(private_variant::Destroy, data,
nullptr);
727 construct_in_place_args<type>(data, il, etl::forward<TArgs>(args)...);
729 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
733 return *
static_cast<type*
>(data);
741 template <
typename T, etl::enable_if_t< !etl::is_same<etl::remove_cvref_t<T>, variant>::value,
int> = 0>
744 using type = etl::remove_cvref_t<T>;
746 static_assert(etl::is_one_of<type, TTypes...>::value,
"Unsupported type");
748 if (!valueless_by_exception())
750 operation(private_variant::Destroy, data,
nullptr);
753 construct_in_place<type>(data, etl::forward<T>(value));
755 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
756 type_id = index_of_type<type>::value;
769 if (!valueless_by_exception())
771 operation(Destroy, data,
nullptr);
774 if (other.valueless_by_exception())
776 type_id = variant_npos;
780 operation = other.operation;
781 operation(Copy, data, other.data);
783 type_id = other.type_id;
798 if (!valueless_by_exception())
800 operation(Destroy, data,
nullptr);
803 if (other.valueless_by_exception())
805 type_id = variant_npos;
809 operation = other.operation;
810 operation(Move, data, other.data);
812 type_id = other.type_id;
823 constexpr bool valueless_by_exception() const ETL_NOEXCEPT
825 return type_id == variant_npos;
831 constexpr size_t index() const ETL_NOEXCEPT
841 template <
typename T>
844 return etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value;
852 template <typename T, etl::enable_if_t<is_supported_type<T>(),
int> = 0>
853 constexpr bool is_type() const ETL_NOEXCEPT
855 return (type_id == index_of_type<T>::value);
859 template <typename T, etl::enable_if_t<!is_supported_type<T>(),
int> = 0>
860 constexpr bool is_type() const ETL_NOEXCEPT
873 return type_id == other.type_id;
879 void swap(variant& rhs) ETL_NOEXCEPT
881 variant temp(etl::move(*
this));
882 *
this = etl::move(rhs);
883 rhs = etl::move(temp);
889 template <
typename TVisitor>
890 etl::enable_if_t<etl::is_visitor<TVisitor>::value,
void> accept(TVisitor& v)
892 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
893 do_visitor(v, etl::make_index_sequence<
sizeof...(TTypes)>{});
895 do_visitor<
sizeof...(TTypes)>(v);
902 template <
typename TVisitor>
903 etl::enable_if_t<etl::is_visitor<TVisitor>::value,
void> accept(TVisitor& v)
const
905 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
906 do_visitor(v, etl::make_index_sequence<
sizeof...(TTypes)>{});
908 do_visitor<
sizeof...(TTypes)>(v);
915 template <
typename TVisitor>
916 etl::enable_if_t<!etl::is_visitor<TVisitor>::value,
void> accept(TVisitor& v)
918 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
919 do_operator(v, etl::make_index_sequence<
sizeof...(TTypes)>{});
921 do_operator<
sizeof...(TTypes)>(v);
928 template <
typename TVisitor>
929 etl::enable_if_t<!etl::is_visitor<TVisitor>::value,
void> accept(TVisitor& v)
const
931 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
932 do_operator(v, etl::make_index_sequence<
sizeof...(TTypes)>{});
934 do_operator<
sizeof...(TTypes)>(v);
942 template <
typename TVisitor>
943 #if !defined(ETL_IN_UNIT_TEST)
947 accept_visitor(TVisitor& v)
949 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
950 do_visitor(v, etl::make_index_sequence<
sizeof...(TTypes)>{});
952 do_visitor<
sizeof...(TTypes)>(v);
960 template <
typename TVisitor>
961 #if !defined(ETL_IN_UNIT_TEST)
965 accept_visitor(TVisitor& v)
const
967 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
968 do_visitor(v, etl::make_index_sequence<
sizeof...(TTypes)>{});
970 do_visitor<
sizeof...(TTypes)>(v);
978 template <
typename TVisitor>
979 #if !defined(ETL_IN_UNIT_TEST)
983 accept_functor(TVisitor& v)
985 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
986 do_operator(v, etl::make_index_sequence<
sizeof...(TTypes)>{});
988 do_operator<
sizeof...(TTypes)>(v);
996 template <
typename TVisitor>
997 #if !defined(ETL_IN_UNIT_TEST)
1001 accept_functor(TVisitor& v)
const
1003 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1004 do_operator(v, etl::make_index_sequence<
sizeof...(TTypes)>{});
1006 do_operator<
sizeof...(TTypes)>(v);
1013 using operation_function = void (*)(int,
char*,
const char*);
1018 template <
typename T>
1019 static void construct_in_place(
char* pstorage,
const T& value)
1021 using type = etl::remove_cvref_t<T>;
1023 ::new (pstorage) type(value);
1029 template <
typename T>
1030 static void construct_in_place(
char* pstorage, T&& value)
1032 using type = etl::remove_cvref_t<T>;
1034 ::new (pstorage) type(etl::move(value));
1040 template <
typename T,
typename... TArgs>
1041 static void construct_in_place_args(
char* pstorage, TArgs&&... args)
1043 using type = etl::remove_cvref_t<T>;
1045 ::new (pstorage) type(etl::forward<TArgs>(args)...);
1051 template <
typename T>
1052 static void default_construct_in_place(
char* pstorage)
1054 using type = etl::remove_cvref_t<T>;
1056 ::new (pstorage) type();
1059 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1063 template <
typename TVisitor,
size_t... I>
1064 void do_visitor(TVisitor& visitor, etl::index_sequence<I...>)
1066 (attempt_visitor<I>(visitor) || ...);
1072 template <
typename TVisitor,
size_t... I>
1073 void do_visitor(TVisitor& visitor, etl::index_sequence<I...>)
const
1075 (attempt_visitor<I>(visitor) || ...);
1081 template <
size_t NTypes,
typename TVisitor>
1082 void do_visitor(TVisitor& visitor)
1084 etl::private_variant::select_do_visitor<NTypes>::do_visitor(*
this, visitor);
1090 template <
size_t NTypes,
typename TVisitor>
1091 void do_visitor(TVisitor& visitor)
const
1093 etl::private_variant::select_do_visitor<NTypes>::do_visitor(*
this, visitor);
1100 template <
size_t Index,
typename TVisitor>
1101 bool attempt_visitor(TVisitor& visitor)
1103 if (Index ==
index())
1121 template <
size_t Index,
typename TVisitor>
1122 bool attempt_visitor(TVisitor& visitor)
const
1124 if (Index ==
index())
1139 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1143 template <
typename TVisitor,
size_t... I>
1144 void do_operator(TVisitor& visitor, etl::index_sequence<I...>)
1146 (attempt_operator<I>(visitor) || ...);
1152 template <
typename TVisitor,
size_t... I>
1153 void do_operator(TVisitor& visitor, etl::index_sequence<I...>)
const
1155 (attempt_operator<I>(visitor) || ...);
1161 template <
size_t NTypes,
typename TVisitor>
1162 void do_operator(TVisitor& visitor)
1164 #if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1165 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 8U,
"ETL_VARIANT_CPP11_MAX_8_TYPES - Only a maximum of 8 types are allowed in this variant");
1168 #if defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1169 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 16U,
"ETL_VARIANT_CPP11_MAX_16_TYPES - Only a maximum of 16 types are allowed in this variant");
1172 #if defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1173 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 24U,
"ETL_VARIANT_CPP11_MAX_24_TYPES - Only a maximum of 24 types are allowed in this variant");
1176 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 32U,
"A maximum of 32 types are allowed in this variant");
1178 etl::private_variant::select_do_operator<NTypes>::do_operator(*
this, visitor);
1184 template <
size_t NTypes,
typename TVisitor>
1185 void do_operator(TVisitor& visitor)
const
1187 #if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1188 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 8U,
"ETL_VARIANT_CPP11_MAX_8_TYPES - Only a maximum of 8 types are allowed in this variant");
1191 #if defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1192 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 16U,
"ETL_VARIANT_CPP11_MAX_16_TYPES - Only a maximum of 16 types are allowed in this variant");
1195 #if defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1196 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 24U,
"ETL_VARIANT_CPP11_MAX_24_TYPES - Only a maximum of 24 types are allowed in this variant");
1199 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 32U,
"A maximum of 32 types are allowed in this variant");
1201 etl::private_variant::select_do_operator<NTypes>::do_operator(*
this, visitor);
1208 template <
size_t Index,
typename TVisitor>
1209 bool attempt_operator(TVisitor& visitor)
1211 if (Index ==
index())
1226 template <
size_t Index,
typename TVisitor>
1227 bool attempt_operator(TVisitor& visitor)
const
1229 if (Index ==
index())
1245 etl::uninitialized_buffer<Size, 1U, Alignment> data;
1250 operation_function operation;
1258 namespace private_variant
1264 template <
typename T,
typename T0,
typename T1,
typename... Ts>
1265 typename etl::enable_if_t<etl::is_same<T, T0>::value,
bool> ETL_CONSTEXPR14 is_same_type_in(
size_t index) ETL_NOEXCEPT;
1267 template <
typename T,
typename T0>
1268 typename etl::enable_if_t<etl::is_same<T, T0>::value,
bool> ETL_CONSTEXPR14 is_same_type_in(
size_t index) ETL_NOEXCEPT;
1270 template <
typename T,
typename T0,
typename T1,
typename... Ts>
1271 typename etl::enable_if_t<!etl::is_same<T, T0>::value,
bool> ETL_CONSTEXPR14 is_same_type_in(
size_t index) ETL_NOEXCEPT;
1273 template <
typename T,
typename T0>
1274 typename etl::enable_if_t<!etl::is_same<T, T0>::value,
bool> ETL_CONSTEXPR14 is_same_type_in(
size_t index) ETL_NOEXCEPT;
1276 template <
typename T,
typename T0,
typename T1,
typename... Ts>
1277 typename etl::enable_if_t<etl::is_same<T, T0>::value,
bool> ETL_CONSTEXPR14 is_same_type_in(
size_t index) ETL_NOEXCEPT
1285 return is_same_type_in<T, T1, Ts...>(index - 1);
1289 template <
typename T,
typename T0>
1290 typename etl::enable_if_t<etl::is_same<T, T0>::value,
bool> ETL_CONSTEXPR14 is_same_type_in(
size_t index) ETL_NOEXCEPT
1295 template <
typename T,
typename T0,
typename T1,
typename... Ts>
1296 typename etl::enable_if_t<!etl::is_same<T, T0>::value,
bool> ETL_CONSTEXPR14 is_same_type_in(
size_t index) ETL_NOEXCEPT
1304 return is_same_type_in<T, T1, Ts...>(index - 1);
1308 template <
typename T,
typename T0>
1309 typename etl::enable_if_t<!etl::is_same<T, T0>::value,
bool> ETL_CONSTEXPR14 is_same_type_in(
size_t) ETL_NOEXCEPT
1318 template <
typename T,
typename... TTypes>
1319 ETL_CONSTEXPR14
bool holds_alternative(
const etl::variant<TTypes...>& v) ETL_NOEXCEPT
1321 return private_variant::is_same_type_in<T, TTypes...>(v.index());
1327 template <
size_t Index,
typename... TTypes>
1328 ETL_CONSTEXPR14
bool holds_alternative(
const etl::variant<TTypes...>& v) ETL_NOEXCEPT
1330 return (Index == v.index());
1336 template <
typename... TTypes>
1337 ETL_CONSTEXPR14
bool holds_alternative(
size_t index,
const etl::variant<TTypes...>& v) ETL_NOEXCEPT
1339 return (index == v.index());
1345 template <
size_t Index,
typename... TTypes>
1346 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<TTypes...> >&
get(etl::variant<TTypes...>& v)
1348 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1349 static_assert(Index <
sizeof...(TTypes),
"Index out of range");
1352 ETL_ASSERT(Index == v.
index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1354 using type = etl::variant_alternative_t<Index, etl::variant<TTypes...> >;
1356 return *
static_cast<type*
>(v.data);
1360 template <
size_t Index,
typename... TTypes>
1361 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<TTypes...> >&&
get(etl::variant<TTypes...>&& v)
1363 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1364 static_assert(Index <
sizeof...(TTypes),
"Index out of range");
1367 ETL_ASSERT(Index == v.
index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1369 using type = etl::variant_alternative_t<Index, etl::variant<TTypes...> >;
1371 return etl::move(*
static_cast<type*
>(v.data));
1375 template <
size_t Index,
typename... TTypes>
1376 ETL_CONSTEXPR14
const etl::variant_alternative_t<Index,
const etl::variant<TTypes...> >&
get(
const etl::variant<TTypes...>& v)
1378 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1379 static_assert(Index <
sizeof...(TTypes),
"Index out of range");
1382 ETL_ASSERT(Index == v.
index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1384 using type = etl::variant_alternative_t<Index, etl::variant<TTypes...> >;
1386 return *
static_cast<const type*
>(v.data);
1390 template <
size_t Index,
typename... TTypes>
1391 ETL_CONSTEXPR14
const etl::variant_alternative_t<Index,
const etl::variant<TTypes...> >&&
get(
const etl::variant<TTypes...>&& v)
1393 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1394 static_assert(Index <
sizeof...(TTypes),
"Index out of range");
1397 ETL_ASSERT(Index == v.
index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1399 using type = etl::variant_alternative_t<Index, etl::variant<TTypes...> >;
1401 return etl::move(*
static_cast<const type*
>(v.data));
1405 template <
typename T,
typename... TTypes>
1406 ETL_CONSTEXPR14 T&
get(etl::variant<TTypes...>& v)
1408 ETL_ASSERT((private_variant::is_same_type_in<T, TTypes...>(v.
index())), ETL_ERROR(etl::variant_incorrect_type_exception));
1410 return *
static_cast<T*
>(v.data);
1414 template <
typename T,
typename... TTypes>
1415 ETL_CONSTEXPR14 T&&
get(etl::variant<TTypes...>&& v)
1417 ETL_ASSERT((private_variant::is_same_type_in<T, TTypes...>(v.
index())), ETL_ERROR(etl::variant_incorrect_type_exception));
1419 return etl::move(*
static_cast<T*
>(v.data));
1423 template <
typename T,
typename... TTypes>
1424 ETL_CONSTEXPR14
const T&
get(
const etl::variant<TTypes...>& v)
1426 ETL_ASSERT((private_variant::is_same_type_in<T, TTypes...>(v.
index())), ETL_ERROR(etl::variant_incorrect_type_exception));
1428 return *
static_cast<const T*
>(v.data);
1432 template <
typename T,
typename... TTypes>
1433 ETL_CONSTEXPR14
const T&&
get(
const etl::variant<TTypes...>&& v)
1435 ETL_ASSERT((private_variant::is_same_type_in<T, TTypes...>(v.
index())), ETL_ERROR(etl::variant_incorrect_type_exception));
1437 return etl::move(*
static_cast<const T*
>(v.data));
1443 template <
size_t Index,
typename... TTypes >
1444 ETL_CONSTEXPR14 etl::add_pointer_t< etl::variant_alternative_t<Index, etl::variant<TTypes...> > > get_if(etl::variant<TTypes...>* pv) ETL_NOEXCEPT
1446 if ((pv !=
nullptr) && (pv->index() == Index))
1457 template <
size_t Index,
typename... TTypes >
1458 ETL_CONSTEXPR14 etl::add_pointer_t<
const etl::variant_alternative_t<Index, etl::variant<TTypes...> > > get_if(
const etl::variant<TTypes...>* pv)
1461 if ((pv !=
nullptr) && (pv->index() == Index))
1472 template <
class T,
typename... TTypes >
1473 ETL_CONSTEXPR14 etl::add_pointer_t<T> get_if(etl::variant<TTypes...>* pv) ETL_NOEXCEPT
1475 if ((pv !=
nullptr) && (private_variant::is_same_type_in<T, TTypes...>(pv->index())))
1477 return static_cast<T*
>(pv->data);
1486 template <
typename T,
typename... TTypes >
1487 ETL_CONSTEXPR14 etl::add_pointer_t<const T> get_if(
const etl::variant<TTypes...>* pv) ETL_NOEXCEPT
1489 if ((pv !=
nullptr) && (private_variant::is_same_type_in<T, TTypes...>(pv->index())))
1491 return static_cast<const T*
>(pv->data);
1502 template <
typename... TTypes>
1503 void swap(etl::variant<TTypes...>& lhs, etl::variant<TTypes...>& rhs)
1511 template <
typename T>
1512 struct variant_size;
1514 template <
typename... TTypes>
1515 struct variant_size<etl::
variant<TTypes...> > : etl::integral_constant<size_t, sizeof...(TTypes)>
1519 template <
typename T>
1520 struct variant_size<const T> : etl::integral_constant<size_t, variant_size<T>::value>
1525 template <
typename... TTypes>
1526 inline constexpr size_t variant_size_v = variant_size<TTypes...>::value;
1532 namespace private_variant
1534 template <
typename TRet,
typename TCallable,
typename TVariant,
size_t tIndex,
typename TNext,
typename... TVariants>
1535 static ETL_CONSTEXPR14 TRet do_visit_single(TCallable&& f, TVariant&& v, TNext&&, TVariants&&... vs);
1542 struct visit_auto_return
1550 template <
typename TCallable,
typename... Ts>
1551 struct single_visit_result_type
1553 using type =
decltype(declval<TCallable>()(declval<Ts>()...));
1556 template <
typename TCallable,
typename... Ts>
1557 using single_visit_result_type_t =
typename single_visit_result_type<TCallable, Ts...>::type;
1563 template <
typename TVar,
typename T>
1564 using rlref_copy = conditional_t<is_reference<TVar>::value, T&, T&&>;
1575 template <
template <
typename...>
class,
typename...>
1576 struct visit_result_helper;
1578 template <
template <
typename...>
class TToInject,
size_t... tAltIndices,
typename TCur>
1579 struct visit_result_helper<TToInject, index_sequence<tAltIndices...>, TCur>
1581 template <
size_t tIndex>
1582 using var_type = rlref_copy<TCur, variant_alternative_t<tIndex, remove_reference_t<TCur> > >;
1584 using type = common_type_t<TToInject<var_type<tAltIndices> >...>;
1587 template <
template <
typename...>
class TToInject,
size_t... tAltIndices,
typename TCur,
typename TNext,
typename... TVs>
1588 struct visit_result_helper<TToInject, index_sequence<tAltIndices...>, TCur, TNext, TVs...>
1590 template <
size_t tIndex>
1591 using var_type = rlref_copy<TCur, variant_alternative_t<tIndex, remove_reference_t<TCur> > >;
1593 template <
size_t tIndex>
1594 struct next_inject_wrap
1596 template <
typename... TNextInj>
1597 using next_inject = TToInject<var_type<tIndex>, TNextInj...>;
1598 using recursive_result =
1599 typename visit_result_helper< next_inject, make_index_sequence<variant_size<remove_reference_t<TNext> >::value>, TNext, TVs...>::type;
1602 using type = common_type_t< typename next_inject_wrap<tAltIndices>::recursive_result...>;
1611 template <
typename TRet,
typename...>
1617 template <
typename TCallable,
typename T1,
typename... Ts>
1618 struct visit_result<visit_auto_return, TCallable, T1, Ts...>
1621 template <
typename... Ts2>
1622 using single_res = single_visit_result_type_t<TCallable, Ts2...>;
1623 using type =
typename visit_result_helper< single_res, make_index_sequence<variant_size<remove_reference_t<T1> >::value>, T1, Ts...>::type;
1626 template <
typename... Ts>
1627 using visit_result_t =
typename visit_result<Ts...>::type;
1633 template <
typename TRet,
typename TCallable,
typename TVariant,
size_t tIndex>
1634 constexpr TRet do_visit_single(TCallable&& f, TVariant&& v)
1636 return static_cast<TCallable&&
>(f)(
etl::get<tIndex>(
static_cast<TVariant&&
>(v)));
1644 template <
typename TRet,
typename TCallable,
typename TCurVariant,
typename... TVarRest>
1645 struct do_visit_helper
1647 using function_pointer = add_pointer_t<TRet(TCallable&&, TCurVariant&&, TVarRest&&...)>;
1649 template <
size_t tIndex>
1650 static constexpr function_pointer fptr() ETL_NOEXCEPT
1652 return &do_visit_single<TRet, TCallable, TCurVariant, tIndex, TVarRest...>;
1659 template <
typename TRet,
typename TCallable,
typename TVariant,
size_t... tIndices,
typename... TVarRest>
1660 static ETL_CONSTEXPR14 TRet do_visit(TCallable&& f, TVariant&& v, index_sequence<tIndices...>, TVarRest&&... variants)
1662 ETL_ASSERT(!v.valueless_by_exception(), ETL_ERROR(bad_variant_access));
1664 using helper_t = do_visit_helper<TRet, TCallable, TVariant, TVarRest...>;
1665 using func_ptr =
typename helper_t::function_pointer;
1667 constexpr func_ptr jmp_table[]{helper_t::template fptr<tIndices>()...};
1669 return jmp_table[v.
index()](
static_cast<TCallable&&
>(f),
static_cast<TVariant&&
>(v),
static_cast<TVarRest&&
>(variants)...);
1672 template <
typename TRet,
typename TCallable,
typename TVariant,
typename... TVs>
1673 static ETL_CONSTEXPR14 TRet visit(TCallable&& f, TVariant&& v, TVs&&... vs)
1675 constexpr size_t variants = etl::variant_size<typename remove_reference<TVariant>::type>::value;
1676 return private_variant::do_visit<TRet>(
static_cast<TCallable&&
>(f),
static_cast<TVariant&&
>(v), make_index_sequence<variants>{},
1677 static_cast<TVs&&
>(vs)...);
1684 template <
typename TRet,
typename TCallable,
typename TVariant,
size_t tIndex>
1685 class constexpr_visit_closure
1687 add_pointer_t<TCallable> callable_;
1688 add_pointer_t<TVariant> variant_;
1692 constexpr constexpr_visit_closure(TCallable&& c, TVariant&& v)
1698 template <
typename... Ts>
1699 ETL_CONSTEXPR14 TRet operator()(Ts&&... args)
const
1701 return static_cast<TCallable&&
>(*callable_)(get<tIndex>(
static_cast<TVariant&&
>(*variant_)),
static_cast<Ts&&
>(args)...);
1705 template <
typename TRet,
typename TCallable,
typename TVariant,
size_t tIndex,
typename TNext,
typename... TVariants>
1706 static ETL_CONSTEXPR14 TRet do_visit_single(TCallable&& f, TVariant&& v, TNext&& next, TVariants&&... vs)
1708 return private_variant::visit<TRet>(
1709 constexpr_visit_closure<TRet, TCallable, TVariant, tIndex>(
static_cast<TCallable&&
>(f),
static_cast<TVariant&&
>(v)),
1710 static_cast<TNext&&
>(next),
static_cast<TVariants&&
>(vs)...);
1719 template <
typename TRet = private_variant::visit_auto_return,
typename... TVariants,
typename TCallable,
1720 typename TDeducedReturn = private_variant::visit_result_t<TRet, TCallable, TVariants...> >
1721 static ETL_CONSTEXPR14 TDeducedReturn visit(TCallable&& f, TVariants&&... vs)
1723 return private_variant::visit<TDeducedReturn>(
static_cast<TCallable&&
>(f),
static_cast<TVariants&&
>(vs)...);
1726 namespace private_variant
1733 template <
typename TVariant>
1734 struct equality_visitor
1736 equality_visitor(
const TVariant& rhs_)
1741 template <
typename TValue>
1742 bool operator()(
const TValue& lhs_downcasted)
1747 const TVariant& rhs;
1755 template <
typename TVariant>
1756 struct less_than_visitor
1758 less_than_visitor(
const TVariant& rhs_)
1763 template <
typename TValue>
1764 bool operator()(
const TValue& lhs_downcasted)
1766 return lhs_downcasted < etl::get<TValue>(rhs);
1769 const TVariant& rhs;
1777 template <
typename... TTypes>
1778 ETL_CONSTEXPR14
bool operator==(
const etl::variant<TTypes...>& lhs,
const etl::variant<TTypes...>& rhs)
1781 if (lhs.valueless_by_exception() && rhs.valueless_by_exception())
1787 if (lhs.valueless_by_exception() || rhs.valueless_by_exception())
1800 private_variant::equality_visitor<etl::variant<TTypes...> >
visitor(rhs);
1802 return etl::visit(
visitor, lhs);
1809 template <
typename... TTypes>
1810 ETL_CONSTEXPR14
bool operator!=(
const etl::variant<TTypes...>& lhs,
const etl::variant<TTypes...>& rhs)
1812 return !(lhs == rhs);
1819 template <
typename... TTypes>
1820 ETL_CONSTEXPR14
bool operator<(
const etl::variant<TTypes...>& lhs,
const etl::variant<TTypes...>& rhs)
1824 if (lhs.valueless_by_exception() && rhs.valueless_by_exception())
1830 if (lhs.valueless_by_exception())
1836 if (rhs.valueless_by_exception())
1849 private_variant::less_than_visitor<etl::variant<TTypes...> >
visitor(rhs);
1851 return etl::visit(
visitor, lhs);
1858 template <
typename... TTypes>
1859 ETL_CONSTEXPR14
bool operator>(
const etl::variant<TTypes...>& lhs,
const etl::variant<TTypes...>& rhs)
1868 template <
typename... TTypes>
1869 ETL_CONSTEXPR14
bool operator<=(
const etl::variant<TTypes...>& lhs,
const etl::variant<TTypes...>& rhs)
1871 return !(lhs > rhs);
1878 template <
typename... TTypes>
1879 ETL_CONSTEXPR14
bool operator>=(
const etl::variant<TTypes...>& lhs,
const etl::variant<TTypes...>& rhs)
1881 return !(lhs < rhs);
1884 namespace private_variant
1886 #if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
1892 template <
typename TVariant>
1893 struct compare_visitor
1895 compare_visitor(
const TVariant& rhs_)
1900 template <
typename TValue>
1901 std::strong_ordering operator()(
const TValue& lhs_downcasted)
1906 const TVariant& rhs;
1916 #if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
1917 template <
typename... TTypes>
1918 ETL_CONSTEXPR14 std::common_comparison_category_t< std::compare_three_way_result_t<TTypes>...> operator<=>(
const etl::variant<TTypes...>& lhs,
1919 const etl::variant<TTypes...>& rhs)
1921 if (lhs.valueless_by_exception() && rhs.valueless_by_exception())
1923 return std::strong_ordering::equal;
1925 else if (lhs.valueless_by_exception())
1927 return std::strong_ordering::less;
1929 else if (rhs.valueless_by_exception())
1931 return std::strong_ordering::greater;
1941 private_variant::compare_visitor<etl::variant<TTypes...> >
visitor(rhs);
1943 return etl::visit(
visitor, lhs);
1950 template <
typename TList>
1951 struct variant_from_type_list;
1953 template <
typename... TTypes>
1954 struct variant_from_type_list<etl::type_list<TTypes...> >
1956 using type = etl::variant<TTypes...>;
1959 template <
typename TTypeList>
1960 using variant_from_type_list_t =
typename variant_from_type_list<TTypeList>::type;
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
Definition exception.h:59
static bool is_supported_type()
Definition variant_legacy.h:889
~variant()
Destructor.
Definition variant_legacy.h:224
bool is_same_type(const variant &other) const
Definition variant_legacy.h:642
T & get()
Definition variant_legacy.h:738
variant & operator=(const T &value)
Definition variant_legacy.h:597
bool is_type() const
Definition variant_legacy.h:710
T & emplace()
Emplace with one constructor parameter.
Definition variant_legacy.h:520
size_t index() const
Gets the index of the type currently stored or UNSUPPORTED_TYPE_ID.
Definition variant_legacy.h:718
Definition variant_legacy.h:115
Definition variant_legacy.h:146
Definition variant_legacy.h:87
Definition variant_legacy.h:101
etl::monostate monostate
Definition variant_legacy.h:80
bitset_ext
Definition absolute.h:40
ETL_CONSTEXPR14 void swap(etl::typed_storage_ext< T > &lhs, etl::typed_storage_ext< T > &rhs) ETL_NOEXCEPT
Swap two etl::typed_storage_ext.
Definition alignment.h:856
ETL_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1081
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1133
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1147
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1093
T & get(array< T, Size > &a)
Definition array.h:1161
ETL_DEPRECATED_REASON("Misspelt class name") typedef scheduler_policy_sequential_single scheduler_policy_sequencial_single
Typedef for backwards compatibility with miss-spelt struct name.
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1106
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1120
A 'no-value' placeholder.
Definition monostate.h:42
Definition variant_legacy.h:989