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
51#if defined(ETL_COMPILER_KEIL)
52 #pragma diag_suppress 940
53 #pragma diag_suppress 111
54#endif
55
56#if ETL_CPP11_NOT_SUPPORTED
57 #if !defined(ETL_IN_UNIT_TEST)
58 #error NOT SUPPORTED FOR C++03 OR BELOW
59 #endif
60#else
61//*****************************************************************************
66//*****************************************************************************
67
68namespace etl
69{
70 namespace private_variant
71 {
72 //*******************************************
73 // The traits an object may have.
74 //*******************************************
75 static constexpr bool Copyable = true;
76 static constexpr bool Non_Copyable = false;
77 static constexpr bool Moveable = true;
78 static constexpr bool Non_Moveable = false;
79
80 //*******************************************
81 // The types of operations we can perform.
82 //*******************************************
83 static constexpr int Copy = 0;
84 static constexpr int Move = 1;
85 static constexpr int Destroy = 2;
86
87 //*******************************************
88 // operation_type
89 //*******************************************
90 template <typename T, bool IsCopyable, bool IsMoveable>
91 struct operation_type;
92
93 //*******************************************
94 // Specialisation for null operation.
95 template <>
96 struct operation_type<void, Non_Copyable, Non_Moveable>
97 {
98 static void do_operation(int, char*, const char*)
99 {
100 // This should never occur.
101 #if defined(ETL_IN_UNIT_TEST)
102 assert(false);
103 #endif
104 }
105 };
106
107 //*******************************************
108 // Specialisation for no-copyable & non-moveable types.
109 template <typename T>
110 struct operation_type<T, Non_Copyable, Non_Moveable>
111 {
112 static void do_operation(int operation, char* pstorage, const char* /*pvalue*/)
113 {
114 switch (operation)
115 {
116 case Destroy:
117 {
118 reinterpret_cast<const T*>(pstorage)->~T();
119 break;
120 }
121
122 default:
123 {
124 // This should never occur.
125 #if defined(ETL_IN_UNIT_TEST)
126 assert(false);
127 #endif
128 break;
129 }
130 }
131 }
132 };
133
134 //*******************************************
135 // Specialisation for no-copyable & moveable types.
136 template <typename T>
137 struct operation_type<T, Non_Copyable, Moveable>
138 {
139 static void do_operation(int operation, char* pstorage, const char* pvalue)
140 {
141 switch (operation)
142 {
143 case Move:
144 {
145 ::new (pstorage) T(etl::move(*reinterpret_cast<T*>(const_cast<char*>(pvalue))));
146 break;
147 }
148
149 case Destroy:
150 {
151 reinterpret_cast<const T*>(pstorage)->~T();
152 break;
153 }
154
155 default:
156 {
157 // This should never occur.
158 #if defined(ETL_IN_UNIT_TEST)
159 assert(false);
160 #endif
161 break;
162 }
163 }
164 }
165 };
166
167 //*******************************************
168 // Specialisation for copyable & non-moveable types.
169 template <typename T>
170 struct operation_type<T, Copyable, Non_Moveable>
171 {
172 static void do_operation(int operation, char* pstorage, const char* pvalue)
173 {
174 switch (operation)
175 {
176 case Copy:
177 {
178 ::new (pstorage) T(*reinterpret_cast<const T*>(pvalue));
179 break;
180 }
181
182 case Destroy:
183 {
184 reinterpret_cast<const T*>(pstorage)->~T();
185 break;
186 }
187
188 default:
189 {
190 // This should never occur.
191 #if defined(ETL_IN_UNIT_TEST)
192 assert(false);
193 #endif
194 break;
195 }
196 }
197 }
198 };
199
200 //*******************************************
201 // Specialisation for copyable & moveable types.
202 template <typename T>
203 struct operation_type<T, Copyable, Moveable>
204 {
205 static void do_operation(int operation, char* pstorage, const char* pvalue)
206 {
207 switch (operation)
208 {
209 case Copy:
210 {
211 ::new (pstorage) T(*reinterpret_cast<const T*>(pvalue));
212 break;
213 }
214
215 case Move:
216 {
217 ::new (pstorage) T(etl::move(*reinterpret_cast<T*>(const_cast<char*>(pvalue))));
218 break;
219 }
220
221 case Destroy:
222 {
223 reinterpret_cast<const T*>(pstorage)->~T();
224 break;
225 }
226
227 default:
228 {
229 // This should never occur.
230 #if defined(ETL_IN_UNIT_TEST)
231 assert(false);
232 #endif
233 break;
234 }
235 }
236 }
237 };
238 } // namespace private_variant
239
241 constexpr size_t variant_npos = etl::integral_limits<size_t>::max;
242
243 //***********************************
244 // variant. Forward declaration
245 template <typename... TTypes>
246 class variant;
247
248 //***************************************************************************
250 //***************************************************************************
251 template <size_t Index, typename T>
252 struct variant_alternative;
253
254 template <size_t Index, typename... TTypes>
255 struct variant_alternative<Index, etl::variant<TTypes...> >
256 {
257 using type = etl::nth_type_t<Index, TTypes...>;
258 };
259
260 template <size_t Index, typename T>
261 struct variant_alternative<Index, const T>
262 {
263 using type = typename variant_alternative<Index, T>::type;
264 };
265
266 template <size_t Index, typename T>
267 using variant_alternative_t = typename variant_alternative<Index, T>::type;
268
269 //***********************************
270 // holds_alternative. Forward declaration
271 template <typename T, typename... TTypes>
272 ETL_CONSTEXPR14 bool holds_alternative(const etl::variant<TTypes...>& v) ETL_NOEXCEPT;
273
274 //***********************************
275 // get. Forward declarations
276 template <size_t Index, typename... VTypes>
277 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...> >& get(etl::variant<VTypes...>& v);
278
279 template <size_t Index, typename... VTypes>
280 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...> >&& get(etl::variant<VTypes...>&& v);
281
282 template <size_t Index, typename... VTypes>
283 ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<VTypes...> >& get(const etl::variant<VTypes...>& v);
284
285 template <size_t Index, typename... VTypes>
286 ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<VTypes...> >&& get(const etl::variant<VTypes...>&& v);
287
288 template <typename T, typename... VTypes>
289 ETL_CONSTEXPR14 T& get(etl::variant<VTypes...>& v);
290
291 template <typename T, typename... VTypes>
292 ETL_CONSTEXPR14 T&& get(etl::variant<VTypes...>&& v);
293
294 template <typename T, typename... VTypes>
295 ETL_CONSTEXPR14 const T& get(const etl::variant<VTypes...>& v);
296
297 template <typename T, typename... VTypes>
298 ETL_CONSTEXPR14 const T&& get(const etl::variant<VTypes...>&& v);
299
300 #if ETL_NOT_USING_CPP17
301 #include "variant_select_do_operator.h"
302 #include "variant_select_do_visitor.h"
303 #endif
304
305 constexpr bool operator>(etl::monostate, etl::monostate) ETL_NOEXCEPT
306 {
307 return false;
308 }
309 constexpr bool operator<(etl::monostate, etl::monostate) ETL_NOEXCEPT
310 {
311 return false;
312 }
313 constexpr bool operator!=(etl::monostate, etl::monostate) ETL_NOEXCEPT
314 {
315 return false;
316 }
317 constexpr bool operator<=(etl::monostate, etl::monostate) ETL_NOEXCEPT
318 {
319 return true;
320 }
321 constexpr bool operator>=(etl::monostate, etl::monostate) ETL_NOEXCEPT
322 {
323 return true;
324 }
325 constexpr bool operator==(etl::monostate, etl::monostate) ETL_NOEXCEPT
326 {
327 return true;
328 }
329 #if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
330 constexpr std::strong_ordering operator<=>(monostate, monostate) ETL_NOEXCEPT
331 {
332 return std::strong_ordering::equal;
333 }
334 #endif
335
336 #if ETL_NOT_USING_STL && !defined(ETL_USE_TYPE_TRAITS_BUILTINS)
337 template <>
338 struct is_copy_constructible<etl::monostate> : public etl::true_type
339 {
340 };
341
342 template <>
343 struct is_move_constructible<etl::monostate> : public etl::true_type
344 {
345 };
346 #endif
347
348 //***************************************************************************
351 //***************************************************************************
352 class variant_exception : public exception
353 {
354 public:
355
356 variant_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
357 : exception(reason_, file_name_, line_number_)
358 {
359 }
360 };
361
362 //***************************************************************************
365 //***************************************************************************
367 {
368 public:
369
370 variant_incorrect_type_exception(string_type file_name_, numeric_type line_number_)
371 : variant_exception(ETL_ERROR_TEXT("variant:unsupported type", ETL_VARIANT_FILE_ID"A"), file_name_, line_number_)
372 {
373 }
374 };
375
376 //***************************************************************************
379 //***************************************************************************
381 {
382 public:
383
384 bad_variant_access(string_type file_name_, numeric_type line_number_)
385 : variant_exception(ETL_ERROR_TEXT("variant:bad variant access", ETL_VARIANT_FILE_ID"B"), file_name_, line_number_)
386 {
387 }
388 };
389
390 //***************************************************************************
394 //***************************************************************************
395 template <typename... TTypes>
396 class variant
397 {
398 public:
399
400 using type_list = etl::type_list<TTypes...>;
401
402 //***************************************************************************
404 //***************************************************************************
405 template <size_t Index, typename... VTypes>
406 friend ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...> >& get(etl::variant<VTypes...>& v);
407
408 template <size_t Index, typename... VTypes>
409 friend ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...> >&& get(etl::variant<VTypes...>&& v);
410
411 template <size_t Index, typename... VTypes>
412 friend ETL_CONSTEXPR14 const etl::variant_alternative_t< Index, const etl::variant<VTypes...> >& get(const etl::variant<VTypes...>& v);
413
414 template <size_t Index, typename... VTypes>
415 friend ETL_CONSTEXPR14 const etl::variant_alternative_t< Index, const etl::variant<VTypes...> >&& get(const etl::variant<VTypes...>&& v);
416
417 template <typename T, typename... VTypes>
418 friend ETL_CONSTEXPR14 T& get(etl::variant<VTypes...>& v);
419
420 template <typename T, typename... VTypes>
421 friend ETL_CONSTEXPR14 T&& get(etl::variant<VTypes...>&& v);
422
423 template <typename T, typename... VTypes>
424 friend ETL_CONSTEXPR14 const T& get(const etl::variant<VTypes...>& v);
425
426 template <typename T, typename... VTypes>
427 friend ETL_CONSTEXPR14 const T&& get(const etl::variant<VTypes...>&& v);
428
429 template < class T, typename... VTypes >
430 friend ETL_CONSTEXPR14 etl::add_pointer_t<T> get_if(etl::variant<VTypes...>* pv) ETL_NOEXCEPT;
431
432 template < class T, typename... VTypes >
433 friend ETL_CONSTEXPR14 etl::add_pointer_t<const T> get_if(const etl::variant<VTypes...>* pv) ETL_NOEXCEPT;
434
435 private:
436
437 // All types of variant are friends.
438 template <typename... UTypes>
439 friend class variant;
440
441 //***************************************************************************
443 //***************************************************************************
444 using largest_t = typename largest_type<TTypes...>::type;
445
446 //***************************************************************************
448 //***************************************************************************
449 static const size_t Size = sizeof(largest_t);
450
451 //***************************************************************************
453 //***************************************************************************
454 static const size_t Alignment = etl::largest_alignment<TTypes...>::value;
455
456 //***************************************************************************
458 //***************************************************************************
459 template <typename T, bool IsCopyable, bool IsMoveable>
460 using operation_type = private_variant::operation_type<T, IsCopyable, IsMoveable>;
461
462 //*******************************************
463 // The types of operations we can perform.
464 //*******************************************
465 static constexpr int Copy = private_variant::Copy;
466 static constexpr int Move = private_variant::Move;
467 static constexpr int Destroy = private_variant::Destroy;
468
469 //*******************************************
470 // Get the index of a type.
471 //*******************************************
472 template <typename T>
473 using index_of_type = etl::type_list_index_of_type<etl::type_list<TTypes...>, etl::remove_cvref_t<T> >;
474
475 //*******************************************
476 // Get the type from the index.
477 //*******************************************
478 template <size_t Index>
479 using type_from_index = typename etl::type_list_type_at_index<etl::type_list<TTypes...>, Index>::type;
480
481 public:
482
483 //***************************************************************************
487 //***************************************************************************
489 ETL_CONSTEXPR14 variant()
490 {
491 using type = type_from_index<0U>;
492
493 default_construct_in_place<type>(data);
494 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
495 type_id = 0U;
496 }
497 #include "diagnostic_pop.h"
498
499 //***************************************************************************
501 //***************************************************************************
503 template <typename T, etl::enable_if_t< !etl::is_same<etl::remove_cvref_t<T>, variant>::value, int> = 0>
504 ETL_CONSTEXPR14 variant(T&& value)
505 : operation(operation_type< etl::remove_cvref_t<T>, etl::is_copy_constructible<etl::remove_cvref_t<T> >::value,
506 etl::is_move_constructible<etl::remove_cvref_t<T> >::value>::do_operation)
507 , type_id(index_of_type<T>::value)
508 {
509 static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
510
511 construct_in_place<etl::remove_cvref_t<T> >(data, etl::forward<T>(value));
512 }
513 #include "diagnostic_pop.h"
514
515 //***************************************************************************
517 //***************************************************************************
519 template <typename T, typename... TArgs>
520 ETL_CONSTEXPR14 explicit variant(etl::in_place_type_t<T>, TArgs&&... args)
521 : operation(operation_type< etl::remove_cvref_t<T>, etl::is_copy_constructible<etl::remove_cvref_t<T> >::value,
522 etl::is_move_constructible<etl::remove_cvref_t<T> >::value>::do_operation)
523 , type_id(index_of_type<T>::value)
524 {
525 static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
526
527 construct_in_place_args<etl::remove_cvref_t<T> >(data, etl::forward<TArgs>(args)...);
528 }
529 #include "diagnostic_pop.h"
530
531 //***************************************************************************
533 //***************************************************************************
535 template <size_t Index, typename... TArgs>
536 ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t<Index>, TArgs&&... args)
537 : type_id(Index)
538 {
539 using type = type_from_index<Index>;
540 static_assert(etl::is_one_of<type, TTypes...>::value, "Unsupported type");
541
542 construct_in_place_args<type>(data, etl::forward<TArgs>(args)...);
543
544 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
545 }
546 #include "diagnostic_pop.h"
547
548 #if ETL_HAS_INITIALIZER_LIST
549 //***************************************************************************
551 //***************************************************************************
553 template <typename T, typename U, typename... TArgs >
554 ETL_CONSTEXPR14 explicit variant(etl::in_place_type_t<T>, std::initializer_list<U> init, TArgs&&... args)
555 : operation(operation_type< etl::remove_cvref_t<T>, etl::is_copy_constructible<etl::remove_cvref_t<T> >::value,
556 etl::is_move_constructible<etl::remove_cvref_t<T> >::value>::do_operation)
557 , type_id(index_of_type<T>::value)
558 {
559 static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
560
561 construct_in_place_args<etl::remove_cvref_t<T> >(data, init, etl::forward<TArgs>(args)...);
562 }
563 #include "diagnostic_pop.h"
564
565 //***************************************************************************
567 //***************************************************************************
569 template <size_t Index, typename U, typename... TArgs >
570 ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t<Index>, std::initializer_list<U> init, TArgs&&... args)
571 : type_id(Index)
572 {
573 using type = type_from_index<Index>;
574 static_assert(etl::is_one_of<type, TTypes...>::value, "Unsupported type");
575
576 construct_in_place_args<type>(data, init, etl::forward<TArgs>(args)...);
577
578 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
579 }
580 #include "diagnostic_pop.h"
581 #endif
582
583 //***************************************************************************
586 //***************************************************************************
588 ETL_CONSTEXPR14 variant(const variant& other)
589 : operation(other.operation)
590 , type_id(other.type_id)
591 {
592 if (other.valueless_by_exception())
593 {
594 type_id = variant_npos;
595 }
596 else
597 {
598 operation(private_variant::Copy, data, other.data);
599 }
600 }
601 #include "diagnostic_pop.h"
602
603 //***************************************************************************
606 //***************************************************************************
608 ETL_CONSTEXPR14 variant(variant&& other)
609 : operation(other.operation)
610 , type_id(other.type_id)
611 {
612 if (other.valueless_by_exception())
613 {
614 type_id = variant_npos;
615 }
616 else
617 {
618 operation(private_variant::Move, data, other.data);
619 }
620 }
621 #include "diagnostic_pop.h"
622
623 //***************************************************************************
625 //***************************************************************************
626 ~variant()
627 {
628 if (!valueless_by_exception())
629 {
630 operation(private_variant::Destroy, data, nullptr);
631 }
632
633 operation = operation_type<void, false, false>::do_operation; // Null operation.
634 type_id = variant_npos;
635 }
636
637 //***************************************************************************
639 //***************************************************************************
640 template <typename T, typename... TArgs>
641 T& emplace(TArgs&&... args)
642 {
643 static_assert(etl::is_one_of<T, TTypes...>::value, "Unsupported type");
644
645 using type = etl::remove_cvref_t<T>;
646
647 if (!valueless_by_exception())
648 {
649 operation(private_variant::Destroy, data, nullptr);
650 }
651
652 construct_in_place_args<type>(data, etl::forward<TArgs>(args)...);
653
654 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
655
656 type_id = index_of_type<T>::value;
657
658 return *static_cast<T*>(data);
659 }
660
661 #if ETL_HAS_INITIALIZER_LIST
662 //***************************************************************************
664 //***************************************************************************
665 template <typename T, typename U, typename... TArgs>
666 T& emplace(std::initializer_list<U> il, TArgs&&... args)
667 {
668 static_assert(etl::is_one_of<T, TTypes...>::value, "Unsupported type");
669
670 using type = etl::remove_cvref_t<T>;
671
672 if (!valueless_by_exception())
673 {
674 operation(private_variant::Destroy, data, nullptr);
675 }
676
677 construct_in_place_args<type>(data, il, etl::forward<TArgs>(args)...);
678
679 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
680
681 type_id = index_of_type<T>::value;
682
683 return *static_cast<T*>(data);
684 }
685 #endif
686
687 //***************************************************************************
689 //***************************************************************************
690 template <size_t Index, typename... TArgs>
691 typename etl::variant_alternative_t<Index, variant<TTypes...> >& emplace(TArgs&&... args)
692 {
693 static_assert(Index < sizeof...(TTypes), "Index out of range");
694
695 using type = type_from_index<Index>;
696
697 if (!valueless_by_exception())
698 {
699 operation(private_variant::Destroy, data, nullptr);
700 }
701
702 construct_in_place_args<type>(data, etl::forward<TArgs>(args)...);
703
704 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
705
706 type_id = Index;
707
708 return *static_cast<type*>(data);
709 }
710
711 #if ETL_HAS_INITIALIZER_LIST
712 //***************************************************************************
714 //***************************************************************************
715 template <size_t Index, typename U, typename... TArgs>
716 typename etl::variant_alternative_t<Index, variant<TTypes...> >& emplace(std::initializer_list<U> il, TArgs&&... args)
717 {
718 static_assert(Index < sizeof...(TTypes), "Index out of range");
719
720 using type = type_from_index<Index>;
721
722 if (!valueless_by_exception())
723 {
724 operation(private_variant::Destroy, data, nullptr);
725 }
726
727 construct_in_place_args<type>(data, il, etl::forward<TArgs>(args)...);
728
729 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
730
731 type_id = Index;
732
733 return *static_cast<type*>(data);
734 }
735 #endif
736
737 //***************************************************************************
740 //***************************************************************************
741 template <typename T, etl::enable_if_t< !etl::is_same<etl::remove_cvref_t<T>, variant>::value, int> = 0>
742 variant& operator=(T&& value)
743 {
744 using type = etl::remove_cvref_t<T>;
745
746 static_assert(etl::is_one_of<type, TTypes...>::value, "Unsupported type");
747
748 if (!valueless_by_exception())
749 {
750 operation(private_variant::Destroy, data, nullptr);
751 }
752
753 construct_in_place<type>(data, etl::forward<T>(value));
754
755 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
756 type_id = index_of_type<type>::value;
757
758 return *this;
759 }
760
761 //***************************************************************************
764 //***************************************************************************
765 variant& operator=(const variant& other)
766 {
767 if (this != &other)
768 {
769 if (!valueless_by_exception())
770 {
771 operation(Destroy, data, nullptr);
772 }
773
774 if (other.valueless_by_exception())
775 {
776 type_id = variant_npos;
777 }
778 else
779 {
780 operation = other.operation;
781 operation(Copy, data, other.data);
782
783 type_id = other.type_id;
784 }
785 }
786
787 return *this;
788 }
789
790 //***************************************************************************
793 //***************************************************************************
794 variant& operator=(variant&& other)
795 {
796 if (this != &other)
797 {
798 if (!valueless_by_exception())
799 {
800 operation(Destroy, data, nullptr);
801 }
802
803 if (other.valueless_by_exception())
804 {
805 type_id = variant_npos;
806 }
807 else
808 {
809 operation = other.operation;
810 operation(Move, data, other.data);
811
812 type_id = other.type_id;
813 }
814 }
815
816 return *this;
817 }
818
819 //***************************************************************************
822 //***************************************************************************
823 constexpr bool valueless_by_exception() const ETL_NOEXCEPT
824 {
825 return type_id == variant_npos;
826 }
827
828 //***************************************************************************
830 //***************************************************************************
831 constexpr size_t index() const ETL_NOEXCEPT
832 {
833 return type_id;
834 }
835
836 //***************************************************************************
840 //***************************************************************************
841 template <typename T>
842 static constexpr bool is_supported_type()
843 {
844 return etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value;
845 }
846
847 //***************************************************************************
851 //***************************************************************************
852 template <typename T, etl::enable_if_t<is_supported_type<T>(), int> = 0>
853 constexpr bool is_type() const ETL_NOEXCEPT
854 {
855 return (type_id == index_of_type<T>::value);
856 }
857
858 //***************************************************************************
859 template <typename T, etl::enable_if_t<!is_supported_type<T>(), int> = 0>
860 constexpr bool is_type() const ETL_NOEXCEPT
861 {
862 return false;
863 }
864
865 //***************************************************************************
870 //***************************************************************************
871 constexpr bool is_same_type(const variant& other) const
872 {
873 return type_id == other.type_id;
874 }
875
876 //***************************************************************************
878 //***************************************************************************
879 void swap(variant& rhs) ETL_NOEXCEPT
880 {
881 variant temp(etl::move(*this));
882 *this = etl::move(rhs);
883 rhs = etl::move(temp);
884 }
885
886 //***************************************************************************
888 //***************************************************************************
889 template <typename TVisitor>
890 etl::enable_if_t<etl::is_visitor<TVisitor>::value, void> accept(TVisitor& v)
891 {
892 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
893 do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
894 #else
895 do_visitor<sizeof...(TTypes)>(v);
896 #endif
897 }
898
899 //***************************************************************************
901 //***************************************************************************
902 template <typename TVisitor>
903 etl::enable_if_t<etl::is_visitor<TVisitor>::value, void> accept(TVisitor& v) const
904 {
905 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
906 do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
907 #else
908 do_visitor<sizeof...(TTypes)>(v);
909 #endif
910 }
911
912 //***************************************************************************
914 //***************************************************************************
915 template <typename TVisitor>
916 etl::enable_if_t<!etl::is_visitor<TVisitor>::value, void> accept(TVisitor& v)
917 {
918 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
919 do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
920 #else
921 do_operator<sizeof...(TTypes)>(v);
922 #endif
923 }
924
925 //***************************************************************************
927 //***************************************************************************
928 template <typename TVisitor>
929 etl::enable_if_t<!etl::is_visitor<TVisitor>::value, void> accept(TVisitor& v) const
930 {
931 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
932 do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
933 #else
934 do_operator<sizeof...(TTypes)>(v);
935 #endif
936 }
937
938 //***************************************************************************
941 //***************************************************************************
942 template <typename TVisitor>
943 #if !defined(ETL_IN_UNIT_TEST)
944 ETL_DEPRECATED_REASON("Replace with accept()")
945 #endif
946 void
947 accept_visitor(TVisitor& v)
948 {
949 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
950 do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
951 #else
952 do_visitor<sizeof...(TTypes)>(v);
953 #endif
954 }
955
956 //***************************************************************************
959 //***************************************************************************
960 template <typename TVisitor>
961 #if !defined(ETL_IN_UNIT_TEST)
962 ETL_DEPRECATED_REASON("Replace with accept()")
963 #endif
964 void
965 accept_visitor(TVisitor& v) const
966 {
967 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
968 do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
969 #else
970 do_visitor<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_functor(TVisitor& v)
984 {
985 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
986 do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
987 #else
988 do_operator<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_functor(TVisitor& v) const
1002 {
1003 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1004 do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
1005 #else
1006 do_operator<sizeof...(TTypes)>(v);
1007 #endif
1008 }
1009
1010 private:
1011
1013 using operation_function = void (*)(int, char*, const char*);
1014
1015 //***************************************************************************
1017 //***************************************************************************
1018 template <typename T>
1019 static void construct_in_place(char* pstorage, const T& value)
1020 {
1021 using type = etl::remove_cvref_t<T>;
1022
1023 ::new (pstorage) type(value);
1024 }
1025
1026 //***************************************************************************
1028 //***************************************************************************
1029 template <typename T>
1030 static void construct_in_place(char* pstorage, T&& value)
1031 {
1032 using type = etl::remove_cvref_t<T>;
1033
1034 ::new (pstorage) type(etl::move(value));
1035 }
1036
1037 //***************************************************************************
1039 //***************************************************************************
1040 template <typename T, typename... TArgs>
1041 static void construct_in_place_args(char* pstorage, TArgs&&... args)
1042 {
1043 using type = etl::remove_cvref_t<T>;
1044
1045 ::new (pstorage) type(etl::forward<TArgs>(args)...);
1046 }
1047
1048 //***************************************************************************
1050 //***************************************************************************
1051 template <typename T>
1052 static void default_construct_in_place(char* pstorage)
1053 {
1054 using type = etl::remove_cvref_t<T>;
1055
1056 ::new (pstorage) type();
1057 }
1058
1059 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1060 //***************************************************************************
1062 //***************************************************************************
1063 template <typename TVisitor, size_t... I>
1064 void do_visitor(TVisitor& visitor, etl::index_sequence<I...>)
1065 {
1066 (attempt_visitor<I>(visitor) || ...);
1067 }
1068
1069 //***************************************************************************
1071 //***************************************************************************
1072 template <typename TVisitor, size_t... I>
1073 void do_visitor(TVisitor& visitor, etl::index_sequence<I...>) const
1074 {
1075 (attempt_visitor<I>(visitor) || ...);
1076 }
1077 #else
1078 //***************************************************************************
1080 //***************************************************************************
1081 template <size_t NTypes, typename TVisitor>
1082 void do_visitor(TVisitor& visitor)
1083 {
1084 etl::private_variant::select_do_visitor<NTypes>::do_visitor(*this, visitor);
1085 }
1086
1087 //***************************************************************************
1089 //***************************************************************************
1090 template <size_t NTypes, typename TVisitor>
1091 void do_visitor(TVisitor& visitor) const
1092 {
1093 etl::private_variant::select_do_visitor<NTypes>::do_visitor(*this, visitor);
1094 }
1095 #endif
1096
1097 //***************************************************************************
1099 //***************************************************************************
1100 template <size_t Index, typename TVisitor>
1101 bool attempt_visitor(TVisitor& visitor)
1102 {
1103 if (Index == index())
1104 {
1105 // Workaround for MSVC (2023/05/13)
1106 // It doesn't compile 'visitor.visit(etl::get<Index>(*this))' correctly
1107 // for C++17 & C++20. Changed all of the instances for consistency.
1108 auto& v = etl::get<Index>(*this);
1109 visitor.visit(v);
1110 return true;
1111 }
1112 else
1113 {
1114 return false;
1115 }
1116 }
1117
1118 //***************************************************************************
1120 //***************************************************************************
1121 template <size_t Index, typename TVisitor>
1122 bool attempt_visitor(TVisitor& visitor) const
1123 {
1124 if (Index == index())
1125 {
1126 // Workaround for MSVC (2023/05/13)
1127 // It doesn't compile 'visitor.visit(etl::get<Index>(*this))' correctly
1128 // for C++17 & C++20. Changed all of the instances for consistency.
1129 auto& v = etl::get<Index>(*this);
1130 visitor.visit(v);
1131 return true;
1132 }
1133 else
1134 {
1135 return false;
1136 }
1137 }
1138
1139 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1140 //***************************************************************************
1142 //***************************************************************************
1143 template <typename TVisitor, size_t... I>
1144 void do_operator(TVisitor& visitor, etl::index_sequence<I...>)
1145 {
1146 (attempt_operator<I>(visitor) || ...);
1147 }
1148
1149 //***************************************************************************
1151 //***************************************************************************
1152 template <typename TVisitor, size_t... I>
1153 void do_operator(TVisitor& visitor, etl::index_sequence<I...>) const
1154 {
1155 (attempt_operator<I>(visitor) || ...);
1156 }
1157 #else
1158 //***************************************************************************
1160 //***************************************************************************
1161 template <size_t NTypes, typename TVisitor>
1162 void do_operator(TVisitor& visitor)
1163 {
1164 #if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1165 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 8U, "ETL_VARIANT_CPP11_MAX_8_TYPES - Only a maximum of 8 types are allowed in this variant");
1166 #endif
1167
1168 #if defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1169 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 16U, "ETL_VARIANT_CPP11_MAX_16_TYPES - Only a maximum of 16 types are allowed in this variant");
1170 #endif
1171
1172 #if defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1173 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 24U, "ETL_VARIANT_CPP11_MAX_24_TYPES - Only a maximum of 24 types are allowed in this variant");
1174 #endif
1175
1176 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 32U, "A maximum of 32 types are allowed in this variant");
1177
1178 etl::private_variant::select_do_operator<NTypes>::do_operator(*this, visitor);
1179 }
1180
1181 //***************************************************************************
1183 //***************************************************************************
1184 template <size_t NTypes, typename TVisitor>
1185 void do_operator(TVisitor& visitor) const
1186 {
1187 #if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1188 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 8U, "ETL_VARIANT_CPP11_MAX_8_TYPES - Only a maximum of 8 types are allowed in this variant");
1189 #endif
1190
1191 #if defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1192 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 16U, "ETL_VARIANT_CPP11_MAX_16_TYPES - Only a maximum of 16 types are allowed in this variant");
1193 #endif
1194
1195 #if defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1196 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 24U, "ETL_VARIANT_CPP11_MAX_24_TYPES - Only a maximum of 24 types are allowed in this variant");
1197 #endif
1198
1199 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 32U, "A maximum of 32 types are allowed in this variant");
1200
1201 etl::private_variant::select_do_operator<NTypes>::do_operator(*this, visitor);
1202 }
1203 #endif
1204
1205 //***************************************************************************
1207 //***************************************************************************
1208 template <size_t Index, typename TVisitor>
1209 bool attempt_operator(TVisitor& visitor)
1210 {
1211 if (Index == index())
1212 {
1213 auto& v = etl::get<Index>(*this);
1214 visitor(v);
1215 return true;
1216 }
1217 else
1218 {
1219 return false;
1220 }
1221 }
1222
1223 //***************************************************************************
1225 //***************************************************************************
1226 template <size_t Index, typename TVisitor>
1227 bool attempt_operator(TVisitor& visitor) const
1228 {
1229 if (Index == index())
1230 {
1231 auto& v = etl::get<Index>(*this);
1232 visitor(v);
1233 return true;
1234 }
1235 else
1236 {
1237 return false;
1238 }
1239 }
1240
1241 //***************************************************************************
1244 //***************************************************************************
1245 etl::uninitialized_buffer<Size, 1U, Alignment> data;
1246
1247 //***************************************************************************
1249 //***************************************************************************
1250 operation_function operation;
1251
1252 //***************************************************************************
1254 //***************************************************************************
1255 size_t type_id;
1256 };
1257
1258 namespace private_variant
1259 {
1260 //***************************************************************************
1263 //***************************************************************************
1264 template <typename T, typename T0, typename T1, typename... Ts>
1265 typename etl::enable_if_t<etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t index) ETL_NOEXCEPT;
1266
1267 template <typename T, typename T0>
1268 typename etl::enable_if_t<etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t index) ETL_NOEXCEPT;
1269
1270 template <typename T, typename T0, typename T1, typename... Ts>
1271 typename etl::enable_if_t<!etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t index) ETL_NOEXCEPT;
1272
1273 template <typename T, typename T0>
1274 typename etl::enable_if_t<!etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t index) ETL_NOEXCEPT;
1275
1276 template <typename T, typename T0, typename T1, typename... Ts>
1277 typename etl::enable_if_t<etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t index) ETL_NOEXCEPT
1278 {
1279 if (index == 0)
1280 {
1281 return true;
1282 }
1283 else
1284 {
1285 return is_same_type_in<T, T1, Ts...>(index - 1);
1286 }
1287 }
1288
1289 template <typename T, typename T0>
1290 typename etl::enable_if_t<etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t index) ETL_NOEXCEPT
1291 {
1292 return index == 0;
1293 }
1294
1295 template <typename T, typename T0, typename T1, typename... Ts>
1296 typename etl::enable_if_t<!etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t index) ETL_NOEXCEPT
1297 {
1298 if (index == 0)
1299 {
1300 return false;
1301 }
1302 else
1303 {
1304 return is_same_type_in<T, T1, Ts...>(index - 1);
1305 }
1306 }
1307
1308 template <typename T, typename T0>
1309 typename etl::enable_if_t<!etl::is_same<T, T0>::value, bool> ETL_CONSTEXPR14 is_same_type_in(size_t) ETL_NOEXCEPT
1310 {
1311 return false;
1312 }
1313 } // namespace private_variant
1314
1315 //***************************************************************************
1317 //***************************************************************************
1318 template <typename T, typename... TTypes>
1319 ETL_CONSTEXPR14 bool holds_alternative(const etl::variant<TTypes...>& v) ETL_NOEXCEPT
1320 {
1321 return private_variant::is_same_type_in<T, TTypes...>(v.index());
1322 }
1323
1324 //***************************************************************************
1326 //***************************************************************************
1327 template <size_t Index, typename... TTypes>
1328 ETL_CONSTEXPR14 bool holds_alternative(const etl::variant<TTypes...>& v) ETL_NOEXCEPT
1329 {
1330 return (Index == v.index());
1331 }
1332
1333 //***************************************************************************
1335 //***************************************************************************
1336 template <typename... TTypes>
1337 ETL_CONSTEXPR14 bool holds_alternative(size_t index, const etl::variant<TTypes...>& v) ETL_NOEXCEPT
1338 {
1339 return (index == v.index());
1340 }
1341
1342 //***************************************************************************
1344 //***************************************************************************
1345 template <size_t Index, typename... TTypes>
1346 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<TTypes...> >& get(etl::variant<TTypes...>& v)
1347 {
1348 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1349 static_assert(Index < sizeof...(TTypes), "Index out of range");
1350 #endif
1351
1352 ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1353
1354 using type = etl::variant_alternative_t<Index, etl::variant<TTypes...> >;
1355
1356 return *static_cast<type*>(v.data);
1357 }
1358
1359 //***********************************
1360 template <size_t Index, typename... TTypes>
1361 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<TTypes...> >&& get(etl::variant<TTypes...>&& v)
1362 {
1363 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1364 static_assert(Index < sizeof...(TTypes), "Index out of range");
1365 #endif
1366
1367 ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1368
1369 using type = etl::variant_alternative_t<Index, etl::variant<TTypes...> >;
1370
1371 return etl::move(*static_cast<type*>(v.data));
1372 }
1373
1374 //***********************************
1375 template <size_t Index, typename... TTypes>
1376 ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<TTypes...> >& get(const etl::variant<TTypes...>& v)
1377 {
1378 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1379 static_assert(Index < sizeof...(TTypes), "Index out of range");
1380 #endif
1381
1382 ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1383
1384 using type = etl::variant_alternative_t<Index, etl::variant<TTypes...> >;
1385
1386 return *static_cast<const type*>(v.data);
1387 }
1388
1389 //***********************************
1390 template <size_t Index, typename... TTypes>
1391 ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<TTypes...> >&& get(const etl::variant<TTypes...>&& v)
1392 {
1393 #if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1394 static_assert(Index < sizeof...(TTypes), "Index out of range");
1395 #endif
1396
1397 ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1398
1399 using type = etl::variant_alternative_t<Index, etl::variant<TTypes...> >;
1400
1401 return etl::move(*static_cast<const type*>(v.data));
1402 }
1403
1404 //***********************************
1405 template <typename T, typename... TTypes>
1406 ETL_CONSTEXPR14 T& get(etl::variant<TTypes...>& v)
1407 {
1408 ETL_ASSERT((private_variant::is_same_type_in<T, TTypes...>(v.index())), ETL_ERROR(etl::variant_incorrect_type_exception));
1409
1410 return *static_cast<T*>(v.data);
1411 }
1412
1413 //***********************************
1414 template <typename T, typename... TTypes>
1415 ETL_CONSTEXPR14 T&& get(etl::variant<TTypes...>&& v)
1416 {
1417 ETL_ASSERT((private_variant::is_same_type_in<T, TTypes...>(v.index())), ETL_ERROR(etl::variant_incorrect_type_exception));
1418
1419 return etl::move(*static_cast<T*>(v.data));
1420 }
1421
1422 //***********************************
1423 template <typename T, typename... TTypes>
1424 ETL_CONSTEXPR14 const T& get(const etl::variant<TTypes...>& v)
1425 {
1426 ETL_ASSERT((private_variant::is_same_type_in<T, TTypes...>(v.index())), ETL_ERROR(etl::variant_incorrect_type_exception));
1427
1428 return *static_cast<const T*>(v.data);
1429 }
1430
1431 //***********************************
1432 template <typename T, typename... TTypes>
1433 ETL_CONSTEXPR14 const T&& get(const etl::variant<TTypes...>&& v)
1434 {
1435 ETL_ASSERT((private_variant::is_same_type_in<T, TTypes...>(v.index())), ETL_ERROR(etl::variant_incorrect_type_exception));
1436
1437 return etl::move(*static_cast<const T*>(v.data));
1438 }
1439
1440 //***************************************************************************
1442 //***************************************************************************
1443 template < size_t Index, typename... TTypes >
1444 ETL_CONSTEXPR14 etl::add_pointer_t< etl::variant_alternative_t<Index, etl::variant<TTypes...> > > get_if(etl::variant<TTypes...>* pv) ETL_NOEXCEPT
1445 {
1446 if ((pv != nullptr) && (pv->index() == Index))
1447 {
1448 return &etl::get<Index>(*pv);
1449 }
1450 else
1451 {
1452 return nullptr;
1453 }
1454 }
1455
1456 //***********************************
1457 template < size_t Index, typename... TTypes >
1458 ETL_CONSTEXPR14 etl::add_pointer_t< const etl::variant_alternative_t<Index, etl::variant<TTypes...> > > get_if(const etl::variant<TTypes...>* pv)
1459 ETL_NOEXCEPT
1460 {
1461 if ((pv != nullptr) && (pv->index() == Index))
1462 {
1463 return &etl::get<Index>(*pv);
1464 }
1465 else
1466 {
1467 return nullptr;
1468 }
1469 }
1470
1471 //***********************************
1472 template < class T, typename... TTypes >
1473 ETL_CONSTEXPR14 etl::add_pointer_t<T> get_if(etl::variant<TTypes...>* pv) ETL_NOEXCEPT
1474 {
1475 if ((pv != nullptr) && (private_variant::is_same_type_in<T, TTypes...>(pv->index())))
1476 {
1477 return static_cast<T*>(pv->data);
1478 }
1479 else
1480 {
1481 return nullptr;
1482 }
1483 }
1484
1485 //***********************************
1486 template < typename T, typename... TTypes >
1487 ETL_CONSTEXPR14 etl::add_pointer_t<const T> get_if(const etl::variant<TTypes...>* pv) ETL_NOEXCEPT
1488 {
1489 if ((pv != nullptr) && (private_variant::is_same_type_in<T, TTypes...>(pv->index())))
1490 {
1491 return static_cast<const T*>(pv->data);
1492 }
1493 else
1494 {
1495 return nullptr;
1496 }
1497 }
1498
1499 //***************************************************************************
1501 //***************************************************************************
1502 template <typename... TTypes>
1503 void swap(etl::variant<TTypes...>& lhs, etl::variant<TTypes...>& rhs)
1504 {
1505 lhs.swap(rhs);
1506 }
1507
1508 //***************************************************************************
1510 //***************************************************************************
1511 template <typename T>
1512 struct variant_size;
1513
1514 template <typename... TTypes>
1515 struct variant_size<etl::variant<TTypes...> > : etl::integral_constant<size_t, sizeof...(TTypes)>
1516 {
1517 };
1518
1519 template <typename T>
1520 struct variant_size<const T> : etl::integral_constant<size_t, variant_size<T>::value>
1521 {
1522 };
1523
1524 #if ETL_USING_CPP17
1525 template <typename... TTypes>
1526 inline constexpr size_t variant_size_v = variant_size<TTypes...>::value;
1527 #endif
1528
1529 //***************************************************************************
1531 //***************************************************************************
1532 namespace private_variant
1533 {
1534 template <typename TRet, typename TCallable, typename TVariant, size_t tIndex, typename TNext, typename... TVariants>
1535 static ETL_CONSTEXPR14 TRet do_visit_single(TCallable&& f, TVariant&& v, TNext&&, TVariants&&... vs);
1536
1537 //***************************************************************************
1541 //***************************************************************************
1542 struct visit_auto_return
1543 {
1544 };
1545
1546 //***************************************************************************
1549 //***************************************************************************
1550 template <typename TCallable, typename... Ts>
1551 struct single_visit_result_type
1552 {
1553 using type = decltype(declval<TCallable>()(declval<Ts>()...));
1554 };
1555
1556 template <typename TCallable, typename... Ts>
1557 using single_visit_result_type_t = typename single_visit_result_type<TCallable, Ts...>::type;
1558
1559 //***************************************************************************
1562 //***************************************************************************
1563 template <typename TVar, typename T>
1564 using rlref_copy = conditional_t<is_reference<TVar>::value, T&, T&&>;
1565
1566 //***************************************************************************
1574 //***************************************************************************
1575 template <template <typename...> class, typename...>
1576 struct visit_result_helper;
1577
1578 template <template <typename...> class TToInject, size_t... tAltIndices, typename TCur>
1579 struct visit_result_helper<TToInject, index_sequence<tAltIndices...>, TCur>
1580 {
1581 template <size_t tIndex>
1582 using var_type = rlref_copy<TCur, variant_alternative_t<tIndex, remove_reference_t<TCur> > >;
1583
1584 using type = common_type_t<TToInject<var_type<tAltIndices> >...>;
1585 };
1586
1587 template <template <typename...> class TToInject, size_t... tAltIndices, typename TCur, typename TNext, typename... TVs>
1588 struct visit_result_helper<TToInject, index_sequence<tAltIndices...>, TCur, TNext, TVs...>
1589 {
1590 template <size_t tIndex>
1591 using var_type = rlref_copy<TCur, variant_alternative_t<tIndex, remove_reference_t<TCur> > >;
1592
1593 template <size_t tIndex>
1594 struct next_inject_wrap
1595 {
1596 template <typename... TNextInj>
1597 using next_inject = TToInject<var_type<tIndex>, TNextInj...>;
1598 using recursive_result =
1599 typename visit_result_helper< next_inject, make_index_sequence<variant_size<remove_reference_t<TNext> >::value>, TNext, TVs...>::type;
1600 };
1601
1602 using type = common_type_t< typename next_inject_wrap<tAltIndices>::recursive_result...>;
1603 };
1604
1605 //***************************************************************************
1610 //***************************************************************************
1611 template <typename TRet, typename...>
1612 struct visit_result
1613 {
1614 using type = TRet;
1615 };
1616
1617 template <typename TCallable, typename T1, typename... Ts>
1618 struct visit_result<visit_auto_return, TCallable, T1, Ts...>
1619 {
1620 // bind TCallable to the first argument in this variadic alias.
1621 template <typename... Ts2>
1622 using single_res = single_visit_result_type_t<TCallable, Ts2...>;
1623 using type = typename visit_result_helper< single_res, make_index_sequence<variant_size<remove_reference_t<T1> >::value>, T1, Ts...>::type;
1624 };
1625
1626 template <typename... Ts>
1627 using visit_result_t = typename visit_result<Ts...>::type;
1628
1629 //***************************************************************************
1632 //***************************************************************************
1633 template <typename TRet, typename TCallable, typename TVariant, size_t tIndex>
1634 constexpr TRet do_visit_single(TCallable&& f, TVariant&& v)
1635 {
1636 return static_cast<TCallable&&>(f)(etl::get<tIndex>(static_cast<TVariant&&>(v)));
1637 }
1638
1639 //***************************************************************************
1643 //***************************************************************************
1644 template <typename TRet, typename TCallable, typename TCurVariant, typename... TVarRest>
1645 struct do_visit_helper
1646 {
1647 using function_pointer = add_pointer_t<TRet(TCallable&&, TCurVariant&&, TVarRest&&...)>;
1648
1649 template <size_t tIndex>
1650 static constexpr function_pointer fptr() ETL_NOEXCEPT
1651 {
1652 return &do_visit_single<TRet, TCallable, TCurVariant, tIndex, TVarRest...>;
1653 }
1654 };
1655
1656 //***************************************************************************
1658 //***************************************************************************
1659 template <typename TRet, typename TCallable, typename TVariant, size_t... tIndices, typename... TVarRest>
1660 static ETL_CONSTEXPR14 TRet do_visit(TCallable&& f, TVariant&& v, index_sequence<tIndices...>, TVarRest&&... variants)
1661 {
1662 ETL_ASSERT(!v.valueless_by_exception(), ETL_ERROR(bad_variant_access));
1663
1664 using helper_t = do_visit_helper<TRet, TCallable, TVariant, TVarRest...>;
1665 using func_ptr = typename helper_t::function_pointer;
1666
1667 constexpr func_ptr jmp_table[]{helper_t::template fptr<tIndices>()...};
1668
1669 return jmp_table[v.index()](static_cast<TCallable&&>(f), static_cast<TVariant&&>(v), static_cast<TVarRest&&>(variants)...);
1670 }
1671
1672 template <typename TRet, typename TCallable, typename TVariant, typename... TVs>
1673 static ETL_CONSTEXPR14 TRet visit(TCallable&& f, TVariant&& v, TVs&&... vs)
1674 {
1675 constexpr size_t variants = etl::variant_size<typename remove_reference<TVariant>::type>::value;
1676 return private_variant::do_visit<TRet>(static_cast<TCallable&&>(f), static_cast<TVariant&&>(v), make_index_sequence<variants>{},
1677 static_cast<TVs&&>(vs)...);
1678 }
1679
1680 //***************************************************************************
1683 //***************************************************************************
1684 template <typename TRet, typename TCallable, typename TVariant, size_t tIndex>
1685 class constexpr_visit_closure
1686 {
1687 add_pointer_t<TCallable> callable_;
1688 add_pointer_t<TVariant> variant_;
1689
1690 public:
1691
1692 constexpr constexpr_visit_closure(TCallable&& c, TVariant&& v)
1693 : callable_(&c)
1694 , variant_(&v)
1695 {
1696 }
1697
1698 template <typename... Ts>
1699 ETL_CONSTEXPR14 TRet operator()(Ts&&... args) const
1700 {
1701 return static_cast<TCallable&&>(*callable_)(get<tIndex>(static_cast<TVariant&&>(*variant_)), static_cast<Ts&&>(args)...);
1702 }
1703 };
1704
1705 template <typename TRet, typename TCallable, typename TVariant, size_t tIndex, typename TNext, typename... TVariants>
1706 static ETL_CONSTEXPR14 TRet do_visit_single(TCallable&& f, TVariant&& v, TNext&& next, TVariants&&... vs)
1707 {
1708 return private_variant::visit<TRet>(
1709 constexpr_visit_closure<TRet, TCallable, TVariant, tIndex>(static_cast<TCallable&&>(f), static_cast<TVariant&&>(v)),
1710 static_cast<TNext&&>(next), static_cast<TVariants&&>(vs)...);
1711 }
1712
1713 } // namespace private_variant
1714
1715 //***************************************************************************
1718 //***************************************************************************
1719 template < typename TRet = private_variant::visit_auto_return, typename... TVariants, typename TCallable,
1720 typename TDeducedReturn = private_variant::visit_result_t<TRet, TCallable, TVariants...> >
1721 static ETL_CONSTEXPR14 TDeducedReturn visit(TCallable&& f, TVariants&&... vs)
1722 {
1723 return private_variant::visit<TDeducedReturn>(static_cast<TCallable&&>(f), static_cast<TVariants&&>(vs)...);
1724 }
1725
1726 namespace private_variant
1727 {
1728 //***************************************************************************
1732 //***************************************************************************
1733 template <typename TVariant>
1734 struct equality_visitor
1735 {
1736 equality_visitor(const TVariant& rhs_)
1737 : rhs(rhs_)
1738 {
1739 }
1740
1741 template <typename TValue>
1742 bool operator()(const TValue& lhs_downcasted)
1743 {
1744 return lhs_downcasted == etl::get<TValue>(rhs);
1745 }
1746
1747 const TVariant& rhs;
1748 };
1749
1750 //***************************************************************************
1754 //***************************************************************************
1755 template <typename TVariant>
1756 struct less_than_visitor
1757 {
1758 less_than_visitor(const TVariant& rhs_)
1759 : rhs(rhs_)
1760 {
1761 }
1762
1763 template <typename TValue>
1764 bool operator()(const TValue& lhs_downcasted)
1765 {
1766 return lhs_downcasted < etl::get<TValue>(rhs);
1767 }
1768
1769 const TVariant& rhs;
1770 };
1771 } // namespace private_variant
1772
1773 //***************************************************************************
1776 //***************************************************************************
1777 template <typename... TTypes>
1778 ETL_CONSTEXPR14 bool operator==(const etl::variant<TTypes...>& lhs, const etl::variant<TTypes...>& rhs)
1779 {
1780 // If both variants are valueless, they are considered equal
1781 if (lhs.valueless_by_exception() && rhs.valueless_by_exception())
1782 {
1783 return true;
1784 }
1785
1786 // If one variant is valueless and the other is not, they are not equal
1787 if (lhs.valueless_by_exception() || rhs.valueless_by_exception())
1788 {
1789 return false;
1790 }
1791
1792 // If variants have different types, they are not equal
1793 if (lhs.index() != rhs.index())
1794 {
1795 return false;
1796 }
1797
1798 // Variants have the same type, apply the equality operator for the
1799 // contained values
1800 private_variant::equality_visitor<etl::variant<TTypes...> > visitor(rhs);
1801
1802 return etl::visit(visitor, lhs);
1803 }
1804
1805 //***************************************************************************
1808 //***************************************************************************
1809 template <typename... TTypes>
1810 ETL_CONSTEXPR14 bool operator!=(const etl::variant<TTypes...>& lhs, const etl::variant<TTypes...>& rhs)
1811 {
1812 return !(lhs == rhs);
1813 }
1814
1815 //***************************************************************************
1818 //***************************************************************************
1819 template <typename... TTypes>
1820 ETL_CONSTEXPR14 bool operator<(const etl::variant<TTypes...>& lhs, const etl::variant<TTypes...>& rhs)
1821 {
1822 // If both variants are valueless, they are considered equal, so not less
1823 // than
1824 if (lhs.valueless_by_exception() && rhs.valueless_by_exception())
1825 {
1826 return false;
1827 }
1828
1829 // A valueless variant is always less than a variant with a value
1830 if (lhs.valueless_by_exception())
1831 {
1832 return true;
1833 }
1834
1835 // A variant with a value is never less than a valueless variant
1836 if (rhs.valueless_by_exception())
1837 {
1838 return false;
1839 }
1840
1841 // If variants have different types, compare the type index
1842 if (lhs.index() != rhs.index())
1843 {
1844 return lhs.index() < rhs.index();
1845 }
1846
1847 // Variants have the same type, apply the less than operator for the
1848 // contained values
1849 private_variant::less_than_visitor<etl::variant<TTypes...> > visitor(rhs);
1850
1851 return etl::visit(visitor, lhs);
1852 }
1853
1854 //***************************************************************************
1857 //***************************************************************************
1858 template <typename... TTypes>
1859 ETL_CONSTEXPR14 bool operator>(const etl::variant<TTypes...>& lhs, const etl::variant<TTypes...>& rhs)
1860 {
1861 return (rhs < lhs);
1862 }
1863
1864 //***************************************************************************
1867 //***************************************************************************
1868 template <typename... TTypes>
1869 ETL_CONSTEXPR14 bool operator<=(const etl::variant<TTypes...>& lhs, const etl::variant<TTypes...>& rhs)
1870 {
1871 return !(lhs > rhs);
1872 }
1873
1874 //***************************************************************************
1877 //***************************************************************************
1878 template <typename... TTypes>
1879 ETL_CONSTEXPR14 bool operator>=(const etl::variant<TTypes...>& lhs, const etl::variant<TTypes...>& rhs)
1880 {
1881 return !(lhs < rhs);
1882 }
1883
1884 namespace private_variant
1885 {
1886 #if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
1887 //***************************************************************************
1891 //***************************************************************************
1892 template <typename TVariant>
1893 struct compare_visitor
1894 {
1895 compare_visitor(const TVariant& rhs_)
1896 : rhs(rhs_)
1897 {
1898 }
1899
1900 template <typename TValue>
1901 std::strong_ordering operator()(const TValue& lhs_downcasted)
1902 {
1903 return lhs_downcasted <=> etl::get<TValue>(rhs);
1904 }
1905
1906 const TVariant& rhs;
1907 };
1908 #endif
1909 } // namespace private_variant
1910
1911 //***************************************************************************
1915 //***************************************************************************
1916 #if ETL_USING_CPP20 && ETL_USING_STL && !(defined(ETL_DEVELOPMENT_OS_APPLE) && defined(ETL_COMPILER_CLANG))
1917 template <typename... TTypes>
1918 ETL_CONSTEXPR14 std::common_comparison_category_t< std::compare_three_way_result_t<TTypes>...> operator<=>(const etl::variant<TTypes...>& lhs,
1919 const etl::variant<TTypes...>& rhs)
1920 {
1921 if (lhs.valueless_by_exception() && rhs.valueless_by_exception())
1922 {
1923 return std::strong_ordering::equal;
1924 }
1925 else if (lhs.valueless_by_exception())
1926 {
1927 return std::strong_ordering::less;
1928 }
1929 else if (rhs.valueless_by_exception())
1930 {
1931 return std::strong_ordering::greater;
1932 }
1933 else if (lhs.index() != rhs.index())
1934 {
1935 return lhs.index() <=> rhs.index();
1936 }
1937 else
1938 {
1939 // Variants have the same type, apply the equality operator for the
1940 // contained values
1941 private_variant::compare_visitor<etl::variant<TTypes...> > visitor(rhs);
1942
1943 return etl::visit(visitor, lhs);
1944 }
1945 }
1946 #endif
1947
1948 //***************************************************************************
1950 template <typename TList>
1951 struct variant_from_type_list;
1952
1953 template <typename... TTypes>
1954 struct variant_from_type_list<etl::type_list<TTypes...> >
1955 {
1956 using type = etl::variant<TTypes...>;
1957 };
1958
1959 template <typename TTypeList>
1960 using variant_from_type_list_t = typename variant_from_type_list<TTypeList>::type;
1961} // namespace etl
1962#endif
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
Definition exception.h:59
static bool is_supported_type()
Definition variant_legacy.h:889
~variant()
Destructor.
Definition variant_legacy.h:224
bool is_same_type(const variant &other) const
Definition variant_legacy.h:642
T & get()
Definition variant_legacy.h:738
variant & operator=(const T &value)
Definition variant_legacy.h:597
bool is_type() const
Definition variant_legacy.h:710
T & emplace()
Emplace with one constructor parameter.
Definition variant_legacy.h:520
size_t index() const
Gets the index of the type currently stored or UNSUPPORTED_TYPE_ID.
Definition variant_legacy.h:718
Definition variant_legacy.h:115
Definition variant_legacy.h:146
Definition variant_legacy.h:87
Definition variant_legacy.h:101
etl::monostate monostate
Definition variant_legacy.h:80
Definition visitor.h:237
bitset_ext
Definition absolute.h:40
ETL_CONSTEXPR14 void swap(etl::typed_storage_ext< T > &lhs, etl::typed_storage_ext< T > &rhs) ETL_NOEXCEPT
Swap two etl::typed_storage_ext.
Definition alignment.h:856
ETL_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1081
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1133
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1147
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1093
T & get(array< T, Size > &a)
Definition array.h:1161
ETL_DEPRECATED_REASON("Misspelt class name") typedef scheduler_policy_sequential_single scheduler_policy_sequencial_single
Typedef for backwards compatibility with miss-spelt struct name.
bool operator<(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1106
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1120
A 'no-value' placeholder.
Definition monostate.h:42
Definition variant_legacy.h:989