Embedded Template Library 1.0
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 "../exception.h"
35#include "../type_traits.h"
36#include "../integral_limits.h"
37#include "../static_assert.h"
38#include "../alignment.h"
39#include "../error_handler.h"
40#include "../parameter_pack.h"
41#include "../placement_new.h"
42#include "../visitor.h"
43#include "../memory.h"
44#include "../initializer_list.h"
45
46#include <stdint.h>
47
48#if defined(ETL_COMPILER_KEIL)
49 #pragma diag_suppress 940
50 #pragma diag_suppress 111
51#endif
52
53#if ETL_CPP11_NOT_SUPPORTED
54 #if !defined(ETL_IN_UNIT_TEST)
55 #error NOT SUPPORTED FOR C++03 OR BELOW
56 #endif
57#else
58//*****************************************************************************
62//*****************************************************************************
63
64namespace etl
65{
66 namespace private_variant
67 {
68 //***************************************************************************
69 // This is a copy of the normal etl::parameter_pack, but without the static_assert
70 // so that the C++11 versions of do_visitor() & do_operator() do not throw a compile time error.
71 //***************************************************************************
72 template <typename... TTypes>
73 class parameter_pack
74 {
75 public:
76
77 static constexpr size_t size = sizeof...(TTypes);
78
79 //***************************************************************************
81 //***************************************************************************
82 template <typename T>
83 class index_of_type
84 {
85 private:
86
87 using type = etl::remove_cvref_t<T>;
88
89 //***********************************
90 template <typename Type, typename T1, typename... TRest>
91 struct index_of_type_helper
92 {
93 static constexpr size_t value = etl::is_same<Type, T1>::value ? 1 : 1 + index_of_type_helper<Type, TRest...>::value;
94 };
95
96 //***********************************
97 template <typename Type, typename T1>
98 struct index_of_type_helper<Type, T1>
99 {
100 static constexpr size_t value = 1UL;
101 };
102
103 public:
104
105 static_assert(etl::is_one_of<type, TTypes...>::value, "T is not in parameter pack");
106
108 static constexpr size_t value = index_of_type_helper<type, TTypes...>::value - 1;
109 };
110
111 //***************************************************************************
113 //***************************************************************************
114 template <size_t I>
115 class type_from_index
116 {
117 private:
118
119 //***********************************
120 template <size_t II, size_t N, typename T1, typename... TRest>
121 struct type_from_index_helper
122 {
123 using type = typename etl::conditional<II == N, T1, typename type_from_index_helper<II, N + 1, TRest...>::type>::type;
124 };
125
126 //***********************************
127 template <size_t II, size_t N, typename T1>
128 struct type_from_index_helper<II, N, T1>
129 {
130 using type = T1;
131 };
132
133 public:
134
136 using type = typename type_from_index_helper<I, 0, TTypes...>::type;
137 };
138
139 //***********************************
140 template <size_t I>
141 using type_from_index_t = typename type_from_index<I>::type;
142 };
143
144 //*******************************************
145 // The traits an object may have.
146 //*******************************************
147 static constexpr bool Copyable = true;
148 static constexpr bool Non_Copyable = false;
149 static constexpr bool Moveable = true;
150 static constexpr bool Non_Moveable = false;
151
152 //*******************************************
153 // The types of operations we can perform.
154 //*******************************************
155 static constexpr int Copy = 0;
156 static constexpr int Move = 1;
157 static constexpr int Destroy = 2;
158
159 //*******************************************
160 // operation_type
161 //*******************************************
162 template <typename T, bool IsCopyable, bool IsMoveable>
163 struct operation_type;
164
165 //*******************************************
166 // Specialisation for null operation.
167 template <>
168 struct operation_type<void, Non_Copyable, Non_Moveable>
169 {
170 static void do_operation(int , char* , const char* )
171 {
172 // This should never occur.
173#if defined(ETL_IN_UNIT_TEST)
174 assert(false);
175#endif
176 }
177 };
178
179 //*******************************************
180 // Specialisation for no-copyable & non-moveable types.
181 template <typename T>
182 struct operation_type<T, Non_Copyable, Non_Moveable>
183 {
184 static void do_operation(int operation, char* pstorage, const char* /*pvalue*/)
185 {
186 switch (operation)
187 {
188 case Destroy:
189 {
190 reinterpret_cast<const T*>(pstorage)->~T();
191 break;
192 }
193
194 default:
195 {
196 // This should never occur.
197 #if defined(ETL_IN_UNIT_TEST)
198 assert(false);
199 #endif
200 break;
201 }
202 }
203 }
204 };
205
206 //*******************************************
207 // Specialisation for no-copyable & moveable types.
208 template <typename T>
209 struct operation_type<T, Non_Copyable, Moveable>
210 {
211 static void do_operation(int operation, char* pstorage, const char* pvalue)
212 {
213 switch (operation)
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_DEBUG)
231 assert(false);
232 #endif
233 break;
234 }
235 }
236 }
237 };
238
239 //*******************************************
240 // Specialisation for copyable & non-moveable types.
241 template <typename T>
242 struct operation_type<T, Copyable, Non_Moveable>
243 {
244 static void do_operation(int operation, char* pstorage, const char* pvalue)
245 {
246 switch (operation)
247 {
248 case Copy:
249 {
250 ::new (pstorage) T(*reinterpret_cast<const T*>(pvalue));
251 break;
252 }
253
254 case Destroy:
255 {
256 reinterpret_cast<const T*>(pstorage)->~T();
257 break;
258 }
259
260 default:
261 {
262 // This should never occur.
263 #if defined(ETL_IN_UNIT_TEST)
264 assert(false);
265 #endif
266 break;
267 }
268 }
269 }
270 };
271
272 //*******************************************
273 // Specialisation for copyable & moveable types.
274 template <typename T>
275 struct operation_type<T, Copyable, Moveable>
276 {
277 static void do_operation(int operation, char* pstorage, const char* pvalue)
278 {
279 switch (operation)
280 {
281 case Copy:
282 {
283 ::new (pstorage) T(*reinterpret_cast<const T*>(pvalue));
284 break;
285 }
286
287 case Move:
288 {
289 ::new (pstorage) T(etl::move(*reinterpret_cast<T*>(const_cast<char*>(pvalue))));
290 break;
291 }
292
293 case Destroy:
294 {
295 reinterpret_cast<const T*>(pstorage)->~T();
296 break;
297 }
298
299 default:
300 {
301 // This should never occur.
302#if defined(ETL_IN_UNIT_TEST)
303 assert(false);
304#endif
305 break;
306 }
307 }
308 }
309 };
310 }
311
313 constexpr size_t variant_npos = etl::integral_limits<size_t>::max;
314
315 //***********************************
316 // variant. Forward declaration
317 template <typename... TTypes>
318 class variant;
319
320 //***************************************************************************
322 //***************************************************************************
323 template <size_t Index, typename T>
324 struct variant_alternative;
325
326 template <size_t Index, typename... TTypes>
327 struct variant_alternative<Index, etl::variant<TTypes...>>
328 {
329 using type = typename etl::private_variant::parameter_pack<TTypes...>::template type_from_index<Index>::type;
330 };
331
332 template <size_t Index, typename T>
333 struct variant_alternative<Index, const T>
334 {
335 using type = typename variant_alternative<Index, T>::type;
336 };
337
338 template <size_t Index, typename T>
339 using variant_alternative_t = typename variant_alternative<Index, T>::type;
340
341 //***********************************
342 // holds_alternative. Forward declaration
343 template <typename T, typename... TTypes>
344 ETL_CONSTEXPR14 bool holds_alternative(const etl::variant<TTypes...>& v) noexcept;
345
346 //***********************************
347 // get. Forward declarations
348 template <size_t Index, typename... VTypes>
349 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...>>&
351
352 template <size_t Index, typename... VTypes>
353 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...>>&&
355
356 template <size_t Index, typename... VTypes>
357 ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<VTypes...>>&
359
360 template <size_t Index, typename... VTypes>
361 ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<VTypes...>>&&
362 get(const etl::variant<VTypes...>&& v);
363
364 template <typename T, typename... VTypes>
365 ETL_CONSTEXPR14 T& get(etl::variant<VTypes...>& v);
366
367 template <typename T, typename... VTypes>
368 ETL_CONSTEXPR14 T&& get(etl::variant<VTypes...>&& v);
369
370 template <typename T, typename... VTypes>
371 ETL_CONSTEXPR14 const T& get(const etl::variant<VTypes...>& v);
372
373 template <typename T, typename... VTypes>
374 ETL_CONSTEXPR14 const T&& get(const etl::variant<VTypes...>&& v);
375
376 //***************************************************************************
379 //***************************************************************************
380 struct monostate
381 {
382 };
383
384 constexpr bool operator >(etl::monostate, etl::monostate) noexcept { return false; }
385 constexpr bool operator <(etl::monostate, etl::monostate) noexcept { return false; }
386 constexpr bool operator !=(etl::monostate, etl::monostate) noexcept { return false; }
387 constexpr bool operator <=(etl::monostate, etl::monostate) noexcept { return true; }
388 constexpr bool operator >=(etl::monostate, etl::monostate) noexcept { return true; }
389 constexpr bool operator ==(etl::monostate, etl::monostate) noexcept { return true; }
390
391#if ETL_NOT_USING_STL && !defined(ETL_USE_TYPE_TRAITS_BUILTINS)
392 template <>
393 struct is_copy_constructible<etl::monostate> : public etl::true_type
394 {
395 };
396
397 template <>
398 struct is_move_constructible<etl::monostate> : public etl::true_type
399 {
400 };
401#endif
402
403 //***************************************************************************
406 //***************************************************************************
407 class variant_exception : public exception
408 {
409 public:
410 variant_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
411 : exception(reason_, file_name_, line_number_)
412 {
413 }
414 };
415
416 //***************************************************************************
419 //***************************************************************************
420 class variant_incorrect_type_exception : public variant_exception
421 {
422 public:
423 variant_incorrect_type_exception(string_type file_name_, numeric_type line_number_)
424 : variant_exception(ETL_ERROR_TEXT("variant:unsupported type", ETL_VARIANT_FILE_ID"A"), file_name_, line_number_)
425 {
426 }
427 };
428
429 //***************************************************************************
432 //***************************************************************************
433 class bad_variant_access : public variant_exception
434 {
435 public:
436 bad_variant_access(string_type file_name_, numeric_type line_number_)
437 : variant_exception(ETL_ERROR_TEXT("variant:bad variant access", ETL_VARIANT_FILE_ID"B"), file_name_, line_number_)
438 {}
439 };
440
441 //***************************************************************************
445 //***************************************************************************
446 template <typename... TTypes>
447 class variant
448 {
449 public:
450
451 //***************************************************************************
453 //***************************************************************************
454 using type_id_t = uint_least8_t ;
455
456 //***************************************************************************
458 //***************************************************************************
459 template <size_t Index, typename... VTypes>
460 friend ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...>>&
462
463 template <size_t Index, typename... VTypes>
464 friend ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<VTypes...>>&&
466
467 template <size_t Index, typename... VTypes>
468 friend ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<VTypes...>>&
470
471 template <size_t Index, typename... VTypes>
472 friend ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<VTypes...>>&&
473 get(const etl::variant<VTypes...>&& v);
474
475 template <typename T, typename... VTypes>
476 friend ETL_CONSTEXPR14 T& get(etl::variant<VTypes...>& v);
477
478 template <typename T, typename... VTypes>
479 friend ETL_CONSTEXPR14 T&& get(etl::variant<VTypes...>&& v);
480
481 template <typename T, typename... VTypes>
482 friend ETL_CONSTEXPR14 const T& get(const etl::variant<VTypes...>& v);
483
484 template <typename T, typename... VTypes>
485 friend ETL_CONSTEXPR14 const T&& get(const etl::variant<VTypes...>&& v);
486
487 private:
488
489 // All types of variant are friends.
490 template <typename... UTypes>
491 friend class variant;
492
493 //***************************************************************************
495 //***************************************************************************
496 using largest_t = typename largest_type<TTypes...>::type;
497
498 //***************************************************************************
500 //***************************************************************************
501 static const size_t Size = sizeof(largest_t);
502
503 //***************************************************************************
505 //***************************************************************************
506 static const size_t Alignment = etl::largest_alignment<TTypes...>::value;
507
508 //***************************************************************************
510 //***************************************************************************
511 template <typename T, bool IsCopyable, bool IsMoveable>
512 using operation_type = private_variant::operation_type<T, IsCopyable, IsMoveable>;
513
514 //*******************************************
515 // The types of operations we can perform.
516 //*******************************************
517 static constexpr int Copy = private_variant::Copy;
518 static constexpr int Move = private_variant::Move;
519 static constexpr int Destroy = private_variant::Destroy;
520
521 public:
522
523 //***************************************************************************
526 //***************************************************************************
528 ETL_CONSTEXPR14 variant()
529 {
530 using type = typename etl::private_variant::parameter_pack<TTypes...>::template type_from_index<0U>::type;
531
532 default_construct_in_place<type>(data);
533 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
534 type_id = 0U;
535 }
537
538 //***************************************************************************
540 //***************************************************************************
542 template <typename T, etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value, int> = 0>
543 ETL_CONSTEXPR14 variant(T&& value)
544 : 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)
545 , type_id(etl::private_variant::parameter_pack<TTypes...>::template index_of_type<etl::remove_cvref_t<T>>::value)
546 {
547 static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
548
549 construct_in_place<etl::remove_cvref_t<T>>(data, etl::forward<T>(value));
550 }
552
553 //***************************************************************************
555 //***************************************************************************
557 template <typename T, typename... TArgs>
558 ETL_CONSTEXPR14 explicit variant(etl::in_place_type_t<T>, TArgs&&... args)
559 : 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)
560 , type_id(etl::private_variant::parameter_pack<TTypes...>::template index_of_type<etl::remove_cvref_t<T>>::value)
561 {
562 static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...>::value, "Unsupported type");
563
564 construct_in_place_args<etl::remove_cvref_t<T>>(data, etl::forward<TArgs>(args)...);
565 }
567
568 //***************************************************************************
570 //***************************************************************************
572 template <size_t Index, typename... TArgs>
573 ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t<Index>, TArgs&&... args)
574 : type_id(Index)
575 {
576 using type = typename private_variant::parameter_pack<TTypes...>:: template type_from_index_t<Index>;
577 static_assert(etl::is_one_of<type, TTypes...> ::value, "Unsupported type");
578
579 construct_in_place_args<type>(data, etl::forward<TArgs>(args)...);
580
581 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
582 }
584
585#if ETL_HAS_INITIALIZER_LIST
586 //***************************************************************************
588 //***************************************************************************
590 template <typename T, typename U, typename... TArgs >
591 ETL_CONSTEXPR14 explicit variant(etl::in_place_type_t<T>, std::initializer_list<U> init, TArgs&&... args)
592 : 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)
593 , type_id(private_variant::parameter_pack<TTypes...>:: template index_of_type<etl::remove_cvref_t<T>>::value)
594 {
595 static_assert(etl::is_one_of<etl::remove_cvref_t<T>, TTypes...> ::value, "Unsupported type");
596
597 construct_in_place_args<etl::remove_cvref_t<T>>(data, init, etl::forward<TArgs>(args)...);
598 }
600
601 //***************************************************************************
603 //***************************************************************************
605 template <size_t Index, typename U, typename... TArgs >
606 ETL_CONSTEXPR14 explicit variant(etl::in_place_index_t<Index>, std::initializer_list<U> init, TArgs&&... args)
607 : type_id(Index)
608 {
609 using type = typename private_variant::parameter_pack<TTypes...>:: template type_from_index_t<Index>;
610 static_assert(etl::is_one_of<type, TTypes...> ::value, "Unsupported type");
611
612 construct_in_place_args<type>(data, init, etl::forward<TArgs>(args)...);
613
614 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
615 }
617#endif
618
619 //***************************************************************************
622 //***************************************************************************
624 ETL_CONSTEXPR14 variant(const variant& other)
625 : operation(other.operation)
626 , type_id(other.type_id)
627 {
628 if (this != &other)
629 {
630 if (other.index() == variant_npos)
631 {
632 type_id = variant_npos;
633 }
634 else
635 {
636 operation(private_variant::Copy, data, other.data);
637 }
638 }
639 }
641
642 //***************************************************************************
645 //***************************************************************************
647 ETL_CONSTEXPR14 variant(variant&& other)
648 : operation(other.operation)
649 , type_id(other.type_id)
650 {
651 if (this != &other)
652 {
653 if (other.index() == variant_npos)
654 {
655 type_id = variant_npos;
656 }
657 else
658 {
659 operation(private_variant::Move, data, other.data);
660 }
661 }
662 else
663 {
664 type_id = variant_npos;
665 }
666 }
668
669 //***************************************************************************
671 //***************************************************************************
672 ~variant()
673 {
674 if (index() != variant_npos)
675 {
676 operation(private_variant::Destroy, data, nullptr);
677 }
678
679 operation = operation_type<void, false, false>::do_operation; // Null operation.
680 type_id = variant_npos;
681 }
682
683 //***************************************************************************
685 //***************************************************************************
686 template <typename T, typename... TArgs>
687 T& emplace(TArgs&&... args)
688 {
689 static_assert(etl::is_one_of<T, TTypes...>::value, "Unsupported type");
690
691 using type = etl::remove_cvref_t<T>;
692
693 operation(private_variant::Destroy, data, nullptr);
694
695 construct_in_place_args<type>(data, etl::forward<TArgs>(args)...);
696
697 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
698
699 type_id = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
700
701 return *static_cast<T*>(data);
702 }
703
704 //***************************************************************************
706 //***************************************************************************
707 template <size_t Index, typename... TArgs>
708 typename etl::variant_alternative<Index, variant<TArgs...>>::type emplace(TArgs&&... args)
709 {
710 static_assert(Index < etl::private_variant::parameter_pack<TTypes...>::size, "Index out of range");
711
712 using type = typename etl::private_variant::parameter_pack<TTypes...>::template type_from_index<Index>::type;
713
714 operation(private_variant::Destroy, data, nullptr);
715
716 construct_in_place_args<type>(data, etl::forward<TArgs>(args)...);
717
718 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
719
720 type_id = Index;
721
722 return *static_cast<type*>(data);
723 }
724
725 //***************************************************************************
728 //***************************************************************************
729 template <typename T, etl::enable_if_t<!etl::is_same<etl::remove_cvref_t<T>, variant>::value, int> = 0>
730 variant& operator =(T&& value)
731 {
732 using type = etl::remove_cvref_t<T>;
733
734 static_assert(etl::is_one_of<type, TTypes...>::value, "Unsupported type");
735
736 operation(private_variant::Destroy, data, nullptr);
737
738 construct_in_place<type>(data, etl::forward<T>(value));
739
740 operation = operation_type<type, etl::is_copy_constructible<type>::value, etl::is_move_constructible<type>::value>::do_operation;
741 type_id = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<type>::value;
742
743 return *this;
744 }
745
746 //***************************************************************************
749 //***************************************************************************
750 variant& operator =(const variant& other)
751 {
752 if (this != &other)
753 {
754 if (other.index() == variant_npos)
755 {
756 type_id = variant_npos;
757 }
758 else
759 {
760 operation(Destroy, data, nullptr);
761
762 operation = other.operation;
763 operation(Copy, data, other.data);
764
765 type_id = other.type_id;
766 }
767 }
768
769 return *this;
770 }
771
772 //***************************************************************************
775 //***************************************************************************
776 variant& operator =(variant&& other)
777 {
778 if (this != &other)
779 {
780 if (other.index() == variant_npos)
781 {
782 type_id = variant_npos;
783 }
784 else
785 {
786 operation(Destroy, data, nullptr);
787
788 operation = other.operation;
789 operation(Move, data, other.data);
790
791 type_id = other.type_id;
792 }
793 }
794
795 return *this;
796 }
797
798 //***************************************************************************
801 //***************************************************************************
802 constexpr bool valueless_by_exception() const noexcept
803 {
804 return type_id == variant_npos;
805 }
806
807 //***************************************************************************
809 //***************************************************************************
810 constexpr size_t index() const noexcept
811 {
812 return type_id;
813 }
814
815 //***************************************************************************
817 //***************************************************************************
818 void swap(variant& rhs) noexcept
819 {
820 variant temp(etl::move(*this));
821 *this = etl::move(rhs);
822 rhs = etl::move(temp);
823 }
824
825 //***************************************************************************
827 //***************************************************************************
828 template <typename TVisitor>
829 etl::enable_if_t<etl::is_visitor<TVisitor>::value, void>
830 accept(TVisitor& v)
831 {
832#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
833 do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
834#else
835 do_visitor(v);
836#endif
837 }
838
839 //***************************************************************************
841 //***************************************************************************
842 template <typename TVisitor>
843 etl::enable_if_t<etl::is_visitor<TVisitor>::value, void>
844 accept(TVisitor& v) const
845 {
846#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
847 do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
848#else
849 do_visitor(v);
850#endif
851 }
852
853 //***************************************************************************
855 //***************************************************************************
856 template <typename TVisitor>
857 etl::enable_if_t<!etl::is_visitor<TVisitor>::value, void>
858 accept(TVisitor& v)
859 {
860#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
861 do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
862#else
863 do_operator(v);
864#endif
865 }
866
867 //***************************************************************************
869 //***************************************************************************
870 template <typename TVisitor>
871 etl::enable_if_t<!etl::is_visitor<TVisitor>::value, void>
872 accept(TVisitor& v) const
873 {
874#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
875 do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
876#else
877 do_operator(v);
878#endif
879 }
880
881 //***************************************************************************
884 //***************************************************************************
885 template <typename TVisitor>
886#if !defined(ETL_IN_UNIT_TEST)
887 ETL_DEPRECATED_REASON("Replace with accept()")
888#endif
889 void accept_visitor(TVisitor& v)
890 {
891#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
892 do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
893#else
894 do_visitor(v);
895#endif
896 }
897
898 //***************************************************************************
901 //***************************************************************************
902 template <typename TVisitor>
903#if !defined(ETL_IN_UNIT_TEST)
904 ETL_DEPRECATED_REASON("Replace with accept()")
905#endif
906 void accept_visitor(TVisitor& v) const
907 {
908#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
909 do_visitor(v, etl::make_index_sequence<sizeof...(TTypes)>{});
910#else
911 do_visitor(v);
912#endif
913 }
914
915 //***************************************************************************
918 //***************************************************************************
919 template <typename TVisitor>
920#if !defined(ETL_IN_UNIT_TEST)
921 ETL_DEPRECATED_REASON("Replace with accept()")
922#endif
923 void accept_functor(TVisitor& v)
924 {
925#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
926 do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
927#else
928 do_operator(v);
929#endif
930 }
931
932 //***************************************************************************
935 //***************************************************************************
936 template <typename TVisitor>
937#if !defined(ETL_IN_UNIT_TEST)
938 ETL_DEPRECATED_REASON("Replace with accept()")
939#endif
940 void accept_functor(TVisitor& v) const
941 {
942#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
943 do_operator(v, etl::make_index_sequence<sizeof...(TTypes)>{});
944#else
945 do_operator(v);
946#endif
947 }
948
949 private:
950
952 using operation_function = void(*)(int, char*, const char*);
953
954 //***************************************************************************
956 //***************************************************************************
957 template <typename T>
958 static void construct_in_place(char* pstorage, const T& value)
959 {
960 using type = etl::remove_cvref_t<T>;
961
962 ::new (pstorage) type(value);
963 }
964
965 //***************************************************************************
967 //***************************************************************************
968 template <typename T>
969 static void construct_in_place(char* pstorage, T&& value)
970 {
971 using type = etl::remove_cvref_t<T>;
972
973 ::new (pstorage) type(etl::move(value));
974 }
975
976 //***************************************************************************
978 //***************************************************************************
979 template <typename T, typename... TArgs>
980 static void construct_in_place_args(char* pstorage, TArgs&&... args)
981 {
982 using type = etl::remove_cvref_t<T>;
983
984 ::new (pstorage) type(etl::forward<TArgs>(args)...);
985 }
986
987 //***************************************************************************
989 //***************************************************************************
990 template <typename T>
991 static void default_construct_in_place(char* pstorage)
992 {
993 using type = etl::remove_cvref_t<T>;
994
995 ::new (pstorage) type();
996 }
997
998#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
999 //***************************************************************************
1001 //***************************************************************************
1002 template <typename TVisitor, size_t... I>
1003 void do_visitor(TVisitor& visitor, etl::index_sequence<I...>)
1004 {
1005 (attempt_visitor<I>(visitor) || ...);
1006 }
1007
1008 //***************************************************************************
1010 //***************************************************************************
1011 template <typename TVisitor, size_t... I>
1012 void do_visitor(TVisitor& visitor, etl::index_sequence<I...>) const
1013 {
1014 (attempt_visitor<I>(visitor) || ...);
1015 }
1016#else
1017 //***************************************************************************
1019 //***************************************************************************
1020 template <typename TVisitor>
1021 void do_visitor(TVisitor& visitor)
1022 {
1023 switch (index())
1024 {
1025 case 0: { visitor.visit(etl::get<0>(*this)); break; }
1026 case 1: { visitor.visit(etl::get<1>(*this)); break; }
1027 case 2: { visitor.visit(etl::get<2>(*this)); break; }
1028 case 3: { visitor.visit(etl::get<3>(*this)); break; }
1029 case 4: { visitor.visit(etl::get<4>(*this)); break; }
1030 case 5: { visitor.visit(etl::get<5>(*this)); break; }
1031 case 6: { visitor.visit(etl::get<6>(*this)); break; }
1032 case 7: { visitor.visit(etl::get<7>(*this)); break; }
1033#if !defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1034 case 8: { visitor.visit(etl::get<8>(*this)); break; }
1035 case 9: { visitor.visit(etl::get<9>(*this)); break; }
1036 case 10: { visitor.visit(etl::get<10>(*this)); break; }
1037 case 11: { visitor.visit(etl::get<11>(*this)); break; }
1038 case 12: { visitor.visit(etl::get<12>(*this)); break; }
1039 case 13: { visitor.visit(etl::get<13>(*this)); break; }
1040 case 14: { visitor.visit(etl::get<14>(*this)); break; }
1041 case 15: { visitor.visit(etl::get<15>(*this)); break; }
1042#if !defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1043 case 16: { visitor.visit(etl::get<16>(*this)); break; }
1044 case 17: { visitor.visit(etl::get<17>(*this)); break; }
1045 case 18: { visitor.visit(etl::get<18>(*this)); break; }
1046 case 19: { visitor.visit(etl::get<19>(*this)); break; }
1047 case 20: { visitor.visit(etl::get<20>(*this)); break; }
1048 case 21: { visitor.visit(etl::get<21>(*this)); break; }
1049 case 22: { visitor.visit(etl::get<22>(*this)); break; }
1050 case 23: { visitor.visit(etl::get<23>(*this)); break; }
1051#if !defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1052 case 24: { visitor.visit(etl::get<24>(*this)); break; }
1053 case 25: { visitor.visit(etl::get<25>(*this)); break; }
1054 case 26: { visitor.visit(etl::get<26>(*this)); break; }
1055 case 27: { visitor.visit(etl::get<27>(*this)); break; }
1056 case 28: { visitor.visit(etl::get<28>(*this)); break; }
1057 case 29: { visitor.visit(etl::get<29>(*this)); break; }
1058 case 30: { visitor.visit(etl::get<30>(*this)); break; }
1059 case 31: { visitor.visit(etl::get<31>(*this)); break; }
1060#endif
1061#endif
1062#endif
1063 default: break;
1064 }
1065 }
1066
1067 //***************************************************************************
1069 //***************************************************************************
1070 template <typename TVisitor>
1071 void do_visitor(TVisitor& visitor) const
1072 {
1073 switch (index())
1074 {
1075 case 0: { visitor.visit(etl::get<0>(*this)); break; }
1076 case 1: { visitor.visit(etl::get<1>(*this)); break; }
1077 case 2: { visitor.visit(etl::get<2>(*this)); break; }
1078 case 3: { visitor.visit(etl::get<3>(*this)); break; }
1079 case 4: { visitor.visit(etl::get<4>(*this)); break; }
1080 case 5: { visitor.visit(etl::get<5>(*this)); break; }
1081 case 6: { visitor.visit(etl::get<6>(*this)); break; }
1082 case 7: { visitor.visit(etl::get<7>(*this)); break; }
1083#if !defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1084 case 8: { visitor.visit(etl::get<8>(*this)); break; }
1085 case 9: { visitor.visit(etl::get<9>(*this)); break; }
1086 case 10: { visitor.visit(etl::get<10>(*this)); break; }
1087 case 11: { visitor.visit(etl::get<11>(*this)); break; }
1088 case 12: { visitor.visit(etl::get<12>(*this)); break; }
1089 case 13: { visitor.visit(etl::get<13>(*this)); break; }
1090 case 14: { visitor.visit(etl::get<14>(*this)); break; }
1091 case 15: { visitor.visit(etl::get<15>(*this)); break; }
1092#if !defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1093 case 16: { visitor.visit(etl::get<16>(*this)); break; }
1094 case 17: { visitor.visit(etl::get<17>(*this)); break; }
1095 case 18: { visitor.visit(etl::get<18>(*this)); break; }
1096 case 19: { visitor.visit(etl::get<19>(*this)); break; }
1097 case 20: { visitor.visit(etl::get<20>(*this)); break; }
1098 case 21: { visitor.visit(etl::get<21>(*this)); break; }
1099 case 22: { visitor.visit(etl::get<22>(*this)); break; }
1100 case 23: { visitor.visit(etl::get<23>(*this)); break; }
1101#if !defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1102 case 24: { visitor.visit(etl::get<24>(*this)); break; }
1103 case 25: { visitor.visit(etl::get<25>(*this)); break; }
1104 case 26: { visitor.visit(etl::get<26>(*this)); break; }
1105 case 27: { visitor.visit(etl::get<27>(*this)); break; }
1106 case 28: { visitor.visit(etl::get<28>(*this)); break; }
1107 case 29: { visitor.visit(etl::get<29>(*this)); break; }
1108 case 30: { visitor.visit(etl::get<30>(*this)); break; }
1109 case 31: { visitor.visit(etl::get<31>(*this)); break; }
1110#endif
1111#endif
1112#endif
1113 default: break;
1114 }
1115 }
1116#endif
1117
1118 //***************************************************************************
1120 //***************************************************************************
1121 template <size_t Index, typename TVisitor>
1122 bool attempt_visitor(TVisitor& visitor)
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 for C++17 & C++20.
1128 // Changed all of the instances for consistancy.
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 //***************************************************************************
1141 //***************************************************************************
1142 template <size_t Index, typename TVisitor>
1143 bool attempt_visitor(TVisitor& visitor) const
1144 {
1145 if (Index == index())
1146 {
1147 // Workaround for MSVC (2023/05/13)
1148 // It doesn't compile 'visitor.visit(etl::get<Index>(*this))' correctly for C++17 & C++20.
1149 // Changed all of the instances for consistancy.
1150 auto& v = etl::get<Index>(*this);
1151 visitor.visit(v);
1152 return true;
1153 }
1154 else
1155 {
1156 return false;
1157 }
1158 }
1159
1160#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1161 //***************************************************************************
1163 //***************************************************************************
1164 template <typename TVisitor, size_t... I>
1165 void do_operator(TVisitor& visitor, etl::index_sequence<I...>)
1166 {
1167 (attempt_operator<I>(visitor) || ...);
1168 }
1169
1170 //***************************************************************************
1172 //***************************************************************************
1173 template <typename TVisitor, size_t... I>
1174 void do_operator(TVisitor& visitor, etl::index_sequence<I...>) const
1175 {
1176 (attempt_operator<I>(visitor) || ...);
1177 }
1178#else
1179 //***************************************************************************
1181 //***************************************************************************
1182 template <typename TVisitor>
1183 void do_operator(TVisitor& visitor)
1184 {
1185#if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1186 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 8U, "ETL_VARIANT_CPP11_MAX_8_TYPES - Only a maximum of 8 types are allowed in this variant");
1187#endif
1188
1189#if defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1190 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 16U, "ETL_VARIANT_CPP11_MAX_16_TYPES - Only a maximum of 16 types are allowed in this variant");
1191#endif
1192
1193#if defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1194 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 24U, "ETL_VARIANT_CPP11_MAX_24_TYPES - Only a maximum of 24 types are allowed in this variant");
1195#endif
1196
1197 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 32U, "A maximum of 32 types are allowed in this variant");
1198
1199 switch (index())
1200 {
1201 case 0: visitor(etl::get<0>(*this)); break;
1202 case 1: visitor(etl::get<1>(*this)); break;
1203 case 2: visitor(etl::get<2>(*this)); break;
1204 case 3: visitor(etl::get<3>(*this)); break;
1205 case 4: visitor(etl::get<4>(*this)); break;
1206 case 5: visitor(etl::get<5>(*this)); break;
1207 case 6: visitor(etl::get<6>(*this)); break;
1208 case 7: visitor(etl::get<7>(*this)); break;
1209#if !defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1210 case 8: visitor(etl::get<8>(*this)); break;
1211 case 9: visitor(etl::get<9>(*this)); break;
1212 case 10: visitor(etl::get<10>(*this)); break;
1213 case 11: visitor(etl::get<11>(*this)); break;
1214 case 12: visitor(etl::get<12>(*this)); break;
1215 case 13: visitor(etl::get<13>(*this)); break;
1216 case 14: visitor(etl::get<14>(*this)); break;
1217 case 15: visitor(etl::get<15>(*this)); break;
1218#if !defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1219 case 16: visitor(etl::get<16>(*this)); break;
1220 case 17: visitor(etl::get<17>(*this)); break;
1221 case 18: visitor(etl::get<18>(*this)); break;
1222 case 19: visitor(etl::get<19>(*this)); break;
1223 case 20: visitor(etl::get<20>(*this)); break;
1224 case 21: visitor(etl::get<21>(*this)); break;
1225 case 22: visitor(etl::get<22>(*this)); break;
1226 case 23: visitor(etl::get<23>(*this)); break;
1227#if !defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1228 case 24: visitor(etl::get<24>(*this)); break;
1229 case 25: visitor(etl::get<25>(*this)); break;
1230 case 26: visitor(etl::get<26>(*this)); break;
1231 case 27: visitor(etl::get<27>(*this)); break;
1232 case 28: visitor(etl::get<28>(*this)); break;
1233 case 29: visitor(etl::get<29>(*this)); break;
1234 case 30: visitor(etl::get<30>(*this)); break;
1235 case 31: visitor(etl::get<31>(*this)); break;
1236#endif
1237#endif
1238#endif
1239 default: break;
1240 }
1241 }
1242
1243 //***************************************************************************
1245 //***************************************************************************
1246 template <typename TVisitor>
1247 void do_operator(TVisitor& visitor) const
1248 {
1249#if defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1250 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 8U, "ETL_VARIANT_CPP11_MAX_8_TYPES - Only a maximum of 8 types are allowed in this variant");
1251#endif
1252
1253#if defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1254 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 16U, "ETL_VARIANT_CPP11_MAX_16_TYPES - Only a maximum of 16 types are allowed in this variant");
1255#endif
1256
1257#if defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1258 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 24U, "ETL_VARIANT_CPP11_MAX_24_TYPES - Only a maximum of 24 types are allowed in this variant");
1259#endif
1260
1261 ETL_STATIC_ASSERT(sizeof...(TTypes) <= 32U, "A maximum of 32 types are allowed in this variant");
1262
1263 switch (index())
1264 {
1265 case 0: visitor(etl::get<0>(*this)); break;
1266 case 1: visitor(etl::get<1>(*this)); break;
1267 case 2: visitor(etl::get<2>(*this)); break;
1268 case 3: visitor(etl::get<3>(*this)); break;
1269 case 4: visitor(etl::get<4>(*this)); break;
1270 case 5: visitor(etl::get<5>(*this)); break;
1271 case 6: visitor(etl::get<6>(*this)); break;
1272 case 7: visitor(etl::get<7>(*this)); break;
1273#if !defined(ETL_VARIANT_CPP11_MAX_8_TYPES)
1274 case 8: visitor(etl::get<8>(*this)); break;
1275 case 9: visitor(etl::get<9>(*this)); break;
1276 case 10: visitor(etl::get<10>(*this)); break;
1277 case 11: visitor(etl::get<11>(*this)); break;
1278 case 12: visitor(etl::get<12>(*this)); break;
1279 case 13: visitor(etl::get<13>(*this)); break;
1280 case 14: visitor(etl::get<14>(*this)); break;
1281 case 15: visitor(etl::get<15>(*this)); break;
1282#if !defined(ETL_VARIANT_CPP11_MAX_16_TYPES)
1283 case 16: visitor(etl::get<16>(*this)); break;
1284 case 17: visitor(etl::get<17>(*this)); break;
1285 case 18: visitor(etl::get<18>(*this)); break;
1286 case 19: visitor(etl::get<19>(*this)); break;
1287 case 20: visitor(etl::get<20>(*this)); break;
1288 case 21: visitor(etl::get<21>(*this)); break;
1289 case 22: visitor(etl::get<22>(*this)); break;
1290 case 23: visitor(etl::get<23>(*this)); break;
1291#if !defined(ETL_VARIANT_CPP11_MAX_24_TYPES)
1292 case 24: visitor(etl::get<24>(*this)); break;
1293 case 25: visitor(etl::get<25>(*this)); break;
1294 case 26: visitor(etl::get<26>(*this)); break;
1295 case 27: visitor(etl::get<27>(*this)); break;
1296 case 28: visitor(etl::get<28>(*this)); break;
1297 case 29: visitor(etl::get<29>(*this)); break;
1298 case 30: visitor(etl::get<30>(*this)); break;
1299 case 31: visitor(etl::get<31>(*this)); break;
1300#endif
1301#endif
1302#endif
1303 default: break;
1304 }
1305 }
1306#endif
1307
1308 //***************************************************************************
1310 //***************************************************************************
1311 template <size_t Index, typename TVisitor>
1312 bool attempt_operator(TVisitor& visitor)
1313 {
1314 if (Index == index())
1315 {
1316 auto& v = etl::get<Index>(*this);
1317 visitor(v);
1318 return true;
1319 }
1320 else
1321 {
1322 return false;
1323 }
1324 }
1325
1326 //***************************************************************************
1328 //***************************************************************************
1329 template <size_t Index, typename TVisitor>
1330 bool attempt_operator(TVisitor& visitor) const
1331 {
1332 if (Index == index())
1333 {
1334 auto& v = etl::get<Index>(*this);
1335 visitor(v);
1336 return true;
1337 }
1338 else
1339 {
1340 return false;
1341 }
1342 }
1343
1344 //***************************************************************************
1347 //***************************************************************************
1349
1350 //***************************************************************************
1352 //***************************************************************************
1353 operation_function operation;
1354
1355 //***************************************************************************
1357 //***************************************************************************
1358 size_t type_id;
1359 };
1360
1361 //***************************************************************************
1363 //***************************************************************************
1364 template <typename T, typename... TTypes>
1365 ETL_CONSTEXPR14 bool holds_alternative(const etl::variant<TTypes...>& v) noexcept
1366 {
1367 constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
1368
1369 return (Index == variant_npos) ? false : (v.index() == Index);
1370 }
1371
1372 //***************************************************************************
1374 //***************************************************************************
1375 template <size_t Index, typename... TTypes>
1376 ETL_CONSTEXPR14 bool holds_alternative(const etl::variant<TTypes...>& v) noexcept
1377 {
1378 return (Index == v.index());
1379 }
1380
1381 //***************************************************************************
1383 //***************************************************************************
1384 template <typename... TTypes>
1385 ETL_CONSTEXPR14 bool holds_alternative(size_t index, const etl::variant<TTypes...>& v) noexcept
1386 {
1387 return (index == v.index());
1388 }
1389
1390 //***************************************************************************
1392 //***************************************************************************
1393 template <size_t Index, typename... TTypes>
1394 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<TTypes...>>&
1396 {
1397#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1398 static_assert(Index < sizeof...(TTypes), "Index out of range");
1399#endif
1400
1401 ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1402
1403 using type = etl::variant_alternative_t<Index, etl::variant<TTypes...>>;
1404
1405 return *static_cast<type*>(v.data);
1406 }
1407
1408 //***********************************
1409 template <size_t Index, typename... TTypes>
1410 ETL_CONSTEXPR14 etl::variant_alternative_t<Index, etl::variant<TTypes...>>&&
1412 {
1413#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1414 static_assert(Index < sizeof...(TTypes), "Index out of range");
1415#endif
1416
1417 using type = etl::variant_alternative_t<Index, etl::variant<TTypes...>>;
1418
1419 return etl::move(*static_cast<type*>(v.data));
1420 }
1421
1422 //***********************************
1423 template <size_t Index, typename... TTypes>
1424 ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<TTypes...>>&
1426 {
1427#if ETL_USING_CPP17 && !defined(ETL_VARIANT_FORCE_CPP11)
1428 static_assert(Index < sizeof...(TTypes), "Index out of range");
1429#endif
1430
1431 ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1432
1433 using type = etl::variant_alternative_t<Index, etl::variant<TTypes...>>;
1434
1435 return *static_cast<const type*>(v.data);
1436 }
1437
1438 //***********************************
1439 template <size_t Index, typename... TTypes>
1440 ETL_CONSTEXPR14 const etl::variant_alternative_t<Index, const etl::variant<TTypes...>>&&
1441 get(const etl::variant<TTypes...>&& v)
1442 {
1443#if ETL_USING_CPP17 & !defined(ETL_VARIANT_FORCE_CPP11)
1444 static_assert(Index < sizeof...(TTypes), "Index out of range");
1445#endif
1446
1447 ETL_ASSERT(Index == v.index(), ETL_ERROR(etl::variant_incorrect_type_exception));
1448
1449 using type = etl::variant_alternative_t<Index, etl::variant<TTypes...>>;
1450
1451 return etl::move(*static_cast<const type*>(v.data));
1452 }
1453
1454 //***********************************
1455 template <typename T, typename... TTypes>
1456 ETL_CONSTEXPR14 T& get(etl::variant<TTypes...>& v)
1457 {
1458 constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
1459
1460 return get<Index>(v);
1461 }
1462
1463 //***********************************
1464 template <typename T, typename... TTypes>
1465 ETL_CONSTEXPR14 T&& get(etl::variant<TTypes...>&& v)
1466 {
1467 constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
1468
1469 return get<Index>(etl::move(v));
1470 }
1471
1472 //***********************************
1473 template <typename T, typename... TTypes>
1474 ETL_CONSTEXPR14 const T& get(const etl::variant<TTypes...>& v)
1475 {
1476 constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
1477
1478 return get<Index>(v);
1479 }
1480
1481 //***********************************
1482 template <typename T, typename... TTypes>
1483 ETL_CONSTEXPR14 const T&& get(const etl::variant<TTypes...>&& v)
1484 {
1485 constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
1486
1487 return get<Index>(etl::move(v));
1488 }
1489
1490 //***************************************************************************
1492 //***************************************************************************
1493 template< size_t Index, typename... TTypes >
1494 ETL_CONSTEXPR14 etl::add_pointer_t<etl::variant_alternative_t<Index, etl::variant<TTypes...>>>
1495 get_if(etl::variant<TTypes...>* pv) noexcept
1496 {
1497 if ((pv != nullptr) && (pv->index() == Index))
1498 {
1499 return &etl::get<Index>(*pv);
1500 }
1501 else
1502 {
1503 return nullptr;
1504 }
1505 }
1506
1507 //***********************************
1508 template< size_t Index, typename... TTypes >
1509 ETL_CONSTEXPR14 etl::add_pointer_t<const etl::variant_alternative_t<Index, etl::variant<TTypes...>>>
1510 get_if(const etl::variant<TTypes...>* pv) noexcept
1511 {
1512 if ((pv != nullptr) && (pv->index() == Index))
1513 {
1514 return &etl::get<Index>(*pv);
1515 }
1516 else
1517 {
1518 return nullptr;
1519 }
1520 }
1521
1522 //***********************************
1523 template< class T, typename... TTypes >
1524 ETL_CONSTEXPR14 etl::add_pointer_t<T> get_if(etl::variant<TTypes...>* pv) noexcept
1525 {
1526 constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
1527
1528 if ((pv != nullptr) && (pv->index() == Index))
1529 {
1530 return &etl::get<Index>(*pv);
1531 }
1532 else
1533 {
1534 return nullptr;
1535 }
1536 }
1537
1538 //***********************************
1539 template< typename T, typename... TTypes >
1540 ETL_CONSTEXPR14 etl::add_pointer_t<const T> get_if(const etl::variant<TTypes...>* pv) noexcept
1541 {
1542 constexpr size_t Index = etl::private_variant::parameter_pack<TTypes...>::template index_of_type<T>::value;
1543
1544 if ((pv != nullptr) && (pv->index() == Index))
1545 {
1546 return &etl::get<Index>(*pv);
1547 }
1548 else
1549 {
1550 return nullptr;
1551 }
1552 }
1553
1554 //***************************************************************************
1556 //***************************************************************************
1557 template <typename... TTypes>
1559 {
1560 lhs.swap(rhs);
1561 }
1562
1563 //***************************************************************************
1565 //***************************************************************************
1566 template <typename T>
1567 struct variant_size;
1568
1569 template <typename... TTypes>
1570 struct variant_size<etl::variant<TTypes...>>
1571 : etl::integral_constant<size_t, sizeof...(TTypes)>
1572 {
1573 };
1574
1575 template <typename T>
1576 struct variant_size<const T>
1577 : etl::integral_constant<size_t, variant_size<T>::value>
1578 {
1579 };
1580
1581#if ETL_USING_CPP17
1582 template <typename... TTypes>
1583 inline constexpr size_t variant_size_v = variant_size<TTypes...>::value;
1584#endif
1585
1586 //***************************************************************************
1588 //***************************************************************************
1589 namespace private_variant
1590 {
1591 template <typename TRet, typename TCallable, typename TVariant, size_t tIndex, typename TNext, typename... TVariants>
1592 static ETL_CONSTEXPR14 TRet do_visit_single(TCallable&& f, TVariant&& v, TNext&&, TVariants&&... vs);
1593
1594 //***************************************************************************
1598 //***************************************************************************
1599 struct visit_auto_return
1600 {
1601 };
1602
1603 //***************************************************************************
1606 //***************************************************************************
1607 template <typename TCallable, typename... Ts>
1608 struct single_visit_result_type
1609 {
1610 using type = decltype(declval<TCallable>()(declval<Ts>()...));
1611 };
1612
1613 template <typename TCallable, typename... Ts>
1614 using single_visit_result_type_t = typename single_visit_result_type<TCallable, Ts...>::type;
1615
1616 //***************************************************************************
1619 //***************************************************************************
1620 template <typename TVar, typename T>
1621 using rlref_copy = conditional_t<is_reference<TVar>::value, T&, T&&>;
1622
1623 //***************************************************************************
1630 //***************************************************************************
1631 template <template <typename...> class, typename...>
1632 struct visit_result_helper;
1633
1634 template <template <typename...> class TToInject, size_t... tAltIndices, typename TCur>
1635 struct visit_result_helper<TToInject, index_sequence<tAltIndices...>, TCur>
1636 {
1637 template <size_t tIndex>
1638 using var_type = rlref_copy<TCur,
1639 variant_alternative_t<tIndex, remove_reference_t<TCur> > >;
1640
1641 using type = common_type_t<TToInject<var_type<tAltIndices> >...>;
1642 };
1643
1644 template <template <typename...> class TToInject, size_t... tAltIndices, typename TCur, typename TNext, typename... TVs>
1645 struct visit_result_helper<TToInject, index_sequence<tAltIndices...>, TCur, TNext, TVs...>
1646 {
1647 template <size_t tIndex>
1648 using var_type = rlref_copy<TCur, variant_alternative_t<tIndex, remove_reference_t<TCur> > >;
1649
1650 template <size_t tIndex>
1651 struct next_inject_wrap
1652 {
1653 template <typename... TNextInj>
1654 using next_inject = TToInject<var_type<tIndex>, TNextInj...>;
1655 using recursive_result = typename visit_result_helper<next_inject, make_index_sequence<variant_size<remove_reference_t<TNext> >::value>, TNext, TVs...>::type;
1656 };
1657
1658 using type = common_type_t<typename next_inject_wrap<tAltIndices>::recursive_result...>;
1659 };
1660
1661 //***************************************************************************
1665 //***************************************************************************
1666 template <typename TRet, typename...>
1667 struct visit_result
1668 {
1669 using type = TRet;
1670 };
1671
1672 template <typename TCallable, typename T1, typename... Ts>
1673 struct visit_result<visit_auto_return, TCallable, T1, Ts...>
1674 {
1675 // bind TCallable to the first argument in this variadic alias.
1676 template <typename... Ts2>
1677 using single_res = single_visit_result_type_t<TCallable, Ts2...>;
1678 using type = typename visit_result_helper<single_res, make_index_sequence<variant_size<remove_reference_t<T1> >::value>, T1, Ts...>::type;
1679 };
1680
1681 template <typename... Ts>
1682 using visit_result_t = typename visit_result<Ts...>::type;
1683
1684 //***************************************************************************
1687 //***************************************************************************
1688 template <typename TRet, typename TCallable, typename TVariant, size_t tIndex>
1689 constexpr TRet do_visit_single(TCallable&& f, TVariant&& v)
1690 {
1691 return static_cast<TCallable&&>(f)(etl::get<tIndex>(static_cast<TVariant&&>(v)));
1692 }
1693
1694 //***************************************************************************
1698 //***************************************************************************
1699 template <typename TRet, typename TCallable, typename TCurVariant, typename... TVarRest>
1700 struct do_visit_helper
1701 {
1702 using function_pointer = add_pointer_t<TRet(TCallable&&, TCurVariant&&, TVarRest&&...)>;
1703
1704 template <size_t tIndex>
1705 static constexpr function_pointer fptr() noexcept
1706 {
1707 return &do_visit_single<TRet, TCallable, TCurVariant, tIndex, TVarRest...>;
1708 }
1709 };
1710
1711 //***************************************************************************
1713 //***************************************************************************
1714 template <typename TRet, typename TCallable, typename TVariant, size_t... tIndices, typename... TVarRest>
1715 static ETL_CONSTEXPR14 TRet do_visit(TCallable&& f, TVariant&& v, index_sequence<tIndices...>, TVarRest&&... variants)
1716 {
1717 ETL_ASSERT(!v.valueless_by_exception(), ETL_ERROR(bad_variant_access));
1718
1719 using helper_t = do_visit_helper<TRet, TCallable, TVariant, TVarRest...>;
1720 using func_ptr = typename helper_t::function_pointer;
1721
1722 constexpr func_ptr jmp_table[]
1723 {
1724 helper_t::template fptr<tIndices>()...
1725 };
1726
1727 return jmp_table[v.index()](static_cast<TCallable&&>(f), static_cast<TVariant&&>(v), static_cast<TVarRest&&>(variants)...);
1728 }
1729
1730 template <typename TRet, typename TCallable, typename TVariant, typename... TVs>
1731 static ETL_CONSTEXPR14 TRet visit(TCallable&& f, TVariant&& v, TVs&&... vs)
1732 {
1733 constexpr size_t variants = etl::variant_size<typename remove_reference<TVariant>::type>::value;
1734 return private_variant::do_visit<TRet>(static_cast<TCallable&&>(f),
1735 static_cast<TVariant&&>(v),
1736 make_index_sequence<variants>{},
1737 static_cast<TVs&&>(vs)...);
1738 }
1739
1740 //***************************************************************************
1743 //***************************************************************************
1744 template <typename TRet, typename TCallable, typename TVariant, size_t tIndex>
1745 class constexpr_visit_closure
1746 {
1747 add_pointer_t<TCallable> callable_;
1748 add_pointer_t<TVariant> variant_;
1749
1750 public:
1751 constexpr constexpr_visit_closure(TCallable&& c, TVariant&& v)
1752 : callable_(&c), variant_(&v)
1753 {
1754 }
1755
1756 template <typename... Ts>
1757 ETL_CONSTEXPR14 TRet operator()(Ts&&... args) const
1758 {
1759 return static_cast<TCallable&&>(*callable_)(get<tIndex>(static_cast<TVariant&&>(*variant_)), static_cast<Ts&&>(args)...);
1760 }
1761 };
1762
1763 template <typename TRet, typename TCallable, typename TVariant, size_t tIndex, typename TNext, typename... TVariants>
1764 static ETL_CONSTEXPR14 TRet do_visit_single(TCallable&& f, TVariant&& v, TNext&& next, TVariants&&... vs)
1765 {
1766 return private_variant::visit<TRet>(constexpr_visit_closure<TRet, TCallable, TVariant, tIndex>(static_cast<TCallable&&>(f), static_cast<TVariant&&>(v)),
1767 static_cast<TNext&&>(next), static_cast<TVariants&&>(vs)...);
1768 }
1769
1770 } // namespace private_variant
1771
1772 //***************************************************************************
1775 //***************************************************************************
1776 template <typename TRet = private_variant::visit_auto_return, typename... TVariants, typename TCallable, typename TDeducedReturn = private_variant::visit_result_t<TRet, TCallable, TVariants...> >
1777 static ETL_CONSTEXPR14 TDeducedReturn visit(TCallable&& f, TVariants&&... vs)
1778 {
1779 return private_variant::visit<TDeducedReturn>(static_cast<TCallable&&>(f), static_cast<TVariants&&>(vs)...);
1780 }
1781}
1782#endif
#define ETL_ASSERT(b, e)
Definition: error_handler.h:316
ETL_CONSTEXPR exception(string_type reason_, string_type, numeric_type line_)
Constructor.
Definition: exception.h:69
Definition: integral_limits.h:468
Definition: largest.h:227
conditional
Definition: type_traits_generator.h:1160
integral_constant
Definition: type_traits_generator.h:832
is_same
Definition: type_traits_generator.h:1041
~variant()
Destructor.
Definition: variant_legacy.h:230
T & get()
Definition: variant_legacy.h:726
uint_least8_t type_id_t
The type used for ids.
Definition: variant_legacy.h:153
variant & operator=(const T &value)
Definition: variant_legacy.h:589
T & emplace(const TP1 &value1)
Emplace with one constructor parameter.
Definition: variant_legacy.h:527
size_t index() const
Gets the index of the type currently stored or UNSUPPORTED_TYPE_ID.
Definition: variant_legacy.h:707
Definition: variant_legacy.h:147
Definition: variant_legacy.h:100
Definition: variant_legacy.h:79
bitset_ext
Definition: absolute.h:38
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:684
T & get(array< T, MAXN > &a)
Definition: array.h:710
bool operator>=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:696
bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:645
void swap(etl::array< T, SIZE > &lhs, etl::array< T, SIZE > &rhs)
Template deduction guides.
Definition: array.h:621
bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:633
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:657
bool operator<=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:672
Definition: utility.h:591
Definition: utility.h:580
Definition: type_traits_generator.h:2033
Definition: type_traits.h:1376
Definition: variant_legacy.h:923