31#include "../platform.h"
32#include "../utility.h"
33#include "../largest.h"
34#include "../nth_type.h"
35#include "../exception.h"
36#include "../type_traits.h"
37#include "../integral_limits.h"
38#include "../static_assert.h"
39#include "../alignment.h"
40#include "../error_handler.h"
41#include "../type_list.h"
42#include "../placement_new.h"
43#include "../visitor.h"
45#include "../compare.h"
46#include "../initializer_list.h"
47#include "../monostate.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
69 namespace private_variant
74 static constexpr bool Copyable =
true;
76 static constexpr bool Moveable =
true;
82 static constexpr int Copy = 0;
83 static constexpr int Move = 1;
84 static constexpr int Destroy = 2;
89 template <
typename T,
bool IsCopyable,
bool IsMoveable>
97 static void do_operation(
int,
char*,
const char*)
100#if defined(ETL_IN_UNIT_TEST)
108 template <
typename T>
111 static void do_operation(
int operation,
char* pstorage,
const char* )
117 reinterpret_cast<const T*
>(pstorage)->~T();
124#if defined(ETL_IN_UNIT_TEST)
135 template <
typename T>
138 static void do_operation(
int operation,
char* pstorage,
const char* pvalue)
144 ::new (pstorage) T(etl::move(*
reinterpret_cast<T*
>(
const_cast<char*
>(pvalue))));
150 reinterpret_cast<const T*
>(pstorage)->~T();
157#if defined(ETL_IN_UNIT_TEST)
168 template <
typename T>
171 static void do_operation(
int operation,
char* pstorage,
const char* pvalue)
177 ::new (pstorage) T(*
reinterpret_cast<const T*
>(pvalue));
183 reinterpret_cast<const T*
>(pstorage)->~T();
190#if defined(ETL_IN_UNIT_TEST)
201 template <
typename T>
204 static void do_operation(
int operation,
char* pstorage,
const char* pvalue)
210 ::new (pstorage) T(*
reinterpret_cast<const T*
>(pvalue));
216 ::new (pstorage) T(etl::move(*
reinterpret_cast<T*
>(
const_cast<char*
>(pvalue))));
222 reinterpret_cast<const T*
>(pstorage)->~T();
229#if defined(ETL_IN_UNIT_TEST)
244 template <
typename...
TTypes>
250 template <
size_t Index,
typename T>
251 struct variant_alternative;
254 struct variant_alternative<
Index,
etl::variant<TTypes...>>
259 template <
size_t Index,
typename T>
262 using type =
typename variant_alternative<Index, T>::type;
265 template <
size_t Index,
typename T>
270 template <
typename T,
typename...
TTypes>
291 template <
typename T,
typename...
VTypes>
294 template <
typename T,
typename...
VTypes>
297 template <
typename T,
typename...
VTypes>
300 template <
typename T,
typename...
VTypes>
303#if ETL_NOT_USING_CPP17
304 #include "variant_select_do_visitor.h"
305 #include "variant_select_do_operator.h"
314#if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
315 constexpr std::strong_ordering
operator<=>(monostate, monostate)
noexcept
317 return std::strong_ordering::equal;
321#if ETL_NOT_USING_STL && !defined(ETL_USE_TYPE_TRAITS_BUILTINS)
337 class variant_exception :
public exception
350 class variant_incorrect_type_exception :
public variant_exception
354 : variant_exception(ETL_ERROR_TEXT(
"variant:unsupported type", ETL_VARIANT_FILE_ID
"A"),
file_name_,
line_number_)
363 class bad_variant_access :
public variant_exception
367 : variant_exception(ETL_ERROR_TEXT(
"variant:bad variant access", ETL_VARIANT_FILE_ID
"B"),
file_name_,
line_number_)
376 template <
typename...
TTypes>
400 template <
typename T,
typename...
VTypes>
403 template <
typename T,
typename...
VTypes>
406 template <
typename T,
typename...
VTypes>
409 template <
typename T,
typename...
VTypes>
415 template <
typename...
UTypes>
416 friend class variant;
421 using largest_t =
typename largest_type<
TTypes...>::type;
426 static const size_t Size =
sizeof(largest_t);
436 template <
typename T,
bool IsCopyable,
bool IsMoveable>
437 using operation_type = private_variant::operation_type<T, IsCopyable, IsMoveable>;
442 static constexpr int Copy = private_variant::Copy;
443 static constexpr int Move = private_variant::Move;
444 static constexpr int Destroy = private_variant::Destroy;
449 template <
typename T>
455 template <
size_t Index>
465 ETL_CONSTEXPR14 variant()
479 template <
typename T, etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value,
int> = 0>
480 ETL_CONSTEXPR14 variant(
T&& value)
494 template <
typename T,
typename...
TArgs>
522#if ETL_HAS_INITIALIZER_LIST
527 template <
typename T,
typename U,
typename...
TArgs >
542 template <
size_t Index,
typename U,
typename...
TArgs >
561 ETL_CONSTEXPR14 variant(
const variant&
other)
562 : operation(
other.operation)
563 , type_id(
other.type_id)
573 operation(private_variant::Copy, data,
other.data);
584 ETL_CONSTEXPR14 variant(variant&&
other)
585 : operation(
other.operation)
586 , type_id(
other.type_id)
596 operation(private_variant::Move, data,
other.data);
613 operation(private_variant::Destroy, data,
nullptr);
616 operation = operation_type<void, false, false>::do_operation;
623 template <
typename T,
typename...
TArgs>
630 operation(private_variant::Destroy, data,
nullptr);
636 type_id = index_of_type<T>::value;
638 return *
static_cast<T*
>(data);
641#if ETL_HAS_INITIALIZER_LIST
645 template <
typename T,
typename U,
typename...
TArgs>
652 operation(private_variant::Destroy, data,
nullptr);
658 type_id = index_of_type<T>::value;
660 return *
static_cast<T*
>(data);
670 static_assert(
Index <
sizeof...(TTypes),
"Index out of range");
674 operation(private_variant::Destroy, data,
nullptr);
682 return *
static_cast<type*
>(data);
685#if ETL_HAS_INITIALIZER_LIST
689 template <
size_t Index,
typename U,
typename...
TArgs>
692 static_assert(
Index <
sizeof...(TTypes),
"Index out of range");
696 operation(private_variant::Destroy, data,
nullptr);
704 return *
static_cast<type*
>(data);
712 template <
typename T, etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value,
int> = 0>
719 operation(private_variant::Destroy, data,
nullptr);
724 type_id = index_of_type<type>::value;
743 operation(
Destroy, data,
nullptr);
745 operation =
other.operation;
748 type_id =
other.type_id;
769 operation(
Destroy, data,
nullptr);
771 operation =
other.operation;
774 type_id =
other.type_id;
803 template <
typename T>
817 return (type_id == index_of_type<T>::value);
835 return type_id ==
other.type_id;
841 void swap(variant&
rhs)
noexcept
843 variant
temp(etl::move(*
this));
844 *
this = etl::move(
rhs);
851 template <
typename TVisitor>
855#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
858 do_visitor<
sizeof...(TTypes)>(
v);
865 template <
typename TVisitor>
869#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
872 do_visitor<
sizeof...(TTypes)>(
v);
879 template <
typename TVisitor>
883#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
886 do_operator<
sizeof...(TTypes)>(
v);
893 template <
typename TVisitor>
897#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
900 do_operator<
sizeof...(TTypes)>(
v);
908 template <
typename TVisitor>
909#if !defined(ETL_IN_UNIT_TEST)
910 ETL_DEPRECATED_REASON(
"Replace with accept()")
914#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
917 do_visitor<
sizeof...(TTypes)>(
v);
925 template <
typename TVisitor>
926#if !defined(ETL_IN_UNIT_TEST)
927 ETL_DEPRECATED_REASON(
"Replace with accept()")
931#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
934 do_visitor<
sizeof...(TTypes)>(
v);
942 template <
typename TVisitor>
943#if !defined(ETL_IN_UNIT_TEST)
944 ETL_DEPRECATED_REASON(
"Replace with accept()")
948#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
951 do_operator<
sizeof...(TTypes)>(
v);
959 template <
typename TVisitor>
960#if !defined(ETL_IN_UNIT_TEST)
961 ETL_DEPRECATED_REASON(
"Replace with accept()")
965#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
968 do_operator<
sizeof...(TTypes)>(
v);
980 template <
typename T>
991 template <
typename T>
1002 template <
typename T,
typename...
TArgs>
1013 template <
typename T>
1021#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1025 template <
typename TVisitor,
size_t...
I>
1034 template <
typename TVisitor,
size_t...
I>
1043 template <
size_t NTypes,
typename TVisitor>
1046 etl::private_variant::select_do_visitor<NTypes>::do_visitor(*
this, visitor);
1052 template <
size_t NTypes,
typename TVisitor>
1053 void do_visitor(
TVisitor& visitor)
const
1055 etl::private_variant::select_do_visitor<NTypes>::do_visitor(*
this, visitor);
1062 template <
size_t Index,
typename TVisitor>
1083 template <
size_t Index,
typename TVisitor>
1101#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1105 template <
typename TVisitor,
size_t...
I>
1114 template <
typename TVisitor,
size_t...
I>
1123 template <
size_t NTypes,
typename TVisitor>
1124 void do_operator(
TVisitor& visitor)
1126#if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1127 ETL_STATIC_ASSERT(
sizeof...(
TTypes) <= 8U,
"ETL_VARIANT_CPP11_MAX_8_TYPES - Only a maximum of 8 types are allowed in this variant");
1130#if defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1131 ETL_STATIC_ASSERT(
sizeof...(
TTypes) <= 16U,
"ETL_VARIANT_CPP11_MAX_16_TYPES - Only a maximum of 16 types are allowed in this variant");
1134#if defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1135 ETL_STATIC_ASSERT(
sizeof...(
TTypes) <= 24U,
"ETL_VARIANT_CPP11_MAX_24_TYPES - Only a maximum of 24 types are allowed in this variant");
1138 ETL_STATIC_ASSERT(
sizeof...(
TTypes) <= 32U,
"A maximum of 32 types are allowed in this variant");
1140 etl::private_variant::select_do_operator<NTypes>::do_operator(*
this, visitor);
1146 template <
size_t NTypes,
typename TVisitor>
1147 void do_operator(
TVisitor& visitor)
const
1149#if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1150 ETL_STATIC_ASSERT(
sizeof...(
TTypes) <= 8U,
"ETL_VARIANT_CPP11_MAX_8_TYPES - Only a maximum of 8 types are allowed in this variant");
1153#if defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1154 ETL_STATIC_ASSERT(
sizeof...(
TTypes) <= 16U,
"ETL_VARIANT_CPP11_MAX_16_TYPES - Only a maximum of 16 types are allowed in this variant");
1157#if defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1158 ETL_STATIC_ASSERT(
sizeof...(
TTypes) <= 24U,
"ETL_VARIANT_CPP11_MAX_24_TYPES - Only a maximum of 24 types are allowed in this variant");
1161 ETL_STATIC_ASSERT(
sizeof...(
TTypes) <= 32U,
"A maximum of 32 types are allowed in this variant");
1163 etl::private_variant::select_do_operator<NTypes>::do_operator(*
this, visitor);
1170 template <
size_t Index,
typename TVisitor>
1188 template <
size_t Index,
typename TVisitor>
1207 etl::uninitialized_buffer<Size, 1U, Alignment> data;
1223 template <
typename T,
typename...
TTypes>
1237 return (
Index ==
v.index());
1243 template <
typename...
TTypes>
1246 return (index ==
v.index());
1256#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1257 static_assert(
Index <
sizeof...(TTypes),
"Index out of range");
1264 return *
static_cast<type*
>(
v.data);
1272#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1273 static_assert(
Index <
sizeof...(TTypes),
"Index out of range");
1278 return etl::move(*
static_cast<type*
>(
v.data));
1286#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1287 static_assert(
Index <
sizeof...(TTypes),
"Index out of range");
1294 return *
static_cast<const type*
>(
v.data);
1302#if ETL_USING_CPP17 & !defined(ETL_VARIANT_FORCE_CPP11)
1303 static_assert(
Index <
sizeof...(TTypes),
"Index out of range");
1310 return etl::move(*
static_cast<const type*
>(
v.data));
1314 template <
typename T,
typename...
TTypes>
1323 template <
typename T,
typename...
TTypes>
1332 template <
typename T,
typename...
TTypes>
1341 template <
typename T,
typename...
TTypes>
1356 if ((
pv !=
nullptr) && (
pv->index() ==
Index))
1371 if ((
pv !=
nullptr) && (
pv->index() ==
Index))
1382 template<
class T,
typename...
TTypes >
1387 if ((
pv !=
nullptr) && (
pv->index() ==
Index))
1398 template<
typename T,
typename...
TTypes >
1403 if ((
pv !=
nullptr) && (
pv->index() ==
Index))
1416 template <
typename...
TTypes>
1425 template <
typename T>
1428 template <
typename...
TTypes>
1434 template <
typename T>
1441 template <
typename...
TTypes>
1448 namespace private_variant
1469 using type =
decltype(declval<TCallable>()(declval<Ts>()...));
1479 template <
typename TVar,
typename T>
1490 template <
template <
typename...>
class,
typename...>
1496 template <
size_t tIndex>
1497 using var_type = rlref_copy<TCur,
1498 variant_alternative_t<tIndex, remove_reference_t<TCur> > >;
1500 using type = common_type_t<TToInject<var_type<tAltIndices> >...>;
1506 template <
size_t tIndex>
1507 using var_type = rlref_copy<TCur, variant_alternative_t<tIndex, remove_reference_t<TCur> > >;
1509 template <
size_t tIndex>
1510 struct next_inject_wrap
1512 template <
typename... TNextInj>
1513 using next_inject = TToInject<var_type<tIndex>, TNextInj...>;
1514 using recursive_result =
typename visit_result_helper<next_inject, make_index_sequence<variant_size<remove_reference_t<TNext> >::value>, TNext, TVs...>::type;
1517 using type = common_type_t<typename next_inject_wrap<tAltIndices>::recursive_result...>;
1525 template <
typename TRet,
typename...>
1535 template <
typename... Ts2>
1536 using single_res = single_visit_result_type_t<TCallable, Ts2...>;
1537 using type =
typename visit_result_helper<single_res, make_index_sequence<variant_size<remove_reference_t<T1> >::value>, T1, Ts...>::type;
1540 template <
typename...
Ts>
1547 template <
typename TRet,
typename TCallable,
typename TVariant,
size_t tIndex>
1561 using function_pointer = add_pointer_t<TRet(TCallable&&, TCurVariant&&, TVarRest&&...)>;
1563 template <
size_t tIndex>
1564 static constexpr function_pointer fptr() noexcept
1566 return &do_visit_single<TRet, TCallable, TCurVariant, tIndex, TVarRest...>;
1576 ETL_ASSERT(!
v.valueless_by_exception(), ETL_ERROR(bad_variant_access));
1579 using func_ptr =
typename helper_t::function_pointer;
1593 return private_variant::do_visit<TRet>(
static_cast<TCallable&&
>(
f),
1596 static_cast<TVs&&
>(
vs)...);
1603 template <
typename TRet,
typename TCallable,
typename TVariant,
size_t tIndex>
1606 add_pointer_t<TCallable> callable_;
1607 add_pointer_t<TVariant> variant_;
1610 constexpr constexpr_visit_closure(TCallable&& c, TVariant&& v)
1611 : callable_(&c), variant_(&v)
1615 template <
typename... Ts>
1616 ETL_CONSTEXPR14 TRet operator()(Ts&&... args)
const
1618 return static_cast<TCallable&&
>(*callable_)(get<tIndex>(
static_cast<TVariant&&
>(*variant_)),
static_cast<Ts&&
>(args)...);
1638 return private_variant::visit<TDeducedReturn>(
static_cast<TCallable&&
>(
f),
static_cast<TVariants&&
>(
vs)...);
1641 namespace private_variant
1647 template <
typename TVariant>
1655 template <
typename TValue>
1668 template <
typename TVariant>
1676 template <
typename TValue>
1690 template <
typename...
TTypes>
1694 if (
lhs.valueless_by_exception() &&
rhs.valueless_by_exception())
1700 if (
lhs.valueless_by_exception() ||
rhs.valueless_by_exception())
1706 if (
lhs.index() !=
rhs.index())
1714 return etl::visit(visitor,
lhs);
1721 template <
typename...
TTypes>
1731 template <
typename...
TTypes>
1735 if (
lhs.valueless_by_exception() &&
rhs.valueless_by_exception())
1741 if (
lhs.valueless_by_exception())
1747 if (
rhs.valueless_by_exception())
1753 if (
lhs.index() !=
rhs.index())
1755 return lhs.index() <
rhs.index();
1761 return etl::visit(visitor,
lhs);
1768 template <
typename...
TTypes>
1778 template <
typename...
TTypes>
1788 template <
typename...
TTypes>
1794 namespace private_variant
1796#if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
1801 template <
typename TVariant>
1804 compare_visitor(
const TVariant& rhs_)
1809 template <
typename TValue>
1810 std::strong_ordering operator()(
const TValue& lhs_downcasted)
1815 const TVariant& rhs;
1825#if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
1826 template <
typename...
TTypes>
1828 std::common_comparison_category_t<std::compare_three_way_result_t<TTypes>...>
1831 if (
lhs.valueless_by_exception() &&
rhs.valueless_by_exception())
1833 return std::strong_ordering::equal;
1835 else if (
lhs.valueless_by_exception())
1837 return std::strong_ordering::less;
1839 else if (
rhs.valueless_by_exception())
1841 return std::strong_ordering::greater;
1843 else if (
lhs.index() !=
rhs.index())
1845 return lhs.index() <=>
rhs.index();
1852 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
integral_constant
Definition type_traits_generator.h:871
static bool is_supported_type()
Definition variant_legacy.h:878
~variant()
Destructor.
Definition variant_legacy.h:229
bool is_same_type(const variant &other) const
Definition variant_legacy.h:661
T & get()
Definition variant_legacy.h:753
variant & operator=(const T &value)
Definition variant_legacy.h:616
bool is_type() const
Definition variant_legacy.h:726
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
Definition variant_legacy.h:146
Definition variant_legacy.h:99
etl::monostate monostate
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:1148
T & get(array< T, MAXN > &a)
Definition array.h:1174
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1160
bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1109
void swap(etl::array< T, SIZE > &lhs, etl::array< T, SIZE > &rhs)
Template deduction guides.
Definition array.h:1085
bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1097
ETL_NODISCARD ETL_CONSTEXPR14 T round_half_even_unscaled(T value) ETL_NOEXCEPT
Definition scaled_rounding.h:314
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1121
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1136
Definition type_traits_generator.h:2168
A 'no-value' placeholder.
Definition monostate.h:42