31#include "../platform.h"
32#include "../utility.h"
33#include "../largest.h"
34#include "../exception.h"
35#include "../type_traits.h"
36#include "../integral_limits.h"
37#include "../static_assert.h"
38#include "../alignment.h"
39#include "../error_handler.h"
40#include "../parameter_pack.h"
41#include "../placement_new.h"
42#include "../visitor.h"
44#include "../compare.h"
45#include "../initializer_list.h"
49#if defined(ETL_COMPILER_KEIL)
50 #pragma diag_suppress 940
51 #pragma diag_suppress 111
54#if ETL_CPP11_NOT_SUPPORTED
55 #if !defined(ETL_IN_UNIT_TEST)
56 #error NOT SUPPORTED FOR C++03 OR BELOW
67 namespace private_variant
73 template <
typename... TTypes>
78 static constexpr size_t size =
sizeof...(TTypes);
91 template <
typename Type,
typename T1,
typename... TRest>
92 struct index_of_type_helper
98 template <
typename Type,
typename T1>
99 struct index_of_type_helper<Type, T1>
101 static constexpr size_t value = 1UL;
106 static_assert(
etl::is_one_of<type, TTypes...>::value,
"T is not in parameter pack");
109 static constexpr size_t value = index_of_type_helper<type, TTypes...>::value - 1;
116 class type_from_index
121 template <
size_t II,
size_t N,
typename T1,
typename... TRest>
122 struct type_from_index_helper
124 using type =
typename etl::conditional<II == N, T1,
typename type_from_index_helper<II, N + 1, TRest...>::type>::type;
128 template <
size_t II,
size_t N,
typename T1>
129 struct type_from_index_helper<II, N, T1>
137 using type =
typename type_from_index_helper<I, 0, TTypes...>::type;
142 using type_from_index_t =
typename type_from_index<I>::type;
148 static constexpr bool Copyable =
true;
149 static constexpr bool Non_Copyable =
false;
150 static constexpr bool Moveable =
true;
151 static constexpr bool Non_Moveable =
false;
156 static constexpr int Copy = 0;
157 static constexpr int Move = 1;
158 static constexpr int Destroy = 2;
163 template <
typename T,
bool IsCopyable,
bool IsMoveable>
164 struct operation_type;
169 struct operation_type<void, Non_Copyable, Non_Moveable>
171 static void do_operation(
int ,
char* ,
const char* )
174#if defined(ETL_IN_UNIT_TEST)
182 template <
typename T>
183 struct operation_type<T, Non_Copyable, Non_Moveable>
185 static void do_operation(
int operation,
char* pstorage,
const char* )
191 reinterpret_cast<const T*
>(pstorage)->~T();
198 #if defined(ETL_IN_UNIT_TEST)
209 template <
typename T>
210 struct operation_type<T, Non_Copyable, Moveable>
212 static void do_operation(
int operation,
char* pstorage,
const char* pvalue)
218 ::new (pstorage) T(etl::move(*
reinterpret_cast<T*
>(
const_cast<char*
>(pvalue))));
224 reinterpret_cast<const T*
>(pstorage)->~T();
231 #if defined(ETL_IN_UNIT_TEST)
242 template <
typename T>
243 struct operation_type<T, Copyable, Non_Moveable>
245 static void do_operation(
int operation,
char* pstorage,
const char* pvalue)
251 ::new (pstorage) T(*
reinterpret_cast<const T*
>(pvalue));
257 reinterpret_cast<const T*
>(pstorage)->~T();
264 #if defined(ETL_IN_UNIT_TEST)
275 template <
typename T>
276 struct operation_type<T, Copyable, Moveable>
278 static void do_operation(
int operation,
char* pstorage,
const char* pvalue)
284 ::new (pstorage) T(*
reinterpret_cast<const T*
>(pvalue));
290 ::new (pstorage) T(etl::move(*
reinterpret_cast<T*
>(
const_cast<char*
>(pvalue))));
296 reinterpret_cast<const T*
>(pstorage)->~T();
303#if defined(ETL_IN_UNIT_TEST)
318 template <
typename... TTypes>
324 template <
size_t Index,
typename T>
325 struct variant_alternative;
327 template <
size_t Index,
typename... TTypes>
328 struct variant_alternative<Index,
etl::variant<TTypes...>>
330 using type =
typename etl::private_variant::parameter_pack<TTypes...>::template type_from_index<Index>::type;
333 template <
size_t Index,
typename T>
334 struct variant_alternative<Index, const T>
336 using type =
typename variant_alternative<Index, T>::type;
339 template <
size_t Index,
typename T>
340 using variant_alternative_t =
typename variant_alternative<Index, T>::type;
344 template <
typename T,
typename... TTypes>
349 template <
size_t Index,
typename... VTypes>
353 template <
size_t Index,
typename... VTypes>
357 template <
size_t Index,
typename... VTypes>
361 template <
size_t Index,
typename... VTypes>
365 template <
typename T,
typename... VTypes>
368 template <
typename T,
typename... VTypes>
371 template <
typename T,
typename... VTypes>
374 template <
typename T,
typename... VTypes>
391#if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
392 constexpr std::strong_ordering operator<=>(monostate, monostate)
noexcept
394 return std::strong_ordering::equal;
398#if ETL_NOT_USING_STL && !defined(ETL_USE_TYPE_TRAITS_BUILTINS)
414 class variant_exception :
public exception
417 variant_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
418 :
exception(reason_, file_name_, line_number_)
427 class variant_incorrect_type_exception :
public variant_exception
430 variant_incorrect_type_exception(string_type file_name_, numeric_type line_number_)
431 : variant_exception(ETL_ERROR_TEXT(
"variant:unsupported type", ETL_VARIANT_FILE_ID
"A"), file_name_, line_number_)
440 class bad_variant_access :
public variant_exception
443 bad_variant_access(string_type file_name_, numeric_type line_number_)
444 : variant_exception(ETL_ERROR_TEXT(
"variant:bad variant access", ETL_VARIANT_FILE_ID
"B"), file_name_, line_number_)
453 template <
typename... TTypes>
466 template <
size_t Index,
typename... VTypes>
470 template <
size_t Index,
typename... VTypes>
474 template <
size_t Index,
typename... VTypes>
478 template <
size_t Index,
typename... VTypes>
482 template <
typename T,
typename... VTypes>
485 template <
typename T,
typename... VTypes>
488 template <
typename T,
typename... VTypes>
491 template <
typename T,
typename... VTypes>
497 template <
typename... UTypes>
498 friend class variant;
503 using largest_t =
typename largest_type<TTypes...>::type;
508 static const size_t Size =
sizeof(largest_t);
518 template <
typename T,
bool IsCopyable,
bool IsMoveable>
519 using operation_type = private_variant::operation_type<T, IsCopyable, IsMoveable>;
524 static constexpr int Copy = private_variant::Copy;
525 static constexpr int Move = private_variant::Move;
526 static constexpr int Destroy = private_variant::Destroy;
531 template <
typename T>
532 using index_of_type =
typename etl::private_variant::parameter_pack<TTypes...>::template index_of_type<etl::remove_cvref_t<T>>;
537 template <
size_t Index>
538 using type_from_index =
typename etl::private_variant::parameter_pack<TTypes...>::template type_from_index<Index>::type;
547 ETL_CONSTEXPR14 variant()
549 using type =
typename etl::private_variant::parameter_pack<TTypes...>::template type_from_index<0U>::type;
551 default_construct_in_place<type>(data);
561 template <
typename T, etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value,
int> = 0>
562 ETL_CONSTEXPR14 variant(T&& value)
563 : operation(operation_type<
etl::remove_cvref_t<T>,
etl::is_copy_constructible<
etl::remove_cvref_t<T>>::value,
etl::is_move_constructible<
etl::remove_cvref_t<T>>::value>::do_operation)
564 , type_id(index_of_type<T>::value)
568 construct_in_place<etl::remove_cvref_t<T>>(data,
etl::forward<T>(value));
576 template <
typename T,
typename... TArgs>
578 : operation(operation_type<
etl::remove_cvref_t<T>,
etl::is_copy_constructible<
etl::remove_cvref_t<T>>::value,
etl::is_move_constructible<
etl::remove_cvref_t<T>>::value>::do_operation)
579 , type_id(index_of_type<T>::value)
591 template <
size_t Index,
typename... TArgs>
595 using type =
typename private_variant::parameter_pack<TTypes...>:: template type_from_index_t<Index>;
596 static_assert(
etl::is_one_of<type, TTypes...> ::value,
"Unsupported type");
604#if ETL_HAS_INITIALIZER_LIST
609 template <
typename T,
typename U,
typename... TArgs >
611 : operation(operation_type<
etl::remove_cvref_t<T>,
etl::is_copy_constructible<
etl::remove_cvref_t<T>>::value,
etl::is_move_constructible<
etl::remove_cvref_t<T>>::value>::do_operation)
612 , type_id(index_of_type<T>::value)
624 template <
size_t Index,
typename U,
typename... TArgs >
628 using type =
typename private_variant::parameter_pack<TTypes...>:: template type_from_index_t<Index>;
629 static_assert(
etl::is_one_of<type, TTypes...> ::value,
"Unsupported type");
643 ETL_CONSTEXPR14 variant(
const variant& other)
644 : operation(other.operation)
645 , type_id(other.type_id)
649 if (other.index() == variant_npos)
651 type_id = variant_npos;
655 operation(private_variant::Copy, data, other.data);
666 ETL_CONSTEXPR14 variant(variant&& other)
667 : operation(other.operation)
668 , type_id(other.type_id)
672 if (other.index() == variant_npos)
674 type_id = variant_npos;
678 operation(private_variant::Move, data, other.data);
683 type_id = variant_npos;
693 if (
index() != variant_npos)
695 operation(private_variant::Destroy, data,
nullptr);
698 operation = operation_type<void, false, false>::do_operation;
699 type_id = variant_npos;
705 template <
typename T,
typename... TArgs>
708 static_assert(
etl::is_one_of<T, TTypes...>::value,
"Unsupported type");
712 operation(private_variant::Destroy, data,
nullptr);
718 type_id = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
720 return *
static_cast<T*
>(data);
723#if ETL_HAS_INITIALIZER_LIST
727 template <
typename T,
typename U,
typename... TArgs>
728 T&
emplace(std::initializer_list<U> il, TArgs&&... args)
730 static_assert(
etl::is_one_of<T, TTypes...>::value,
"Unsupported type");
734 operation(private_variant::Destroy, data,
nullptr);
740 type_id = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
742 return *
static_cast<T*
>(data);
749 template <
size_t Index,
typename... TArgs>
752 static_assert(Index < etl::private_variant::parameter_pack<TTypes...>
::size,
"Index out of range");
754 using type = type_from_index<Index>;
756 operation(private_variant::Destroy, data,
nullptr);
764 return *
static_cast<type*
>(data);
767#if ETL_HAS_INITIALIZER_LIST
771 template <
size_t Index,
typename U,
typename... TArgs>
774 static_assert(Index < etl::private_variant::parameter_pack<TTypes...>
::size,
"Index out of range");
776 using type = type_from_index<Index>;
778 operation(private_variant::Destroy, data,
nullptr);
786 return *
static_cast<type*
>(data);
794 template <
typename T, etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value,
int> = 0>
799 static_assert(
etl::is_one_of<type, TTypes...>::value,
"Unsupported type");
801 operation(private_variant::Destroy, data,
nullptr);
806 type_id = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<type>::value;
819 if (other.index() == variant_npos)
821 type_id = variant_npos;
825 operation(Destroy, data,
nullptr);
827 operation = other.operation;
828 operation(Copy, data, other.data);
830 type_id = other.type_id;
845 if (other.index() == variant_npos)
847 type_id = variant_npos;
851 operation(Destroy, data,
nullptr);
853 operation = other.operation;
854 operation(Move, data, other.data);
856 type_id = other.type_id;
867 constexpr bool valueless_by_exception() const noexcept
869 return type_id == variant_npos;
875 constexpr size_t index() const noexcept
885 template <
typename T>
896 template <typename T, etl::enable_if_t<is_supported_type<T>(),
int> = 0>
897 constexpr bool is_type() const noexcept
899 return (type_id == etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value);
903 template <typename T, etl::enable_if_t<!is_supported_type<T>(),
int> = 0>
904 constexpr bool is_type() const noexcept
917 return type_id == other.type_id;
923 void swap(variant& rhs)
noexcept
925 variant temp(etl::move(*
this));
926 *
this = etl::move(rhs);
927 rhs = etl::move(temp);
933 template <
typename TVisitor>
937#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
947 template <
typename TVisitor>
949 accept(TVisitor& v)
const
951#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
961 template <
typename TVisitor>
965#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
975 template <
typename TVisitor>
977 accept(TVisitor& v)
const
979#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
990 template <
typename TVisitor>
991#if !defined(ETL_IN_UNIT_TEST)
992 ETL_DEPRECATED_REASON(
"Replace with accept()")
994 void accept_visitor(TVisitor& v)
996#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1007 template <
typename TVisitor>
1008#if !defined(ETL_IN_UNIT_TEST)
1009 ETL_DEPRECATED_REASON(
"Replace with accept()")
1011 void accept_visitor(TVisitor& v)
const
1013#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1024 template <
typename TVisitor>
1025#if !defined(ETL_IN_UNIT_TEST)
1026 ETL_DEPRECATED_REASON(
"Replace with accept()")
1028 void accept_functor(TVisitor& v)
1030#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1041 template <
typename TVisitor>
1042#if !defined(ETL_IN_UNIT_TEST)
1043 ETL_DEPRECATED_REASON(
"Replace with accept()")
1045 void accept_functor(TVisitor& v)
const
1047#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1057 using operation_function = void(*)(int,
char*,
const char*);
1062 template <
typename T>
1063 static void construct_in_place(
char* pstorage,
const T& value)
1067 ::new (pstorage) type(value);
1073 template <
typename T>
1074 static void construct_in_place(
char* pstorage, T&& value)
1078 ::new (pstorage) type(etl::move(value));
1084 template <
typename T,
typename... TArgs>
1085 static void construct_in_place_args(
char* pstorage, TArgs&&... args)
1095 template <
typename T>
1096 static void default_construct_in_place(
char* pstorage)
1100 ::new (pstorage) type();
1103#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1107 template <
typename TVisitor,
size_t... I>
1110 (attempt_visitor<I>(visitor) || ...);
1116 template <
typename TVisitor,
size_t... I>
1119 (attempt_visitor<I>(visitor) || ...);
1125 template <
typename TVisitor>
1126 void do_visitor(TVisitor& visitor)
1130 case 0: { visitor.visit(
etl::get<0>(*
this));
break; }
1131 case 1: { visitor.visit(
etl::get<1>(*
this));
break; }
1132 case 2: { visitor.visit(
etl::get<2>(*
this));
break; }
1133 case 3: { visitor.visit(
etl::get<3>(*
this));
break; }
1134 case 4: { visitor.visit(
etl::get<4>(*
this));
break; }
1135 case 5: { visitor.visit(
etl::get<5>(*
this));
break; }
1136 case 6: { visitor.visit(
etl::get<6>(*
this));
break; }
1137 case 7: { visitor.visit(
etl::get<7>(*
this));
break; }
1138#if !defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1139 case 8: { visitor.visit(
etl::get<8>(*
this));
break; }
1140 case 9: { visitor.visit(
etl::get<9>(*
this));
break; }
1141 case 10: { visitor.visit(
etl::get<10>(*
this));
break; }
1142 case 11: { visitor.visit(
etl::get<11>(*
this));
break; }
1143 case 12: { visitor.visit(
etl::get<12>(*
this));
break; }
1144 case 13: { visitor.visit(
etl::get<13>(*
this));
break; }
1145 case 14: { visitor.visit(
etl::get<14>(*
this));
break; }
1146 case 15: { visitor.visit(
etl::get<15>(*
this));
break; }
1147#if !defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1148 case 16: { visitor.visit(
etl::get<16>(*
this));
break; }
1149 case 17: { visitor.visit(
etl::get<17>(*
this));
break; }
1150 case 18: { visitor.visit(
etl::get<18>(*
this));
break; }
1151 case 19: { visitor.visit(
etl::get<19>(*
this));
break; }
1152 case 20: { visitor.visit(
etl::get<20>(*
this));
break; }
1153 case 21: { visitor.visit(
etl::get<21>(*
this));
break; }
1154 case 22: { visitor.visit(
etl::get<22>(*
this));
break; }
1155 case 23: { visitor.visit(
etl::get<23>(*
this));
break; }
1156#if !defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1157 case 24: { visitor.visit(
etl::get<24>(*
this));
break; }
1158 case 25: { visitor.visit(
etl::get<25>(*
this));
break; }
1159 case 26: { visitor.visit(
etl::get<26>(*
this));
break; }
1160 case 27: { visitor.visit(
etl::get<27>(*
this));
break; }
1161 case 28: { visitor.visit(
etl::get<28>(*
this));
break; }
1162 case 29: { visitor.visit(
etl::get<29>(*
this));
break; }
1163 case 30: { visitor.visit(
etl::get<30>(*
this));
break; }
1164 case 31: { visitor.visit(
etl::get<31>(*
this));
break; }
1175 template <
typename TVisitor>
1176 void do_visitor(TVisitor& visitor)
const
1180 case 0: { visitor.visit(
etl::get<0>(*
this));
break; }
1181 case 1: { visitor.visit(
etl::get<1>(*
this));
break; }
1182 case 2: { visitor.visit(
etl::get<2>(*
this));
break; }
1183 case 3: { visitor.visit(
etl::get<3>(*
this));
break; }
1184 case 4: { visitor.visit(
etl::get<4>(*
this));
break; }
1185 case 5: { visitor.visit(
etl::get<5>(*
this));
break; }
1186 case 6: { visitor.visit(
etl::get<6>(*
this));
break; }
1187 case 7: { visitor.visit(
etl::get<7>(*
this));
break; }
1188#if !defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1189 case 8: { visitor.visit(
etl::get<8>(*
this));
break; }
1190 case 9: { visitor.visit(
etl::get<9>(*
this));
break; }
1191 case 10: { visitor.visit(
etl::get<10>(*
this));
break; }
1192 case 11: { visitor.visit(
etl::get<11>(*
this));
break; }
1193 case 12: { visitor.visit(
etl::get<12>(*
this));
break; }
1194 case 13: { visitor.visit(
etl::get<13>(*
this));
break; }
1195 case 14: { visitor.visit(
etl::get<14>(*
this));
break; }
1196 case 15: { visitor.visit(
etl::get<15>(*
this));
break; }
1197#if !defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1198 case 16: { visitor.visit(
etl::get<16>(*
this));
break; }
1199 case 17: { visitor.visit(
etl::get<17>(*
this));
break; }
1200 case 18: { visitor.visit(
etl::get<18>(*
this));
break; }
1201 case 19: { visitor.visit(
etl::get<19>(*
this));
break; }
1202 case 20: { visitor.visit(
etl::get<20>(*
this));
break; }
1203 case 21: { visitor.visit(
etl::get<21>(*
this));
break; }
1204 case 22: { visitor.visit(
etl::get<22>(*
this));
break; }
1205 case 23: { visitor.visit(
etl::get<23>(*
this));
break; }
1206#if !defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1207 case 24: { visitor.visit(
etl::get<24>(*
this));
break; }
1208 case 25: { visitor.visit(
etl::get<25>(*
this));
break; }
1209 case 26: { visitor.visit(
etl::get<26>(*
this));
break; }
1210 case 27: { visitor.visit(
etl::get<27>(*
this));
break; }
1211 case 28: { visitor.visit(
etl::get<28>(*
this));
break; }
1212 case 29: { visitor.visit(
etl::get<29>(*
this));
break; }
1213 case 30: { visitor.visit(
etl::get<30>(*
this));
break; }
1214 case 31: { visitor.visit(
etl::get<31>(*
this));
break; }
1226 template <
size_t Index,
typename TVisitor>
1227 bool attempt_visitor(TVisitor& visitor)
1229 if (Index ==
index())
1247 template <
size_t Index,
typename TVisitor>
1248 bool attempt_visitor(TVisitor& visitor)
const
1250 if (Index ==
index())
1265#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1269 template <
typename TVisitor,
size_t... I>
1272 (attempt_operator<I>(visitor) || ...);
1278 template <
typename TVisitor,
size_t... I>
1281 (attempt_operator<I>(visitor) || ...);
1287 template <
typename TVisitor>
1288 void do_operator(TVisitor& visitor)
1290#if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1291 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 8U,
"ETL_VARIANT_CPP11_MAX_8_TYPES - Only a maximum of 8 types are allowed in this variant");
1294#if defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1295 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 16U,
"ETL_VARIANT_CPP11_MAX_16_TYPES - Only a maximum of 16 types are allowed in this variant");
1298#if defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1299 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 24U,
"ETL_VARIANT_CPP11_MAX_24_TYPES - Only a maximum of 24 types are allowed in this variant");
1302 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 32U,
"A maximum of 32 types are allowed in this variant");
1314#if !defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1323#if !defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1332#if !defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1351 template <
typename TVisitor>
1352 void do_operator(TVisitor& visitor)
const
1354#if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1355 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 8U,
"ETL_VARIANT_CPP11_MAX_8_TYPES - Only a maximum of 8 types are allowed in this variant");
1358#if defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1359 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 16U,
"ETL_VARIANT_CPP11_MAX_16_TYPES - Only a maximum of 16 types are allowed in this variant");
1362#if defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1363 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 24U,
"ETL_VARIANT_CPP11_MAX_24_TYPES - Only a maximum of 24 types are allowed in this variant");
1366 ETL_STATIC_ASSERT(
sizeof...(TTypes) <= 32U,
"A maximum of 32 types are allowed in this variant");
1378#if !defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1387#if !defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1396#if !defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1416 template <
size_t Index,
typename TVisitor>
1417 bool attempt_operator(TVisitor& visitor)
1419 if (Index ==
index())
1434 template <
size_t Index,
typename TVisitor>
1435 bool attempt_operator(TVisitor& visitor)
const
1437 if (Index ==
index())
1458 operation_function operation;
1469 template <
typename T,
typename... TTypes>
1472 constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
1474 return (Index == variant_npos) ? false : (v.index() == Index);
1480 template <
size_t Index,
typename... TTypes>
1483 return (Index == v.index());
1489 template <
typename... TTypes>
1492 return (index == v.index());
1498 template <
size_t Index,
typename... TTypes>
1502#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1503 static_assert(Index <
sizeof...(TTypes),
"Index out of range");
1510 return *
static_cast<type*
>(v.data);
1514 template <
size_t Index,
typename... TTypes>
1518#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1519 static_assert(Index <
sizeof...(TTypes),
"Index out of range");
1524 return etl::move(*
static_cast<type*
>(v.data));
1528 template <
size_t Index,
typename... TTypes>
1532#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1533 static_assert(Index <
sizeof...(TTypes),
"Index out of range");
1540 return *
static_cast<const type*
>(v.data);
1544 template <
size_t Index,
typename... TTypes>
1548#if ETL_USING_CPP17 & !defined(ETL_VARIANT_FORCE_CPP11)
1549 static_assert(Index <
sizeof...(TTypes),
"Index out of range");
1556 return etl::move(*
static_cast<const type*
>(v.data));
1560 template <
typename T,
typename... TTypes>
1563 constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
1565 return get<Index>(v);
1569 template <
typename T,
typename... TTypes>
1572 constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
1574 return get<Index>(etl::move(v));
1578 template <
typename T,
typename... TTypes>
1581 constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
1583 return get<Index>(v);
1587 template <
typename T,
typename... TTypes>
1590 constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
1592 return get<Index>(etl::move(v));
1598 template<
size_t Index,
typename... TTypes >
1602 if ((pv !=
nullptr) && (pv->index() == Index))
1613 template<
size_t Index,
typename... TTypes >
1617 if ((pv !=
nullptr) && (pv->index() == Index))
1628 template<
class T,
typename... TTypes >
1631 constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
1633 if ((pv !=
nullptr) && (pv->index() == Index))
1644 template<
typename T,
typename... TTypes >
1647 constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
1649 if ((pv !=
nullptr) && (pv->index() == Index))
1662 template <
typename... TTypes>
1671 template <
typename T>
1672 struct variant_size;
1674 template <
typename... TTypes>
1675 struct variant_size<
etl::variant<TTypes...>>
1680 template <
typename T>
1681 struct variant_size<const T>
1687 template <
typename... TTypes>
1688 inline constexpr size_t variant_size_v = variant_size<TTypes...>::value;
1694 namespace private_variant
1696 template <
typename TRet,
typename TCallable,
typename TVariant,
size_t tIndex,
typename TNext,
typename... TVariants>
1697 static ETL_CONSTEXPR14 TRet do_visit_single(TCallable&& f, TVariant&& v, TNext&&, TVariants&&... vs);
1704 struct visit_auto_return
1712 template <
typename TCallable,
typename... Ts>
1713 struct single_visit_result_type
1715 using type =
decltype(declval<TCallable>()(declval<Ts>()...));
1718 template <
typename TCallable,
typename... Ts>
1719 using single_visit_result_type_t =
typename single_visit_result_type<TCallable, Ts...>::type;
1725 template <
typename TVar,
typename T>
1726 using rlref_copy = conditional_t<is_reference<TVar>::value, T&, T&&>;
1736 template <
template <
typename...>
class,
typename...>
1737 struct visit_result_helper;
1739 template <
template <
typename...>
class TToInject,
size_t... tAltIndices,
typename TCur>
1740 struct visit_result_helper<TToInject, index_sequence<tAltIndices...>, TCur>
1742 template <
size_t tIndex>
1743 using var_type = rlref_copy<TCur,
1744 variant_alternative_t<tIndex, remove_reference_t<TCur> > >;
1746 using type = common_type_t<TToInject<var_type<tAltIndices> >...>;
1749 template <
template <
typename...>
class TToInject,
size_t... tAltIndices,
typename TCur,
typename TNext,
typename... TVs>
1750 struct visit_result_helper<TToInject, index_sequence<tAltIndices...>, TCur, TNext, TVs...>
1752 template <
size_t tIndex>
1753 using var_type = rlref_copy<TCur, variant_alternative_t<tIndex, remove_reference_t<TCur> > >;
1755 template <
size_t tIndex>
1756 struct next_inject_wrap
1758 template <
typename... TNextInj>
1759 using next_inject = TToInject<var_type<tIndex>, TNextInj...>;
1760 using recursive_result =
typename visit_result_helper<next_inject, make_index_sequence<variant_size<remove_reference_t<TNext> >::value>, TNext, TVs...>::type;
1763 using type = common_type_t<typename next_inject_wrap<tAltIndices>::recursive_result...>;
1771 template <
typename TRet,
typename...>
1777 template <
typename TCallable,
typename T1,
typename... Ts>
1778 struct visit_result<visit_auto_return, TCallable, T1, Ts...>
1781 template <
typename... Ts2>
1782 using single_res = single_visit_result_type_t<TCallable, Ts2...>;
1783 using type =
typename visit_result_helper<single_res, make_index_sequence<variant_size<remove_reference_t<T1> >::value>, T1, Ts...>::type;
1786 template <
typename... Ts>
1787 using visit_result_t =
typename visit_result<Ts...>::type;
1793 template <
typename TRet,
typename TCallable,
typename TVariant,
size_t tIndex>
1794 constexpr TRet do_visit_single(TCallable&& f, TVariant&& v)
1796 return static_cast<TCallable&&
>(f)(
etl::get<tIndex>(
static_cast<TVariant&&
>(v)));
1804 template <
typename TRet,
typename TCallable,
typename TCurVariant,
typename... TVarRest>
1805 struct do_visit_helper
1807 using function_pointer = add_pointer_t<TRet(TCallable&&, TCurVariant&&, TVarRest&&...)>;
1809 template <
size_t tIndex>
1810 static constexpr function_pointer fptr() noexcept
1812 return &do_visit_single<TRet, TCallable, TCurVariant, tIndex, TVarRest...>;
1819 template <
typename TRet,
typename TCallable,
typename TVariant,
size_t... tIndices,
typename... TVarRest>
1820 static ETL_CONSTEXPR14 TRet do_visit(TCallable&& f, TVariant&& v, index_sequence<tIndices...>, TVarRest&&... variants)
1822 ETL_ASSERT(!v.valueless_by_exception(), ETL_ERROR(bad_variant_access));
1824 using helper_t = do_visit_helper<TRet, TCallable, TVariant, TVarRest...>;
1825 using func_ptr =
typename helper_t::function_pointer;
1827 constexpr func_ptr jmp_table[]
1829 helper_t::template fptr<tIndices>()...
1832 return jmp_table[v.index()](
static_cast<TCallable&&
>(f),
static_cast<TVariant&&
>(v),
static_cast<TVarRest&&
>(variants)...);
1835 template <
typename TRet,
typename TCallable,
typename TVariant,
typename... TVs>
1836 static ETL_CONSTEXPR14 TRet visit(TCallable&& f, TVariant&& v, TVs&&... vs)
1839 return private_variant::do_visit<TRet>(
static_cast<TCallable&&
>(f),
1840 static_cast<TVariant&&
>(v),
1841 make_index_sequence<variants>{},
1842 static_cast<TVs&&
>(vs)...);
1849 template <
typename TRet,
typename TCallable,
typename TVariant,
size_t tIndex>
1850 class constexpr_visit_closure
1852 add_pointer_t<TCallable> callable_;
1853 add_pointer_t<TVariant> variant_;
1856 constexpr constexpr_visit_closure(TCallable&& c, TVariant&& v)
1857 : callable_(&c), variant_(&v)
1861 template <
typename... Ts>
1862 ETL_CONSTEXPR14 TRet operator()(Ts&&... args)
const
1864 return static_cast<TCallable&&
>(*callable_)(get<tIndex>(
static_cast<TVariant&&
>(*variant_)),
static_cast<Ts&&
>(args)...);
1868 template <
typename TRet,
typename TCallable,
typename TVariant,
size_t tIndex,
typename TNext,
typename... TVariants>
1869 static ETL_CONSTEXPR14 TRet do_visit_single(TCallable&& f, TVariant&& v, TNext&& next, TVariants&&... vs)
1871 return private_variant::visit<TRet>(constexpr_visit_closure<TRet, TCallable, TVariant, tIndex>(
static_cast<TCallable&&
>(f),
static_cast<TVariant&&
>(v)),
1872 static_cast<TNext&&
>(next),
static_cast<TVariants&&
>(vs)...);
1881 template <
typename TRet = private_variant::visit_auto_return,
typename... TVariants,
typename TCallable,
typename TDeducedReturn = private_variant::visit_result_t<TRet, TCallable, TVariants...> >
1882 static ETL_CONSTEXPR14 TDeducedReturn visit(TCallable&& f, TVariants&&... vs)
1884 return private_variant::visit<TDeducedReturn>(
static_cast<TCallable&&
>(f),
static_cast<TVariants&&
>(vs)...);
1887 namespace private_variant
1893 template <
typename TVariant>
1894 struct equality_visitor
1896 equality_visitor(
const TVariant& rhs_)
1901 template <
typename TValue>
1902 bool operator()(
const TValue& lhs_downcasted)
1907 const TVariant& rhs;
1914 template <
typename TVariant>
1915 struct less_than_visitor
1917 less_than_visitor(
const TVariant& rhs_)
1922 template <
typename TValue>
1923 bool operator()(
const TValue& lhs_downcasted)
1925 return lhs_downcasted < etl::get<TValue>(rhs);
1928 const TVariant& rhs;
1936 template <
typename... TTypes>
1940 if (lhs.valueless_by_exception() && rhs.valueless_by_exception())
1946 if (lhs.valueless_by_exception() || rhs.valueless_by_exception())
1952 if (lhs.index() != rhs.index())
1958 private_variant::equality_visitor<
etl::variant<TTypes...>> visitor(rhs);
1960 return etl::visit(visitor, lhs);
1967 template <
typename... TTypes>
1970 return !(lhs == rhs);
1977 template <
typename... TTypes>
1981 if (lhs.valueless_by_exception() && rhs.valueless_by_exception())
1987 if (lhs.valueless_by_exception())
1993 if (rhs.valueless_by_exception())
1999 if (lhs.index() != rhs.index())
2001 return lhs.index() < rhs.index();
2005 private_variant::less_than_visitor<
etl::variant<TTypes...>> visitor(rhs);
2007 return etl::visit(visitor, lhs);
2014 template <
typename... TTypes>
2024 template <
typename... TTypes>
2027 return !(lhs > rhs);
2034 template <
typename... TTypes>
2037 return !(lhs < rhs);
2040 namespace private_variant
2042#if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
2047 template <
typename TVariant>
2048 struct compare_visitor
2050 compare_visitor(
const TVariant& rhs_)
2055 template <
typename TValue>
2056 std::strong_ordering operator()(
const TValue& lhs_downcasted)
2061 const TVariant& rhs;
2071#if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
2072 template <
typename... TTypes>
2074 std::common_comparison_category_t<std::compare_three_way_result_t<TTypes>...>
2077 if (lhs.valueless_by_exception() && rhs.valueless_by_exception())
2079 return std::strong_ordering::equal;
2081 else if (lhs.valueless_by_exception())
2083 return std::strong_ordering::less;
2085 else if (rhs.valueless_by_exception())
2087 return std::strong_ordering::greater;
2089 else if (lhs.index() != rhs.index())
2091 return lhs.index() <=> rhs.index();
2096 private_variant::compare_visitor<
etl::variant<TTypes...>> visitor(rhs);
2098 return etl::visit(visitor, lhs);
#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 integral_limits.h:516
conditional
Definition type_traits_generator.h:1155
integral_constant
Definition type_traits_generator.h:827
is_same
Definition type_traits_generator.h:1036
static bool is_supported_type()
Definition variant_legacy.h:879
~variant()
Destructor.
Definition variant_legacy.h:230
bool is_same_type(const variant &other) const
Definition variant_legacy.h:662
T & get()
Definition variant_legacy.h:754
uint_least8_t type_id_t
The type used for ids.
Definition variant_legacy.h:153
variant & operator=(const T &value)
Definition variant_legacy.h:617
bool is_type() const
Definition variant_legacy.h:727
T & emplace()
Emplace with one constructor parameter.
Definition variant_legacy.h:540
size_t index() const
Gets the index of the type currently stored or UNSUPPORTED_TYPE_ID.
Definition variant_legacy.h:735
Definition variant_legacy.h:147
Definition variant_legacy.h:100
Definition variant_legacy.h:79
bitset_ext
Definition absolute.h:38
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:693
T & get(array< T, MAXN > &a)
Definition array.h:719
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:705
bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:654
void swap(etl::array< T, SIZE > &lhs, etl::array< T, SIZE > &rhs)
Template deduction guides.
Definition array.h:630
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1187
bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:642
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:666
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:681
Definition type_traits_generator.h:2074
pair holds two objects of arbitrary type
Definition utility.h:164
Definition variant_legacy.h:950