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