Embedded Template Library 1.0
Loading...
Searching...
No Matches
variant_variadic.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2021 jwellbelove, Robin S�derholm
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#include "../platform.h"
32#include "../alignment.h"
33#include "../compare.h"
34#include "../error_handler.h"
35#include "../exception.h"
36#include "../initializer_list.h"
37#include "../integral_limits.h"
38#include "../largest.h"
39#include "../memory.h"
40#include "../monostate.h"
41#include "../nth_type.h"
42#include "../placement_new.h"
43#include "../static_assert.h"
44#include "../type_list.h"
45#include "../type_traits.h"
46#include "../utility.h"
47#include "../visitor.h"
48
49#include <stdint.h>
50#include <string.h>
51
52#if defined(ETL_COMPILER_KEIL)
53 #pragma diag_suppress 940
54 #pragma diag_suppress 111
55#endif
56
57#if ETL_CPP11_NOT_SUPPORTED
58 #if !defined(ETL_IN_UNIT_TEST)
59 #error NOT SUPPORTED FOR C++03 OR BELOW
60 #endif
61#else
62//*****************************************************************************
66//*****************************************************************************
67
68namespace etl
69{
70 namespace private_variant
71 {
72 //*******************************************
78 //*******************************************
79 template <size_t Index, typename... TTypes>
80 struct variant_operations;
81
82 // Base case: no types left.
83 template <size_t Index>
84 struct variant_operations<Index>
85 {
86 static void destroy(char*, size_t) {}
87 static void copy(char*, const char*, size_t) {}
88 static void move(char*, const char*, size_t) {}
89 };
90
91 // Recursive case.
92 template <size_t Index, typename THead, typename... TRest>
93 struct variant_operations<Index, THead, TRest...>
94 {
95 static void destroy(char* data, size_t type_id)
96 {
97 if (type_id == Index)
98 {
99 reinterpret_cast<const THead*>(data)->~THead();
100 }
101 else
102 {
103 variant_operations<Index + 1, TRest...>::destroy(data, type_id);
104 }
105 }
106
107 static void copy(char* dst, const char* src, size_t type_id)
108 {
109 if (type_id == Index)
110 {
111 copy_impl(dst, src, etl::integral_constant<bool, etl::is_copy_constructible<THead>::value>{});
112 }
113 else
114 {
115 variant_operations<Index + 1, TRest...>::copy(dst, src, type_id);
116 }
117 }
118
119 static void move(char* dst, const char* src, size_t type_id)
120 {
121 if (type_id == Index)
122 {
123 move_impl(dst, src, etl::integral_constant<bool, etl::is_move_constructible<THead>::value>{});
124 }
125 else
126 {
127 variant_operations<Index + 1, TRest...>::move(dst, src, type_id);
128 }
129 }
130
131 private:
132
133 static void copy_impl(char* dst, const char* src, etl::true_type)
134 {
135 ::new (dst) THead(*reinterpret_cast<const THead*>(src));
136 }
137
138 static void copy_impl(char*, const char*, etl::false_type) {}
139
140 static void move_impl(char* dst, const char* src, etl::true_type)
141 {
142 ::new (dst) THead(etl::move(*reinterpret_cast<THead*>(const_cast<char*>(src))));
143 }
144
145 static void move_impl(char*, const char*, etl::false_type) {}
146 };
147
148 //*******************************************
150 //*******************************************
151 template <typename... TTypes>
152 struct are_all_trivially_destructible : etl::conjunction<etl::is_trivially_destructible<TTypes>...>
153 {
154 };
155
156 //*******************************************
159 //*******************************************
160 template <typename... TTypes>
161 union variadic_union;
162
164 template <>
165 union variadic_union<>
166 {
167 constexpr variadic_union() ETL_NOEXCEPT {}
168 };
169
171 template <typename THead, typename... TRest>
172 union variadic_union<THead, TRest...>
173 {
174 THead head;
175 variadic_union<TRest...> tail;
176
177 constexpr variadic_union() ETL_NOEXCEPT
178 : tail()
179 {
180 }
181
182 // Constructor for head element (index 0).
183 template <typename T>
184 constexpr variadic_union(etl::in_place_index_t<0>, T&& value)
185 : head(etl::forward<T>(value))
186 {
187 }
188
189 // Constructor for tail elements (index > 0).
190 template <size_t Index, typename T>
191 constexpr variadic_union(etl::in_place_index_t<Index>, T&& value)
192 : tail(etl::in_place_index_t<Index - 1>{}, etl::forward<T>(value))
193 {
194 }
195 };
196
197 //*******************************************
199 //*******************************************
200 // Non-const lvalue reference
201 template <size_t Index, typename THead, typename... TRest>
202 ETL_CONSTEXPR14 typename etl::enable_if_t<(Index == 0), THead&> variadic_union_get(variadic_union<THead, TRest...>& u) ETL_NOEXCEPT
203 {
204 return u.head;
205 }
206
207 template <size_t Index, typename THead, typename... TRest>
208 ETL_CONSTEXPR14 typename etl::enable_if_t<(Index != 0), etl::nth_type_t<Index, THead, TRest...>&>
209 variadic_union_get(variadic_union<THead, TRest...>& u) ETL_NOEXCEPT
210 {
211 return variadic_union_get<Index - 1>(u.tail);
212 }
213
214 // Const lvalue reference
215 template <size_t Index, typename THead, typename... TRest>
216 constexpr typename etl::enable_if_t<(Index == 0), const THead&> variadic_union_get(const variadic_union<THead, TRest...>& u) ETL_NOEXCEPT
217 {
218 return u.head;
219 }
220
221 template <size_t Index, typename THead, typename... TRest>
222 constexpr typename etl::enable_if_t<(Index != 0), const etl::nth_type_t<Index, THead, TRest...>&>
223 variadic_union_get(const variadic_union<THead, TRest...>& u) ETL_NOEXCEPT
224 {
225 return variadic_union_get<Index - 1>(u.tail);
226 }
227
228 // Rvalue reference
229 template <size_t Index, typename THead, typename... TRest>
230 ETL_CONSTEXPR14 typename etl::enable_if_t<(Index == 0), THead&&> variadic_union_get(variadic_union<THead, TRest...>&& u) ETL_NOEXCEPT
231 {
232 return etl::move(u.head);
233 }
234
235 template <size_t Index, typename THead, typename... TRest>
236 ETL_CONSTEXPR14 typename etl::enable_if_t<(Index != 0), etl::nth_type_t<Index, THead, TRest...>&&>
237 variadic_union_get(variadic_union<THead, TRest...>&& u) ETL_NOEXCEPT
238 {
239 return variadic_union_get<Index - 1>(etl::move(u.tail));
240 }
241
242 // Const rvalue reference
243 template <size_t Index, typename THead, typename... TRest>
244 constexpr typename etl::enable_if_t<(Index == 0), const THead&&> variadic_union_get(const variadic_union<THead, TRest...>&& u) ETL_NOEXCEPT
245 {
246 return etl::move(u.head);
247 }
248
249 template <size_t Index, typename THead, typename... TRest>
250 constexpr typename etl::enable_if_t<(Index != 0), const etl::nth_type_t<Index, THead, TRest...>&&>
251 variadic_union_get(const variadic_union<THead, TRest...>&& u) ETL_NOEXCEPT
252 {
253 return variadic_union_get<Index - 1>(etl::move(u.tail));
254 }
255 } // namespace private_variant
256
258 constexpr size_t variant_npos = etl::integral_limits<size_t>::max;
259
260 //***********************************
261 // variant. Forward declaration
262 template <typename... TTypes>
263 class variant;
264
265 //***************************************************************************
267 //***************************************************************************
268 template <size_t Index, typename T>
269 struct variant_alternative;
270
271 template <size_t Index, typename... TTypes>
272 struct variant_alternative<Index, etl::variant<TTypes...> >
273 {
274 using type = etl::nth_type_t<Index, TTypes...>;
275 };
276
277 template <size_t Index, typename T>
278 struct variant_alternative<Index, const T>
279 {
280 using type = typename variant_alternative<Index, T>::type;
281 };
282
283 template <size_t Index, typename T>
284 using variant_alternative_t = typename variant_alternative<Index, T>::type;
285
286 //***********************************
287 // holds_alternative. Forward declaration
288 template <typename T, typename... TTypes>
289 ETL_CONSTEXPR14 bool holds_alternative(const etl::variant<TTypes...>& v) ETL_NOEXCEPT;
290
291 //***********************************
292 // get. Forward declarations
293 template <size_t Index, typename... VTypes>
294 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...> >& get(etl::variant<VTypes...>& v);
295
296 template <size_t Index, typename... VTypes>
297 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...> >&& get(etl::variant<VTypes...>&& v);
298
299 template <size_t Index, typename... VTypes>
300 ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<VTypes...> >& get(const etl::variant<VTypes...>& v);
301
302 template <size_t Index, typename... VTypes>
303 ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<VTypes...> >&& get(const etl::variant<VTypes...>&& v);
304
305 template <typename T, typename... VTypes>
306 ETL_CONSTEXPR14 T& get(etl::variant<VTypes...>& v);
307
308 template <typename T, typename... VTypes>
309 ETL_CONSTEXPR14 T&& get(etl::variant<VTypes...>&& v);
310
311 template <typename T, typename... VTypes>
312 ETL_CONSTEXPR14 const T& get(const etl::variant<VTypes...>& v);
313
314 template <typename T, typename... VTypes>
315 ETL_CONSTEXPR14 const T&& get(const etl::variant<VTypes...>&& v);
316
317 #if ETL_NOT_USING_CPP17
318 #include "variant_select_do_operator.h"
319 #include "variant_select_do_visitor.h"
320 #endif
321
322 constexpr bool operator>(etl::monostate, etl::monostate) ETL_NOEXCEPT
323 {
324 return false;
325 }
326 constexpr bool operator<(etl::monostate, etl::monostate) ETL_NOEXCEPT
327 {
328 return false;
329 }
330 constexpr bool operator!=(etl::monostate, etl::monostate) ETL_NOEXCEPT
331 {
332 return false;
333 }
334 constexpr bool operator<=(etl::monostate, etl::monostate) ETL_NOEXCEPT
335 {
336 return true;
337 }
338 constexpr bool operator>=(etl::monostate, etl::monostate) ETL_NOEXCEPT
339 {
340 return true;
341 }
342 constexpr bool operator==(etl::monostate, etl::monostate) ETL_NOEXCEPT
343 {
344 return true;
345 }
346 #if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
347 constexpr std::strong_ordering operator<=>(monostate, monostate) ETL_NOEXCEPT
348 {
349 return std::strong_ordering::equal;
350 }
351 #endif
352
353 #if ETL_NOT_USING_STL && !defined(ETL_USE_TYPE_TRAITS_BUILTINS)
354 template <>
355 struct is_copy_constructible<etl::monostate> : public etl::true_type
356 {
357 };
358
359 template <>
360 struct is_move_constructible<etl::monostate> : public etl::true_type
361 {
362 };
363 #endif
364
365 //***************************************************************************
368 //***************************************************************************
369 class variant_exception : public exception
370 {
371 public:
372
373 variant_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
374 : exception(reason_, file_name_, line_number_)
375 {
376 }
377 };
378
379 //***************************************************************************
382 //***************************************************************************
384 {
385 public:
386
387 variant_incorrect_type_exception(string_type file_name_, numeric_type line_number_)
388 : variant_exception(ETL_ERROR_TEXT("variant:unsupported type", ETL_VARIANT_FILE_ID"A"), file_name_, line_number_)
389 {
390 }
391 };
392
393 //***************************************************************************
396 //***************************************************************************
398 {
399 public:
400
401 bad_variant_access(string_type file_name_, numeric_type line_number_)
402 : variant_exception(ETL_ERROR_TEXT("variant:bad variant access", ETL_VARIANT_FILE_ID"B"), file_name_, line_number_)
403 {
404 }
405 };
406
407 namespace private_variant
408 {
409 //***************************************************************************
413 //***************************************************************************
414 template <bool IsAllTriviallyDestructible, typename... TTypes>
415 struct variant_base
416 {
417 using largest_t = typename largest_type<TTypes...>::type;
418 static const size_t Size = sizeof(largest_t);
419 static const size_t Alignment = etl::largest_alignment<TTypes...>::value;
420
421 etl::uninitialized_buffer<Size, 1U, Alignment> data;
422 size_t type_id;
423
424 ETL_CONSTEXPR14 variant_base() noexcept
425 : type_id(variant_npos)
426 {
427 }
428
429 ETL_CONSTEXPR14 variant_base(size_t id) noexcept
430 : type_id(id)
431 {
432 }
433
434 ~variant_base()
435 {
436 if (type_id != variant_npos)
437 {
438 variant_operations<0, TTypes...>::destroy(data, type_id);
439 }
440 type_id = variant_npos;
441 }
442 };
443
444 //***************************************************************************
450 //***************************************************************************
451 template <typename... TTypes>
452 struct variant_base<true, TTypes...>
453 {
454 variadic_union<TTypes...> data;
455 size_t type_id;
456
457 constexpr variant_base() noexcept
458 : data()
459 , type_id(variant_npos)
460 {
461 }
462
463 constexpr variant_base(size_t id) noexcept
464 : data()
465 , type_id(id)
466 {
467 }
468
469 template <size_t Index, typename T>
470 constexpr variant_base(etl::in_place_index_t<Index>, T&& value,
471 size_t id) noexcept(etl::is_nothrow_constructible<etl::nth_type_t<Index, TTypes...>, T>::value)
472 : data(etl::in_place_index_t<Index>{}, etl::forward<T>(value))
473 , type_id(id)
474 {
475 }
476
477 ~variant_base() = default;
478 };
479 } // namespace private_variant
480
481 //***************************************************************************
484 //***************************************************************************
485 template <typename... TTypes>
486 class variant : private private_variant::variant_base<private_variant::are_all_trivially_destructible<TTypes...>::value, TTypes...>
487 {
488 using base_type = private_variant::variant_base<private_variant::are_all_trivially_destructible<TTypes...>::value, TTypes...>;
489
490 static constexpr bool Is_Trivially_Destructible_Suite = private_variant::are_all_trivially_destructible<TTypes...>::value;
491
492 public:
493
494 using type_list = etl::type_list<TTypes...>;
495
496 //***************************************************************************
498 //***************************************************************************
499 template <size_t Index, typename... VTypes>
500 friend ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...> >& get(etl::variant<VTypes...>& v);
501
502 template <size_t Index, typename... VTypes>
503 friend ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...> >&& get(etl::variant<VTypes...>&& v);
504
505 template <size_t Index, typename... VTypes>
506 friend ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<VTypes...> >& get(const etl::variant<VTypes...>& v);
507
508 template <size_t Index, typename... VTypes>
509 friend ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<VTypes...> >&& get(const etl::variant<VTypes...>&& v);
510
511 template <typename T, typename... VTypes>
512 friend ETL_CONSTEXPR14 T& get(etl::variant<VTypes...>& v);
513
514 template <typename T, typename... VTypes>
515 friend ETL_CONSTEXPR14 T&& get(etl::variant<VTypes...>&& v);
516
517 template <typename T, typename... VTypes>
518 friend ETL_CONSTEXPR14 const T& get(const etl::variant<VTypes...>& v);
519
520 template <typename T, typename... VTypes>
521 friend ETL_CONSTEXPR14 const T&& get(const etl::variant<VTypes...>&& v);
522
523 template < class T, typename... VTypes >
524 friend ETL_CONSTEXPR14 etl::add_pointer_t<T> get_if(etl::variant<VTypes...>* pv) ETL_NOEXCEPT;
525
526 template < class T, typename... VTypes >
527 friend ETL_CONSTEXPR14 etl::add_pointer_t<const T> get_if(const etl::variant<VTypes...>* pv) ETL_NOEXCEPT;
528
529 private:
530
531 //*******************************************
532 // Get the index of a type.
533 //*******************************************
534 template <typename T>
535 using index_of_type = etl::type_list_index_of_type<etl::type_list<TTypes...>, etl::remove_cvref_t<T> >;
536
537 //*******************************************
538 // Get the type from the index.
539 //*******************************************
540 template <size_t Index>
541 using type_from_index = typename etl::type_list_type_at_index<etl::type_list<TTypes...>, Index>::type;
542
543 //*******************************************
544 // Bring base members into scope.
545 //*******************************************
546 using base_type::data;
547 using base_type::type_id;
548
549 public:
550
551 //***************************************************************************
554 //***************************************************************************
556 template <bool Trivial = Is_Trivially_Destructible_Suite, etl::enable_if_t<!Trivial, int> = 0>
557 ETL_CONSTEXPR14 variant() noexcept(etl::is_nothrow_default_constructible<type_from_index<0U> >::value)
558 {
559 using type = type_from_index<0U>;
560
561 default_construct_in_place<type>(data);
562 type_id = 0U;
563 }
564
565 template <bool Trivial = Is_Trivially_Destructible_Suite, etl::enable_if_t<Trivial, int> = 0>
566 constexpr variant() noexcept(etl::is_nothrow_default_constructible<type_from_index<0U> >::value)
567 : base_type(etl::in_place_index_t<0>{}, type_from_index<0U>{}, 0U)
568 {
569 }
570 #include "diagnostic_pop.h"
571
572 //***************************************************************************
574 //***************************************************************************
576 template <typename T, bool Trivial_ = Is_Trivially_Destructible_Suite,
577 etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value && !Trivial_, int> = 0>
578 ETL_CONSTEXPR14 variant(T&& value)
579 : base_type(index_of_type<T>::value)
580 {
581 static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
582
583 construct_in_place<etl::remove_cvref_t<T> >(data, etl::forward<T>(value));
584 }
585
586 template <typename T, bool Trivial_ = Is_Trivially_Destructible_Suite,
587 etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value && Trivial_, int> = 0>
588 constexpr variant(T&& value)
589 : base_type(etl::in_place_index_t<index_of_type<T>::value>{}, etl::forward<T>(value), index_of_type<T>::value)
590 {
591 static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
592 }
593 #include "diagnostic_pop.h"
594
595 //***************************************************************************
597 //***************************************************************************
599 template <typename T, typename... TArgs, bool Trivial_ = Is_Trivially_Destructible_Suite, etl::enable_if_t<!Trivial_, int> = 0>
600 ETL_CONSTEXPR14 explicit variant(etl::in_place_type_t<T>, TArgs&&... args)
601 : base_type(index_of_type<T>::value)
602 {
603 static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
604
605 construct_in_place_args<etl::remove_cvref_t<T> >(data, etl::forward<TArgs>(args)...);
606 }
607
608 template <typename T, typename... TArgs, bool Trivial_ = Is_Trivially_Destructible_Suite, etl::enable_if_t<Trivial_, int> = 0>
609 constexpr explicit variant(etl::in_place_type_t<T>, TArgs&&... args)
610 : base_type(etl::in_place_index_t<index_of_type<T>::value>{}, etl::remove_cvref_t<T>(etl::forward<TArgs>(args)...), index_of_type<T>::value)
611 {
612 static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
613 }
614 #include "diagnostic_pop.h"
615
616 //***************************************************************************
618 //***************************************************************************
620 template <size_t Index, typename... TArgs, bool Trivial_ = Is_Trivially_Destructible_Suite, etl::enable_if_t<!Trivial_, int> = 0>
621 ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t<Index>, TArgs&&... args)
622 : base_type(Index)
623 {
624 using type = type_from_index<Index>;
625 static_assert(etl::is_one_of<type, TTypes...>::value, "Unsupported type");
626
627 construct_in_place_args<type>(data, etl::forward<TArgs>(args)...);
628 }
629
630 template <size_t Index, typename... TArgs, bool Trivial_ = Is_Trivially_Destructible_Suite, etl::enable_if_t<Trivial_, int> = 0>
631 constexpr explicit variant(etl::in_place_index_t<Index>, TArgs&&... args)
632 : base_type(etl::in_place_index_t<Index>{}, type_from_index<Index>(etl::forward<TArgs>(args)...), Index)
633 {
634 using type = type_from_index<Index>;
635 static_assert(etl::is_one_of<type, TTypes...>::value, "Unsupported type");
636 }
637 #include "diagnostic_pop.h"
638
639 #if ETL_HAS_INITIALIZER_LIST
640 //***************************************************************************
642 //***************************************************************************
644 template <typename T, typename U, typename... TArgs >
645 ETL_CONSTEXPR14 explicit variant(etl::in_place_type_t<T>, std::initializer_list<U> init, TArgs&&... args)
646 : base_type(index_of_type<T>::value)
647 {
648 static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
649
650 construct_in_place_args<etl::remove_cvref_t<T> >(data, init, etl::forward<TArgs>(args)...);
651 }
652 #include "diagnostic_pop.h"
653
654 //***************************************************************************
656 //***************************************************************************
658 template <size_t Index, typename U, typename... TArgs >
659 ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t<Index>, std::initializer_list<U> init, TArgs&&... args)
660 : base_type(Index)
661 {
662 using type = type_from_index<Index>;
663 static_assert(etl::is_one_of<type, TTypes...>::value, "Unsupported type");
664
665 construct_in_place_args<type>(data, init, etl::forward<TArgs>(args)...);
666 }
667 #include "diagnostic_pop.h"
668 #endif
669
670 //***************************************************************************
673 //***************************************************************************
675 ETL_CONSTEXPR14 variant(const variant& other) noexcept(etl::conjunction<etl::is_nothrow_copy_constructible<TTypes>...>::value)
676 : base_type(other.type_id)
677 {
678 if (other.index() != variant_npos)
679 {
680 do_copy_from(other, etl::integral_constant<bool, Is_Trivially_Destructible_Suite>{});
681 }
682 }
683 #include "diagnostic_pop.h"
684
685 //***************************************************************************
688 //***************************************************************************
690 ETL_CONSTEXPR14 variant(variant&& other) noexcept(etl::conjunction<etl::is_nothrow_move_constructible<TTypes>...>::value)
691 : base_type(other.type_id)
692 {
693 if (other.index() != variant_npos)
694 {
695 do_move_from(other, etl::integral_constant<bool, Is_Trivially_Destructible_Suite>{});
696 }
697 }
698 #include "diagnostic_pop.h"
699
700 //***************************************************************************
704 //***************************************************************************
705 // ~variant() is provided by base_type
706
707 //***************************************************************************
709 //***************************************************************************
710 template <typename T, typename... TArgs>
711 T& emplace(TArgs&&... args) ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<etl::remove_cvref_t<T>, TArgs...>::value))
712 {
713 static_assert(etl::is_one_of<T, TTypes...>::value, "Unsupported type");
714
715 using type = etl::remove_cvref_t<T>;
716
717 do_destroy();
718 do_emplace<type>(etl::forward<TArgs>(args)...);
719
720 type_id = index_of_type<T>::value;
721
722 return get_value<index_of_type<T>::value>();
723 }
724
725 #if ETL_HAS_INITIALIZER_LIST
726 //***************************************************************************
728 //***************************************************************************
729 template <typename T, typename U, typename... TArgs>
730 T& emplace(std::initializer_list<U> il, TArgs&&... args)
731 ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<etl::remove_cvref_t<T>, std::initializer_list<U>, TArgs...>::value))
732 {
733 static_assert(etl::is_one_of<T, TTypes...>::value, "Unsupported type");
734
735 using type = etl::remove_cvref_t<T>;
736
737 do_destroy();
738 do_emplace<type>(il, etl::forward<TArgs>(args)...);
739
740 type_id = index_of_type<T>::value;
741
742 return get_value<index_of_type<T>::value>();
743 }
744 #endif
745
746 //***************************************************************************
748 //***************************************************************************
749 template <size_t Index, typename... TArgs>
750 typename etl::variant_alternative_t<Index, variant<TTypes...> >& emplace(TArgs&&... args)
751 ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<type_from_index<Index>, TArgs...>::value))
752 {
753 static_assert(Index < sizeof...(TTypes), "Index out of range");
754
755 using type = type_from_index<Index>;
756
757 do_destroy();
758 do_emplace<type>(etl::forward<TArgs>(args)...);
759
760 type_id = Index;
761
762 return get_value<Index>();
763 }
764
765 #if ETL_HAS_INITIALIZER_LIST
766 //***************************************************************************
768 //***************************************************************************
769 template <size_t Index, typename U, typename... TArgs>
770 typename etl::variant_alternative_t<Index, variant<TTypes...> >& emplace(std::initializer_list<U> il, TArgs&&... args)
771 ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<type_from_index<Index>, std::initializer_list<U>, TArgs...>::value))
772 {
773 static_assert(Index < sizeof...(TTypes), "Index out of range");
774
775 using type = type_from_index<Index>;
776
777 do_destroy();
778 do_emplace<type>(il, etl::forward<TArgs>(args)...);
779
780 type_id = Index;
781
782 return get_value<Index>();
783 }
784 #endif
785
786 //***************************************************************************
789 //***************************************************************************
790 template <typename T, etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value, int> = 0>
791 variant& operator=(T&& value)
792 {
793 using type = etl::remove_cvref_t<T>;
794
795 static_assert(etl::is_one_of<type, TTypes...>::value, "Unsupported type");
796
797 do_destroy();
798 do_construct<type>(etl::forward<T>(value));
799
800 type_id = index_of_type<type>::value;
801
802 return *this;
803 }
804
805 //***************************************************************************
808 //***************************************************************************
809 variant& operator=(const variant& other) ETL_NOEXCEPT_IF((etl::conjunction<etl::is_nothrow_copy_constructible<TTypes>...>::value))
810 {
811 if (this != &other)
812 {
813 if (other.index() == variant_npos)
814 {
815 type_id = variant_npos;
816 }
817 else
818 {
819 do_destroy();
820
822
823 type_id = other.type_id;
824 }
825 }
826
827 return *this;
828 }
829
830 //***************************************************************************
833 //***************************************************************************
834 variant& operator=(variant&& other) ETL_NOEXCEPT_IF((etl::conjunction<etl::is_nothrow_move_constructible<TTypes>...>::value))
835 {
836 if (this != &other)
837 {
838 if (other.index() == variant_npos)
839 {
840 type_id = variant_npos;
841 }
842 else
843 {
844 do_destroy();
845
847
848 type_id = other.type_id;
849 }
850 }
851
852 return *this;
853 }
854
855 //***************************************************************************
858 //***************************************************************************
859 constexpr bool valueless_by_exception() const ETL_NOEXCEPT
860 {
861 return type_id == variant_npos;
862 }
863
864 //***************************************************************************
866 //***************************************************************************
867 constexpr size_t index() const ETL_NOEXCEPT
868 {
869 return type_id;
870 }
871
872 //***************************************************************************
876 //***************************************************************************
877 template <typename T>
878 static constexpr bool is_supported_type()
879 {
880 return etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value;
881 }
882
883 //***************************************************************************
887 //***************************************************************************
888 template <typename T, etl::enable_if_t<is_supported_type<T>(), int> = 0>
889 constexpr bool is_type() const ETL_NOEXCEPT
890 {
891 return (type_id == index_of_type<T>::value);
892 }
893
894 //***************************************************************************
895 template <typename T, etl::enable_if_t<!is_supported_type<T>(), int> = 0>
896 constexpr bool is_type() const ETL_NOEXCEPT
897 {
898 return false;
899 }
900
901 //***************************************************************************
906 //***************************************************************************
907 constexpr bool is_same_type(const variant& other) const
908 {
909 return type_id == other.type_id;
910 }
911
912 //***************************************************************************
914 //***************************************************************************
915 void swap(variant& rhs) ETL_NOEXCEPT
916 {
917 variant temp(etl::move(*this));
918 *this = etl::move(rhs);
919 rhs = etl::move(temp);
920 }
921
922 //***************************************************************************
924 //***************************************************************************
925 template <typename TVisitor>
926 etl::enable_if_t<etl::is_visitor<TVisitor>::value, void> accept(TVisitor& v)
927 {
928 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
929 do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
930 #else
931 do_visitor<sizeof...(TTypes)>(v);
932 #endif
933 }
934
935 //***************************************************************************
937 //***************************************************************************
938 template <typename TVisitor>
939 etl::enable_if_t<etl::is_visitor<TVisitor>::value, void> accept(TVisitor& v) const
940 {
941 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
942 do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
943 #else
944 do_visitor<sizeof...(TTypes)>(v);
945 #endif
946 }
947
948 //***************************************************************************
950 //***************************************************************************
951 template <typename TVisitor>
952 etl::enable_if_t<!etl::is_visitor<TVisitor>::value, void> accept(TVisitor& v)
953 {
954 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
955 do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
956 #else
957 do_operator<sizeof...(TTypes)>(v);
958 #endif
959 }
960
961 //***************************************************************************
963 //***************************************************************************
964 template <typename TVisitor>
965 etl::enable_if_t<!etl::is_visitor<TVisitor>::value, void> accept(TVisitor& v) const
966 {
967 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
968 do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
969 #else
970 do_operator<sizeof...(TTypes)>(v);
971 #endif
972 }
973
974 //***************************************************************************
977 //***************************************************************************
978 template <typename TVisitor>
979 #if !defined(ETL_IN_UNIT_TEST)
980 ETL_DEPRECATED_REASON("Replace with accept()")
981 #endif
982 void
983 accept_visitor(TVisitor& v)
984 {
985 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
986 do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
987 #else
988 do_visitor<sizeof...(TTypes)>(v);
989 #endif
990 }
991
992 //***************************************************************************
995 //***************************************************************************
996 template <typename TVisitor>
997 #if !defined(ETL_IN_UNIT_TEST)
998 ETL_DEPRECATED_REASON("Replace with accept()")
999 #endif
1000 void
1001 accept_visitor(TVisitor& v) const
1002 {
1003 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1004 do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
1005 #else
1006 do_visitor<sizeof...(TTypes)>(v);
1007 #endif
1008 }
1009
1010 //***************************************************************************
1013 //***************************************************************************
1014 template <typename TVisitor>
1015 #if !defined(ETL_IN_UNIT_TEST)
1016 ETL_DEPRECATED_REASON("Replace with accept()")
1017 #endif
1018 void
1019 accept_functor(TVisitor& v)
1020 {
1021 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1022 do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
1023 #else
1024 do_operator<sizeof...(TTypes)>(v);
1025 #endif
1026 }
1027
1028 //***************************************************************************
1031 //***************************************************************************
1032 template <typename TVisitor>
1033 #if !defined(ETL_IN_UNIT_TEST)
1034 ETL_DEPRECATED_REASON("Replace with accept()")
1035 #endif
1036 void
1037 accept_functor(TVisitor& v) const
1038 {
1039 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1040 do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
1041 #else
1042 do_operator<sizeof...(TTypes)>(v);
1043 #endif
1044 }
1045
1046 private:
1047
1048 //***************************************************************************
1050 //***************************************************************************
1051 template <typename T, typename U>
1052 static void construct_in_place(char* pstorage, U&& value)
1053 {
1054 using type = etl::remove_cvref_t<T>;
1055
1056 ::new (pstorage) type(etl::forward<U>(value));
1057 }
1058
1059 //***************************************************************************
1061 //***************************************************************************
1062 template <typename T, typename... TArgs>
1063 static void construct_in_place_args(char* pstorage, TArgs&&... args)
1064 {
1065 using type = etl::remove_cvref_t<T>;
1066
1067 ::new (pstorage) type(etl::forward<TArgs>(args)...);
1068 }
1069
1070 //***************************************************************************
1072 //***************************************************************************
1073 template <typename T>
1074 static void default_construct_in_place(char* pstorage) ETL_NOEXCEPT_IF((etl::is_nothrow_default_constructible<etl::remove_cvref_t<T> >::value))
1075 {
1076 using type = etl::remove_cvref_t<T>;
1077
1078 ::new (pstorage) type();
1079 }
1080
1081 //***************************************************************************
1083 //***************************************************************************
1084 void do_destroy()
1085 {
1087 }
1088
1089 void do_destroy_impl(etl::integral_constant<bool, true>)
1090 {
1091 // Trivially destructible: no-op.
1092 }
1093
1094 void do_destroy_impl(etl::integral_constant<bool, false>)
1095 {
1096 private_variant::variant_operations<0, TTypes...>::destroy(data, type_id);
1097 }
1098
1099 //***************************************************************************
1102 //***************************************************************************
1103 template <typename T, typename... TArgs>
1104 void do_emplace(TArgs&&... args)
1105 {
1106 do_emplace_impl<T>(etl::integral_constant<bool, Is_Trivially_Destructible_Suite>{}, etl::forward<TArgs>(args)...);
1107 }
1108
1109 // Trivially destructible suite: storage is a variadic_union. The old member is
1110 // trivially destructible, so placement-new of the new member is well-defined at
1111 // runtime (emplace is not constexpr, so placement-new is permitted here).
1112 template <typename T, typename... TArgs>
1113 void do_emplace_impl(etl::integral_constant<bool, true>, TArgs&&... args)
1114 {
1115 ::new (static_cast<void*>(etl::addressof(private_variant::variadic_union_get<index_of_type<T>::value>(data)))) T(etl::forward<TArgs>(args)...);
1116 }
1117
1118 // Non-trivially destructible suite: storage is an uninitialized_buffer.
1119 template <typename T, typename... TArgs>
1120 void do_emplace_impl(etl::integral_constant<bool, false>, TArgs&&... args)
1121 {
1122 ::new (static_cast<char*>(data)) T(etl::forward<TArgs>(args)...);
1123 }
1124
1125 //***************************************************************************
1127 //***************************************************************************
1128 template <typename T, typename U>
1129 void do_construct(U&& value)
1130 {
1131 do_construct_impl<T>(etl::forward<U>(value), etl::integral_constant<bool, Is_Trivially_Destructible_Suite>{});
1132 }
1133
1134 template <typename T, typename U>
1135 void do_construct_impl(U&& value, etl::integral_constant<bool, true>)
1136 {
1137 // Begin the lifetime of the new alternative via placement new. The target
1138 // union member is not alive after do_destroy(), and the alternative may be
1139 // non-assignable (e.g. reference or const members), so assignment would be
1140 // both undefined behaviour and ill-formed for such types. Use etl::addressof
1141 // so the raw storage address is used even for types that overload operator&.
1142 ::new (static_cast<void*>(etl::addressof(private_variant::variadic_union_get<index_of_type<T>::value>(data)))) T(etl::forward<U>(value));
1143 }
1144
1145 template <typename T, typename U>
1146 void do_construct_impl(U&& value, etl::integral_constant<bool, false>)
1147 {
1148 // Non-trivially destructible: use placement new.
1149 ::new (static_cast<char*>(data)) T(etl::forward<U>(value));
1150 }
1151
1152 //***************************************************************************
1154 //***************************************************************************
1155 void do_copy_from(const variant& other, etl::integral_constant<bool, true>)
1156 {
1157 // Trivially destructible: copy via memcpy to avoid issues with non-trivial copy assignment in union.
1158 memcpy(static_cast<void*>(&data), static_cast<const void*>(&other.data), sizeof(data));
1159 }
1160
1161 void do_copy_from(const variant& other, etl::integral_constant<bool, false>)
1162 {
1163 // Non-trivially destructible: use switch-based dispatch.
1164 private_variant::variant_operations<0, TTypes...>::copy(data, other.data, other.type_id);
1165 }
1166
1167 //***************************************************************************
1169 //***************************************************************************
1170 void do_move_from(variant& other, etl::integral_constant<bool, true>)
1171 {
1172 // Trivially destructible: copy via memcpy (trivial move == copy).
1173 memcpy(static_cast<void*>(&data), static_cast<const void*>(&other.data), sizeof(data));
1174 }
1175
1176 void do_move_from(variant& other, etl::integral_constant<bool, false>)
1177 {
1178 // Non-trivially destructible: use switch-based dispatch.
1179 private_variant::variant_operations<0, TTypes...>::move(data, other.data, other.type_id);
1180 }
1181
1182 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1183 //***************************************************************************
1185 //***************************************************************************
1186 template <typename TVisitor, size_t... I>
1187 void do_visitor(TVisitor& visitor, etl::index_sequence<I...>)
1188 {
1189 (attempt_visitor<I>(visitor) || ...);
1190 }
1191
1192 //***************************************************************************
1194 //***************************************************************************
1195 template <typename TVisitor, size_t... I>
1196 void do_visitor(TVisitor& visitor, etl::index_sequence<I...>) const
1197 {
1198 (attempt_visitor<I>(visitor) || ...);
1199 }
1200 #else
1201 //***************************************************************************
1203 //***************************************************************************
1204 template <size_t NTypes, typename TVisitor>
1205 void do_visitor(TVisitor& visitor)
1206 {
1207 etl::private_variant::select_do_visitor<NTypes>::do_visitor(*this, visitor);
1208 }
1209
1210 //***************************************************************************
1212 //***************************************************************************
1213 template <size_t NTypes, typename TVisitor>
1214 void do_visitor(TVisitor& visitor) const
1215 {
1216 etl::private_variant::select_do_visitor<NTypes>::do_visitor(*this, visitor);
1217 }
1218 #endif
1219
1220 //***************************************************************************
1222 //***************************************************************************
1223 template <size_t Index, typename TVisitor>
1224 bool attempt_visitor(TVisitor& visitor)
1225 {
1226 if (Index == index())
1227 {
1228 // Workaround for MSVC (2023/05/13)
1229 // It doesn't compile 'visitor.visit(etl::get<Index>(*this))' correctly for C++17 & C++20.
1230 // Changed all of the instances for consistency.
1231 auto& v = etl::get<Index>(*this);
1232 visitor.visit(v);
1233 return true;
1234 }
1235 else
1236 {
1237 return false;
1238 }
1239 }
1240
1241 //***************************************************************************
1243 //***************************************************************************
1244 template <size_t Index, typename TVisitor>
1245 bool attempt_visitor(TVisitor& visitor) const
1246 {
1247 if (Index == index())
1248 {
1249 // Workaround for MSVC (2023/05/13)
1250 // It doesn't compile 'visitor.visit(etl::get<Index>(*this))' correctly for C++17 & C++20.
1251 // Changed all of the instances for consistency.
1252 auto& v = etl::get<Index>(*this);
1253 visitor.visit(v);
1254 return true;
1255 }
1256 else
1257 {
1258 return false;
1259 }
1260 }
1261
1262 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1263 //***************************************************************************
1265 //***************************************************************************
1266 template <typename TVisitor, size_t... I>
1267 void do_operator(TVisitor& visitor, etl::index_sequence<I...>)
1268 {
1269 (attempt_operator<I>(visitor) || ...);
1270 }
1271
1272 //***************************************************************************
1274 //***************************************************************************
1275 template <typename TVisitor, size_t... I>
1276 void do_operator(TVisitor& visitor, etl::index_sequence<I...>) const
1277 {
1278 (attempt_operator<I>(visitor) || ...);
1279 }
1280 #else
1281 //***************************************************************************
1283 //***************************************************************************
1284 template <size_t NTypes, typename TVisitor>
1285 void do_operator(TVisitor& visitor)
1286 {
1287 #if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1288 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 8U, "ETL_VARIANT_CPP11_MAX_8_TYPES - Only a maximum of 8 types are allowed in this variant");
1289 #endif
1290
1291 #if defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1292 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 16U, "ETL_VARIANT_CPP11_MAX_16_TYPES - Only a maximum of 16 types are allowed in this variant");
1293 #endif
1294
1295 #if defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1296 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 24U, "ETL_VARIANT_CPP11_MAX_24_TYPES - Only a maximum of 24 types are allowed in this variant");
1297 #endif
1298
1299 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 32U, "A maximum of 32 types are allowed in this variant");
1300
1301 etl::private_variant::select_do_operator<NTypes>::do_operator(*this, visitor);
1302 }
1303
1304 //***************************************************************************
1306 //***************************************************************************
1307 template <size_t NTypes, typename TVisitor>
1308 void do_operator(TVisitor& visitor) const
1309 {
1310 #if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1311 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 8U, "ETL_VARIANT_CPP11_MAX_8_TYPES - Only a maximum of 8 types are allowed in this variant");
1312 #endif
1313
1314 #if defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1315 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 16U, "ETL_VARIANT_CPP11_MAX_16_TYPES - Only a maximum of 16 types are allowed in this variant");
1316 #endif
1317
1318 #if defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1319 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 24U, "ETL_VARIANT_CPP11_MAX_24_TYPES - Only a maximum of 24 types are allowed in this variant");
1320 #endif
1321
1322 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 32U, "A maximum of 32 types are allowed in this variant");
1323
1324 etl::private_variant::select_do_operator<NTypes>::do_operator(*this, visitor);
1325 }
1326 #endif
1327
1328 //***************************************************************************
1330 //***************************************************************************
1331 template <size_t Index, typename TVisitor>
1332 bool attempt_operator(TVisitor& visitor)
1333 {
1334 if (Index == index())
1335 {
1336 auto& v = etl::get<Index>(*this);
1337 visitor(v);
1338 return true;
1339 }
1340 else
1341 {
1342 return false;
1343 }
1344 }
1345
1346 //***************************************************************************
1348 //***************************************************************************
1349 template <size_t Index, typename TVisitor>
1350 bool attempt_operator(TVisitor& visitor) const
1351 {
1352 if (Index == index())
1353 {
1354 auto& v = etl::get<Index>(*this);
1355 visitor(v);
1356 return true;
1357 }
1358 else
1359 {
1360 return false;
1361 }
1362 }
1363
1364 //***************************************************************************
1368 //***************************************************************************
1369 template <size_t Index>
1370 ETL_CONSTEXPR14 type_from_index<Index>& get_value() ETL_NOEXCEPT
1371 {
1373 }
1374
1375 template <size_t Index>
1376 constexpr const type_from_index<Index>& get_value() const ETL_NOEXCEPT
1377 {
1379 }
1380
1381 // Trivially destructible: use variadic_union accessor
1382 template <size_t Index>
1383 ETL_CONSTEXPR14 type_from_index<Index>& get_value_impl(etl::integral_constant<bool, true>) ETL_NOEXCEPT
1384 {
1385 return private_variant::variadic_union_get<Index>(data);
1386 }
1387
1388 template <size_t Index>
1389 constexpr const type_from_index<Index>& get_value_impl(etl::integral_constant<bool, true>) const ETL_NOEXCEPT
1390 {
1391 return private_variant::variadic_union_get<Index>(data);
1392 }
1393
1394 // Non-trivially destructible: use pointer cast on uninitialized_buffer
1395 template <size_t Index>
1396 ETL_CONSTEXPR14 type_from_index<Index>& get_value_impl(etl::integral_constant<bool, false>) ETL_NOEXCEPT
1397 {
1398 return *static_cast<type_from_index<Index>*>(data);
1399 }
1400
1401 template <size_t Index>
1402 ETL_CONSTEXPR14 const type_from_index<Index>& get_value_impl(etl::integral_constant<bool, false>) const ETL_NOEXCEPT
1403 {
1404 return *static_cast<const type_from_index<Index>*>(data);
1405 }
1406
1407 //***************************************************************************
1409 //***************************************************************************
1410 template <typename T>
1411 ETL_CONSTEXPR14 T* get_value_ptr() ETL_NOEXCEPT
1412 {
1414 }
1415
1416 template <typename T>
1417 constexpr const T* get_value_ptr() const ETL_NOEXCEPT
1418 {
1420 }
1421
1422 // Trivially destructible: use variadic_union accessor
1423 template <typename T>
1424 ETL_CONSTEXPR14 T* get_value_ptr_impl(etl::integral_constant<bool, true>) ETL_NOEXCEPT
1425 {
1426 return &private_variant::variadic_union_get<index_of_type<T>::value>(data);
1427 }
1428
1429 template <typename T>
1430 constexpr const T* get_value_ptr_impl(etl::integral_constant<bool, true>) const ETL_NOEXCEPT
1431 {
1432 return &private_variant::variadic_union_get<index_of_type<T>::value>(data);
1433 }
1434
1435 // Non-trivially destructible: use pointer cast on uninitialized_buffer
1436 template <typename T>
1437 ETL_CONSTEXPR14 T* get_value_ptr_impl(etl::integral_constant<bool, false>) ETL_NOEXCEPT
1438 {
1439 return static_cast<T*>(data);
1440 }
1441
1442 template <typename T>
1443 ETL_CONSTEXPR14 const T* get_value_ptr_impl(etl::integral_constant<bool, false>) const ETL_NOEXCEPT
1444 {
1445 return static_cast<const T*>(data);
1446 }
1447
1448 // data and type_id are inherited from base_type.
1449 // operation is inherited only for non-trivially destructible variants.
1450 };
1451
1452 namespace private_variant
1453 {
1454 //***************************************************************************
1457 //***************************************************************************
1458 template <typename T, typename T0, typename T1, typename... Ts>
1459 typename etl::enable_if_t<etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t index) ETL_NOEXCEPT;
1460
1461 template <typename T, typename T0>
1462 typename etl::enable_if_t<etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t index) ETL_NOEXCEPT;
1463
1464 template <typename T, typename T0, typename T1, typename... Ts>
1465 typename etl::enable_if_t<!etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t index) ETL_NOEXCEPT;
1466
1467 template <typename T, typename T0>
1468 typename etl::enable_if_t<!etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t index) ETL_NOEXCEPT;
1469
1470 template <typename T, typename T0, typename T1, typename... Ts>
1471 typename etl::enable_if_t<etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t index) ETL_NOEXCEPT
1472 {
1473 if (index == 0)
1474 {
1475 return true;
1476 }
1477 else
1478 {
1479 return is_same_type_in<T, T1, Ts...>(index - 1);
1480 }
1481 }
1482
1483 template <typename T, typename T0>
1484 typename etl::enable_if_t<etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t index) ETL_NOEXCEPT
1485 {
1486 return index == 0;
1487 }
1488
1489 template <typename T, typename T0, typename T1, typename... Ts>
1490 typename etl::enable_if_t<!etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t index) ETL_NOEXCEPT
1491 {
1492 if (index == 0)
1493 {
1494 return false;
1495 }
1496 else
1497 {
1498 return is_same_type_in<T, T1, Ts...>(index - 1);
1499 }
1500 }
1501
1502 template <typename T, typename T0>
1503 typename etl::enable_if_t<!etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t) ETL_NOEXCEPT
1504 {
1505 return false;
1506 }
1507 } // namespace private_variant
1508
1509 //***************************************************************************
1511 //***************************************************************************
1512 template <typename T, typename... TTypes>
1513 ETL_CONSTEXPR14 bool holds_alternative(const etl::variant<TTypes...>& v) ETL_NOEXCEPT
1514 {
1515 return private_variant::is_same_type_in<T, TTypes...>(v.index());
1516 }
1517
1518 //***************************************************************************
1520 //***************************************************************************
1521 template <size_t Index, typename... TTypes>
1522 ETL_CONSTEXPR14 bool holds_alternative(const etl::variant<TTypes...>& v) ETL_NOEXCEPT
1523 {
1524 return (Index == v.index());
1525 }
1526
1527 //***************************************************************************
1529 //***************************************************************************
1530 template <typename... TTypes>
1531 ETL_CONSTEXPR14 bool holds_alternative(size_t index, const etl::variant<TTypes...>& v) ETL_NOEXCEPT
1532 {
1533 return (index == v.index());
1534 }
1535
1536 //***************************************************************************
1538 //***************************************************************************
1539 template <size_t Index, typename... TTypes>
1540 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<TTypes...> >& get(etl::variant<TTypes...>& v)
1541 {
1542 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1543 static_assert(Index < sizeof...(TTypes), "Index out of range");
1544 #endif
1545
1546 ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1547
1548 return v.template get_value<Index>();
1549 }
1550
1551 //***********************************
1552 template <size_t Index, typename... TTypes>
1553 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<TTypes...> >&& get(etl::variant<TTypes...>&& v)
1554 {
1555 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1556 static_assert(Index < sizeof...(TTypes), "Index out of range");
1557 #endif
1558
1559 ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1560
1561 return etl::move(v.template get_value<Index>());
1562 }
1563
1564 //***********************************
1565 template <size_t Index, typename... TTypes>
1566 ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<TTypes...> >& get(const etl::variant<TTypes...>& v)
1567 {
1568 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1569 static_assert(Index < sizeof...(TTypes), "Index out of range");
1570 #endif
1571
1572 ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1573
1574 return v.template get_value<Index>();
1575 }
1576
1577 //***********************************
1578 template <size_t Index, typename... TTypes>
1579 ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<TTypes...> >&& get(const etl::variant<TTypes...>&& v)
1580 {
1581 #if ETL_USING_CPP17 & !defined(ETL_VARIANT_FORCE_CPP11)
1582 static_assert(Index < sizeof...(TTypes), "Index out of range");
1583 #endif
1584
1585 ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1586
1587 return etl::move(v.template get_value<Index>());
1588 }
1589
1590 //***********************************
1591 template <typename T, typename... TTypes>
1592 ETL_CONSTEXPR14 T& get(etl::variant<TTypes...>& v)
1593 {
1594 ETL_ASSERT((private_variant::is_same_type_in<T, TTypes...>(v.index())), ETL_ERROR(etl::variant_incorrect_type_exception));
1595
1596 return *v.template get_value_ptr<T>();
1597 }
1598
1599 //***********************************
1600 template <typename T, typename... TTypes>
1601 ETL_CONSTEXPR14 T&& get(etl::variant<TTypes...>&& v)
1602 {
1603 ETL_ASSERT((private_variant::is_same_type_in<T, TTypes...>(v.index())), ETL_ERROR(etl::variant_incorrect_type_exception));
1604
1605 return etl::move(*v.template get_value_ptr<T>());
1606 }
1607
1608 //***********************************
1609 template <typename T, typename... TTypes>
1610 ETL_CONSTEXPR14 const T& get(const etl::variant<TTypes...>& v)
1611 {
1612 ETL_ASSERT((private_variant::is_same_type_in<T, TTypes...>(v.index())), ETL_ERROR(etl::variant_incorrect_type_exception));
1613
1614 return *v.template get_value_ptr<T>();
1615 }
1616
1617 //***********************************
1618 template <typename T, typename... TTypes>
1619 ETL_CONSTEXPR14 const T&& get(const etl::variant<TTypes...>&& v)
1620 {
1621 ETL_ASSERT((private_variant::is_same_type_in<T, TTypes...>(v.index())), ETL_ERROR(etl::variant_incorrect_type_exception));
1622
1623 return etl::move(*v.template get_value_ptr<T>());
1624 }
1625
1626 //***************************************************************************
1628 //***************************************************************************
1629 template < size_t Index, typename... TTypes >
1630 ETL_CONSTEXPR14 etl::add_pointer_t<etl::variant_alternative_t<Index, etl::variant<TTypes...> > > get_if(etl::variant<TTypes...>* pv) ETL_NOEXCEPT
1631 {
1632 if ((pv != nullptr) && (pv->index() == Index))
1633 {
1634 return &etl::get<Index>(*pv);
1635 }
1636 else
1637 {
1638 return nullptr;
1639 }
1640 }
1641
1642 //***********************************
1643 template < size_t Index, typename... TTypes >
1644 ETL_CONSTEXPR14 etl::add_pointer_t<const etl::variant_alternative_t<Index, etl::variant<TTypes...> > > get_if(const etl::variant<TTypes...>* pv)
1645 ETL_NOEXCEPT
1646 {
1647 if ((pv != nullptr) && (pv->index() == Index))
1648 {
1649 return &etl::get<Index>(*pv);
1650 }
1651 else
1652 {
1653 return nullptr;
1654 }
1655 }
1656
1657 //***********************************
1658 template < class T, typename... TTypes >
1659 ETL_CONSTEXPR14 etl::add_pointer_t<T> get_if(etl::variant<TTypes...>* pv) ETL_NOEXCEPT
1660 {
1661 if ((pv != nullptr) && (private_variant::is_same_type_in<T, TTypes...>(pv->index())))
1662 {
1663 return pv->template get_value_ptr<T>();
1664 }
1665 else
1666 {
1667 return nullptr;
1668 }
1669 }
1670
1671 //***********************************
1672 template < typename T, typename... TTypes >
1673 ETL_CONSTEXPR14 etl::add_pointer_t<const T> get_if(const etl::variant<TTypes...>* pv) ETL_NOEXCEPT
1674 {
1675 if ((pv != nullptr) && (private_variant::is_same_type_in<T, TTypes...>(pv->index())))
1676 {
1677 return pv->template get_value_ptr<T>();
1678 }
1679 else
1680 {
1681 return nullptr;
1682 }
1683 }
1684
1685 //***************************************************************************
1687 //***************************************************************************
1688 template <typename... TTypes>
1690 {
1691 lhs.swap(rhs);
1692 }
1693
1694 //***************************************************************************
1696 //***************************************************************************
1697 template <typename T>
1698 struct variant_size;
1699
1700 template <typename... TTypes>
1701 struct variant_size<etl::variant<TTypes...> > : etl::integral_constant<size_t, sizeof...(TTypes)>
1702 {
1703 };
1704
1705 template <typename T>
1706 struct variant_size<const T> : etl::integral_constant<size_t, variant_size<T>::value>
1707 {
1708 };
1709
1710 #if ETL_USING_CPP17
1711 template <typename... TTypes>
1712 inline constexpr size_t variant_size_v = variant_size<TTypes...>::value;
1713 #endif
1714
1715 //***************************************************************************
1717 //***************************************************************************
1718 namespace private_variant
1719 {
1720 template <typename TRet, typename TCallable, typename TVariant, size_t tIndex, typename TNext, typename... TVariants>
1721 static ETL_CONSTEXPR14 TRet do_visit_single(TCallable&& f, TVariant&& v, TNext&&, TVariants&&... vs);
1722
1723 //***************************************************************************
1727 //***************************************************************************
1728 struct visit_auto_return
1729 {
1730 };
1731
1732 //***************************************************************************
1735 //***************************************************************************
1736 template <typename TCallable, typename... Ts>
1737 struct single_visit_result_type
1738 {
1739 using type = decltype(declval<TCallable>()(declval<Ts>()...));
1740 };
1741
1742 template <typename TCallable, typename... Ts>
1743 using single_visit_result_type_t = typename single_visit_result_type<TCallable, Ts...>::type;
1744
1745 //***************************************************************************
1748 //***************************************************************************
1749 template <typename TVar, typename T>
1750 using rlref_copy = conditional_t<is_reference<TVar>::value, T&, T&&>;
1751
1752 //***************************************************************************
1759 //***************************************************************************
1760 template <template <typename...> class, typename...>
1761 struct visit_result_helper;
1762
1763 template <template <typename...> class TToInject, size_t... tAltIndices, typename TCur>
1764 struct visit_result_helper<TToInject, index_sequence<tAltIndices...>, TCur>
1765 {
1766 template <size_t tIndex>
1767 using var_type = rlref_copy<TCur, variant_alternative_t<tIndex, remove_reference_t<TCur> > >;
1768
1769 using type = common_type_t<TToInject<var_type<tAltIndices> >...>;
1770 };
1771
1772 template <template <typename...> class TToInject, size_t... tAltIndices, typename TCur, typename TNext, typename... TVs>
1773 struct visit_result_helper<TToInject, index_sequence<tAltIndices...>, TCur, TNext, TVs...>
1774 {
1775 template <size_t tIndex>
1776 using var_type = rlref_copy<TCur, variant_alternative_t<tIndex, remove_reference_t<TCur> > >;
1777
1778 template <size_t tIndex>
1779 struct next_inject_wrap
1780 {
1781 template <typename... TNextInj>
1782 using next_inject = TToInject<var_type<tIndex>, TNextInj...>;
1783 using recursive_result =
1784 typename visit_result_helper<next_inject, make_index_sequence<variant_size<remove_reference_t<TNext> >::value>, TNext, TVs...>::type;
1785 };
1786
1787 using type = common_type_t<typename next_inject_wrap<tAltIndices>::recursive_result...>;
1788 };
1789
1790 //***************************************************************************
1794 //***************************************************************************
1795 template <typename TRet, typename...>
1796 struct visit_result
1797 {
1798 using type = TRet;
1799 };
1800
1801 template <typename TCallable, typename T1, typename... Ts>
1802 struct visit_result<visit_auto_return, TCallable, T1, Ts...>
1803 {
1804 // bind TCallable to the first argument in this variadic alias.
1805 template <typename... Ts2>
1806 using single_res = single_visit_result_type_t<TCallable, Ts2...>;
1807 using type = typename visit_result_helper<single_res, make_index_sequence<variant_size<remove_reference_t<T1> >::value>, T1, Ts...>::type;
1808 };
1809
1810 template <typename... Ts>
1811 using visit_result_t = typename visit_result<Ts...>::type;
1812
1813 //***************************************************************************
1816 //***************************************************************************
1817 template <typename TRet, typename TCallable, typename TVariant, size_t tIndex>
1818 constexpr TRet do_visit_single(TCallable&& f, TVariant&& v)
1819 {
1820 return static_cast<TCallable&&>(f)(etl::get<tIndex>(static_cast<TVariant&&>(v)));
1821 }
1822
1823 //***************************************************************************
1827 //***************************************************************************
1828 template <typename TRet, typename TCallable, typename TCurVariant, typename... TVarRest>
1829 struct do_visit_helper
1830 {
1831 using function_pointer = add_pointer_t<TRet(TCallable&&, TCurVariant&&, TVarRest&&...)>;
1832
1833 template <size_t tIndex>
1834 static constexpr function_pointer fptr() ETL_NOEXCEPT
1835 {
1836 return &do_visit_single<TRet, TCallable, TCurVariant, tIndex, TVarRest...>;
1837 }
1838 };
1839
1840 //***************************************************************************
1842 //***************************************************************************
1843 template <typename TRet, typename TCallable, typename TVariant, size_t... tIndices, typename... TVarRest>
1844 static ETL_CONSTEXPR14 TRet do_visit(TCallable&& f, TVariant&& v, index_sequence<tIndices...>, TVarRest&&... variants)
1845 {
1846 ETL_ASSERT(!v.valueless_by_exception(), ETL_ERROR(bad_variant_access));
1847
1848 using helper_t = do_visit_helper<TRet, TCallable, TVariant, TVarRest...>;
1849 using func_ptr = typename helper_t::function_pointer;
1850
1851 constexpr func_ptr jmp_table[]{helper_t::template fptr<tIndices>()...};
1852
1853 return jmp_table[v.index()](static_cast<TCallable&&>(f), static_cast<TVariant&&>(v), static_cast<TVarRest&&>(variants)...);
1854 }
1855
1856 template <typename TRet, typename TCallable, typename TVariant, typename... TVs>
1857 static ETL_CONSTEXPR14 TRet visit(TCallable&& f, TVariant&& v, TVs&&... vs)
1858 {
1859 constexpr size_t variants = etl::variant_size<typename remove_reference<TVariant>::type>::value;
1860 return private_variant::do_visit<TRet>(static_cast<TCallable&&>(f), static_cast<TVariant&&>(v), make_index_sequence<variants>{},
1861 static_cast<TVs&&>(vs)...);
1862 }
1863
1864 //***************************************************************************
1867 //***************************************************************************
1868 template <typename TRet, typename TCallable, typename TVariant, size_t tIndex>
1869 class constexpr_visit_closure
1870 {
1871 add_pointer_t<TCallable> callable_;
1872 add_pointer_t<TVariant> variant_;
1873
1874 public:
1875
1876 constexpr constexpr_visit_closure(TCallable&& c, TVariant&& v)
1877 : callable_(&c)
1878 , variant_(&v)
1879 {
1880 }
1881
1882 template <typename... Ts>
1883 ETL_CONSTEXPR14 TRet operator()(Ts&&... args) const
1884 {
1885 return static_cast<TCallable&&>(*callable_)(get<tIndex>(static_cast<TVariant&&>(*variant_)), static_cast<Ts&&>(args)...);
1886 }
1887 };
1888
1889 template <typename TRet, typename TCallable, typename TVariant, size_t tIndex, typename TNext, typename... TVariants>
1890 static ETL_CONSTEXPR14 TRet do_visit_single(TCallable&& f, TVariant&& v, TNext&& next, TVariants&&... vs)
1891 {
1892 return private_variant::visit<TRet>(
1893 constexpr_visit_closure<TRet, TCallable, TVariant, tIndex>(static_cast<TCallable&&>(f), static_cast<TVariant&&>(v)),
1894 static_cast<TNext&&>(next), static_cast<TVariants&&>(vs)...);
1895 }
1896
1897 } // namespace private_variant
1898
1899 //***************************************************************************
1902 //***************************************************************************
1903 template <typename TRet = private_variant::visit_auto_return, typename... TVariants, typename TCallable,
1904 typename TDeducedReturn = private_variant::visit_result_t<TRet, TCallable, TVariants...> >
1905 static ETL_CONSTEXPR14 TDeducedReturn visit(TCallable&& f, TVariants&&... vs)
1906 {
1907 return private_variant::visit<TDeducedReturn>(static_cast<TCallable&&>(f), static_cast<TVariants&&>(vs)...);
1908 }
1909
1910 namespace private_variant
1911 {
1912 //***************************************************************************
1915 //***************************************************************************
1916 template <typename TVariant>
1917 struct equality_visitor
1918 {
1919 equality_visitor(const TVariant& rhs_)
1920 : rhs(rhs_)
1921 {
1922 }
1923
1924 template <typename TValue>
1925 bool operator()(const TValue& lhs_downcasted)
1926 {
1927 return lhs_downcasted == etl::get<TValue>(rhs);
1928 }
1929
1930 const TVariant& rhs;
1931 };
1932
1933 //***************************************************************************
1936 //***************************************************************************
1937 template <typename TVariant>
1938 struct less_than_visitor
1939 {
1940 less_than_visitor(const TVariant& rhs_)
1941 : rhs(rhs_)
1942 {
1943 }
1944
1945 template <typename TValue>
1946 bool operator()(const TValue& lhs_downcasted)
1947 {
1948 return lhs_downcasted < etl::get<TValue>(rhs);
1949 }
1950
1951 const TVariant& rhs;
1952 };
1953 } // namespace private_variant
1954
1955 //***************************************************************************
1958 //***************************************************************************
1959 template <typename... TTypes>
1960 ETL_CONSTEXPR14 bool operator==(const etl::variant<TTypes...>& lhs, const etl::variant<TTypes...>& rhs)
1961 {
1962 // If both variants are valueless, they are considered equal
1963 if (lhs.valueless_by_exception() && rhs.valueless_by_exception())
1964 {
1965 return true;
1966 }
1967
1968 // If one variant is valueless and the other is not, they are not equal
1969 if (lhs.valueless_by_exception() || rhs.valueless_by_exception())
1970 {
1971 return false;
1972 }
1973
1974 // If variants have different types, they are not equal
1975 if (lhs.index() != rhs.index())
1976 {
1977 return false;
1978 }
1979
1980 // Variants have the same type, apply the equality operator for the contained values
1981 private_variant::equality_visitor<etl::variant<TTypes...> > visitor(rhs);
1982
1983 return etl::visit(visitor, lhs);
1984 }
1985
1986 //***************************************************************************
1989 //***************************************************************************
1990 template <typename... TTypes>
1991 ETL_CONSTEXPR14 bool operator!=(const etl::variant<TTypes...>& lhs, const etl::variant<TTypes...>& rhs)
1992 {
1993 return !(lhs == rhs);
1994 }
1995
1996 //***************************************************************************
1999 //***************************************************************************
2000 template <typename... TTypes>
2001 ETL_CONSTEXPR14 bool operator<(const etl::variant<TTypes...>& lhs, const etl::variant<TTypes...>& rhs)
2002 {
2003 // If both variants are valueless, they are considered equal, so not less than
2004 if (lhs.valueless_by_exception() && rhs.valueless_by_exception())
2005 {
2006 return false;
2007 }
2008
2009 // A valueless variant is always less than a variant with a value
2010 if (lhs.valueless_by_exception())
2011 {
2012 return true;
2013 }
2014
2015 // A variant with a value is never less than a valueless variant
2016 if (rhs.valueless_by_exception())
2017 {
2018 return false;
2019 }
2020
2021 // If variants have different types, compare the type index
2022 if (lhs.index() != rhs.index())
2023 {
2024 return lhs.index() < rhs.index();
2025 }
2026
2027 // Variants have the same type, apply the less than operator for the contained values
2028 private_variant::less_than_visitor<etl::variant<TTypes...> > visitor(rhs);
2029
2030 return etl::visit(visitor, lhs);
2031 }
2032
2033 //***************************************************************************
2036 //***************************************************************************
2037 template <typename... TTypes>
2038 ETL_CONSTEXPR14 bool operator>(const etl::variant<TTypes...>& lhs, const etl::variant<TTypes...>& rhs)
2039 {
2040 return (rhs < lhs);
2041 }
2042
2043 //***************************************************************************
2046 //***************************************************************************
2047 template <typename... TTypes>
2048 ETL_CONSTEXPR14 bool operator<=(const etl::variant<TTypes...>& lhs, const etl::variant<TTypes...>& rhs)
2049 {
2050 return !(lhs > rhs);
2051 }
2052
2053 //***************************************************************************
2056 //***************************************************************************
2057 template <typename... TTypes>
2058 ETL_CONSTEXPR14 bool operator>=(const etl::variant<TTypes...>& lhs, const etl::variant<TTypes...>& rhs)
2059 {
2060 return !(lhs < rhs);
2061 }
2062
2063 namespace private_variant
2064 {
2065 #if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
2066 //***************************************************************************
2069 //***************************************************************************
2070 template <typename TVariant>
2071 struct compare_visitor
2072 {
2073 compare_visitor(const TVariant& rhs_)
2074 : rhs(rhs_)
2075 {
2076 }
2077
2078 template <typename TValue>
2079 std::strong_ordering operator()(const TValue& lhs_downcasted)
2080 {
2081 return lhs_downcasted <=> etl::get<TValue>(rhs);
2082 }
2083
2084 const TVariant& rhs;
2085 };
2086 #endif
2087 } // namespace private_variant
2088
2089 //***************************************************************************
2093 //***************************************************************************
2094 #if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
2095 template <typename... TTypes>
2096 ETL_CONSTEXPR14 std::common_comparison_category_t<std::compare_three_way_result_t<TTypes>...> operator<=>(const etl::variant<TTypes...>& lhs,
2097 const etl::variant<TTypes...>& rhs)
2098 {
2099 if (lhs.valueless_by_exception() && rhs.valueless_by_exception())
2100 {
2101 return std::strong_ordering::equal;
2102 }
2103 else if (lhs.valueless_by_exception())
2104 {
2105 return std::strong_ordering::less;
2106 }
2107 else if (rhs.valueless_by_exception())
2108 {
2109 return std::strong_ordering::greater;
2110 }
2111 else if (lhs.index() != rhs.index())
2112 {
2113 return lhs.index() <=> rhs.index();
2114 }
2115 else
2116 {
2117 // Variants have the same type, apply the equality operator for the contained values
2118 private_variant::compare_visitor<etl::variant<TTypes...> > visitor(rhs);
2119
2120 return etl::visit(visitor, lhs);
2121 }
2122 }
2123 #endif
2124
2125 //***************************************************************************
2127 template <typename TList>
2128 struct variant_from_type_list;
2129
2130 template <typename... TTypes>
2131 struct variant_from_type_list<etl::type_list<TTypes...> >
2132 {
2133 using type = etl::variant<TTypes...>;
2134 };
2135
2136 template <typename TTypeList>
2137 using variant_from_type_list_t = typename variant_from_type_list<TTypeList>::type;
2138} // namespace etl
2139#endif
void swap(etl::array_view< T > &lhs, etl::array_view< T > &rhs) ETL_NOEXCEPT
Swaps the values.
Definition array_view.h:692
Make this a clone of the supplied priority queue.
#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
ETL_CONSTEXPR17 etl::enable_if<!etl::is_same< T, etl::nullptr_t >::value, T >::type * addressof(T &t)
Definition addressof.h:52
T & get()
Definition variant_legacy.h:738
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
Definition absolute.h:40
ETL_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1078
ETL_CONSTEXPR TContainer::pointer data(TContainer &container)
Definition iterator.h:1470
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1130
integral_constant< bool, false > false_type
integral_constant specialisations
Definition type_traits.h:80
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1144
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1090
T & get(array< T, Size > &a)
Definition array.h:1158
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1103
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1117
integral_constant
Definition type_traits.h:67
A 'no-value' placeholder.
Definition monostate.h:42
Definition variant_legacy.h:989
ETL_CONSTEXPR14 bool operator==(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Equality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:903
ETL_CONSTEXPR14 bool operator!=(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Inequality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:937