Embedded Template Library 1.0
optional.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) 2015 John Wellbelove
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#ifndef ETL_OPTIONAL_INCLUDED
32#define ETL_OPTIONAL_INCLUDED
33
34#include "platform.h"
35#include "alignment.h"
36#include "memory.h"
37#include "type_traits.h"
38#include "exception.h"
39#include "error_handler.h"
40#include "utility.h"
41#include "placement_new.h"
42
43namespace etl
44{
45 //*****************************************************************************
48 //*****************************************************************************
50 {
51 public:
52
53 // Convertible to any type of null non-member pointer.
54 template<class T>
55 operator T*() const
56 {
57 return 0;
58 }
59
60 private:
61
62 // Can't take address of nullopt.
63 void operator&() const ETL_DELETE;
64 };
65
66 //*****************************************************************************
69 //*****************************************************************************
70 const nullopt_t nullopt = {};
71
72 //***************************************************************************
75 //***************************************************************************
77 {
78 public:
79
80 optional_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
81 : exception(reason_, file_name_, line_number_)
82 {
83 }
84 };
85
86 //***************************************************************************
89 //***************************************************************************
91 {
92 public:
93
94 optional_invalid(string_type file_name_, numeric_type line_number_)
95 : optional_exception("optional:invalid", file_name_, line_number_)
96 {
97 }
98 };
99
100 //*****************************************************************************
106 //*****************************************************************************
107 template <typename T, bool is_pod = etl::is_pod<T>::value>
108 class optional;
109
110 //*****************************************************************************
112 //*****************************************************************************
113 template <typename T>
114 class optional<T, false>
115 {
116 public:
117
118 //***************************************************************************
120 //***************************************************************************
121 ETL_CONSTEXPR
123 : storage()
124 {
125 }
126
127 //***************************************************************************
129 //***************************************************************************
130 ETL_CONSTEXPR
132 : storage()
133 {
134 }
135
137 //***************************************************************************
139 //***************************************************************************
140 ETL_CONSTEXPR20_STL
141 optional(const optional& other)
142 {
143 if (other.has_value())
144 {
145 storage.construct(other.value());
146 }
147 }
149
150#if ETL_USING_CPP11
151 //***************************************************************************
153 //***************************************************************************
154 ETL_CONSTEXPR20_STL
155 optional(optional&& other)
156 {
157 if (other.has_value())
158 {
159 storage.construct(etl::move(other.value()));
160 }
161 }
162#endif
163
164 //***************************************************************************
166 //***************************************************************************
167 ETL_CONSTEXPR20_STL
168 optional(const T& value_)
169 {
170 storage.construct(value_);
171 }
172
173#if ETL_USING_CPP11
174 //***************************************************************************
176 //***************************************************************************
177 ETL_CONSTEXPR20_STL
178 optional(T&& value_)
179 {
180 storage.construct(etl::move(value_));
181 }
182#endif
183
184 //***************************************************************************
186 //***************************************************************************
187 ETL_CONSTEXPR20_STL
189 {
190 storage.destroy();
191 }
192
193 //***************************************************************************
195 //***************************************************************************
196 ETL_CONSTEXPR20_STL
198 {
199 if (has_value())
200 {
201 storage.destroy();
202 }
203
204 return *this;
205 }
206
207 //***************************************************************************
209 //***************************************************************************
210 ETL_CONSTEXPR20_STL
211 optional& operator =(const optional& other)
212 {
213 if (this != &other)
214 {
215 if (other.has_value())
216 {
217 storage.construct(other.value());
218 }
219 else
220 {
221 storage.destroy();
222 }
223 }
224
225 return *this;
226 }
227
228#if ETL_USING_CPP11
229 //***************************************************************************
231 //***************************************************************************
232 ETL_CONSTEXPR20_STL
233 optional& operator =(optional&& other)
234 {
235 if (this != &other)
236 {
237 if (other.has_value())
238 {
239 storage.construct(etl::move(other.value()));
240 }
241 else
242 {
243 storage.destroy();
244 }
245 }
246
247 return *this;
248 }
249#endif
250
251 //***************************************************************************
253 //***************************************************************************
254 ETL_CONSTEXPR20_STL
255 optional& operator =(const T& value_)
256 {
257 storage.construct(value_);
258
259 return *this;
260 }
261
262#if ETL_USING_CPP11
263 //***************************************************************************
265 //***************************************************************************
266 ETL_CONSTEXPR20_STL
267 optional& operator =(T&& value_)
268 {
269 storage.construct(etl::move(value_));
270
271 return *this;
272 }
273#endif
274
275 //***************************************************************************
277 //***************************************************************************
278 ETL_CONSTEXPR20_STL
279 T* operator ->()
280 {
281#if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL)
282 ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
283#endif
284
285 return &storage.u.value;
286 }
287
288 //***************************************************************************
290 //***************************************************************************
291 ETL_CONSTEXPR20_STL
292 const T* operator ->() const
293 {
294#if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL)
295 ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
296#endif
297
298 return &storage.u.value;
299 }
300
301 //***************************************************************************
303 //***************************************************************************
304 ETL_CONSTEXPR20_STL
305 T& operator *() ETL_LVALUE_REF_QUALIFIER
306 {
307#if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL)
308 ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
309#endif
310
311 return storage.u.value;
312 }
313
314 //***************************************************************************
316 //***************************************************************************
317 ETL_CONSTEXPR20_STL
318 const T& operator *() const ETL_LVALUE_REF_QUALIFIER
319 {
320#if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL)
321 ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
322#endif
323
324 return storage.u.value;
325 }
326
327#if ETL_USING_CPP11
328 //***************************************************************************
330 //***************************************************************************
331 ETL_CONSTEXPR20_STL
332 T&& operator *()&&
333 {
334#if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL)
335 ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
336#endif
337
338 return etl::move(storage.u.value);
339 }
340
341 //***************************************************************************
343 //***************************************************************************
344 ETL_CONSTEXPR20_STL
345 const T&& operator *() const&&
346 {
347#if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL)
348 ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
349#endif
350
351 return etl::move(storage.u.value);
352 }
353#endif
354
355 //***************************************************************************
356 // Check whether optional contains value
357 //***************************************************************************
358 ETL_CONSTEXPR20_STL
359 bool has_value() const ETL_NOEXCEPT
360 {
361 return storage.valid;
362 }
363
364 //***************************************************************************
366 //***************************************************************************
367 ETL_CONSTEXPR20_STL
368 ETL_EXPLICIT operator bool() const
369 {
370 return has_value();
371 }
372
373 //***************************************************************************
375 //***************************************************************************
376 ETL_CONSTEXPR20_STL
377 T& value() ETL_LVALUE_REF_QUALIFIER
378 {
379#if ETL_IS_DEBUG_BUILD
380 ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
381#endif
382
383 return storage.u.value;
384 }
385
386 //***************************************************************************
388 //***************************************************************************
389 ETL_CONSTEXPR20_STL
390 const T& value() const ETL_LVALUE_REF_QUALIFIER
391 {
392#if ETL_IS_DEBUG_BUILD
393 ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
394#endif
395
396 return storage.u.value;
397 }
398
399 //***************************************************************************
401 //***************************************************************************
402 ETL_CONSTEXPR20_STL
403 T value_or(const T& default_value) const ETL_LVALUE_REF_QUALIFIER
404 {
405 return has_value() ? value() : default_value;
406 }
407
408#if ETL_USING_CPP11
409 //***************************************************************************
411 //***************************************************************************
412 ETL_CONSTEXPR20_STL
413 T&& value()&&
414 {
415#if ETL_IS_DEBUG_BUILD
416 ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
417#endif
418
419 return etl::move(storage.u.value);
420 }
421
422 //***************************************************************************
424 //***************************************************************************
425 ETL_CONSTEXPR20_STL
426 const T&& value() const&&
427 {
428#if ETL_IS_DEBUG_BUILD
429 ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid));
430#endif
431
432 return etl::move(storage.u.value);
433 }
434
435 //***************************************************************************
437 //***************************************************************************
438 template <typename U>
439 ETL_CONSTEXPR20_STL
440 etl::enable_if_t<etl::is_convertible<U, T>::value, T>
441 value_or(U&& default_value) const&
442 {
443 return has_value() ? value() : etl::forward<T>(default_value);
444 }
445
446 //***************************************************************************
448 //***************************************************************************
449 template <typename U>
450 ETL_CONSTEXPR20_STL
451 etl::enable_if_t<etl::is_convertible<U, T>::value, T>
452 value_or(U&& default_value) &&
453 {
454 return has_value() ? etl::move(value()) : etl::forward<T>(default_value);
455 }
456#endif
457
458 //***************************************************************************
460 //***************************************************************************
461 ETL_CONSTEXPR20_STL
462 void swap(optional& other)
463 {
464 optional temp(*this);
465 *this = other;
466 other = temp;
467 }
468
469 //***************************************************************************
471 //***************************************************************************
472 ETL_CONSTEXPR20_STL
473 void reset()
474 {
475 storage.destroy();
476 }
477
478#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_OPTIONAL_FORCE_CPP03_IMPLEMENTATION)
479 //*************************************************************************
482 //*************************************************************************
483 template <typename ... TArgs>
484 ETL_CONSTEXPR20_STL
485 void emplace(TArgs&& ... args)
486 {
487 storage.construct(etl::forward<TArgs>(args)...);
488 }
489#else
490 //*************************************************************************
493 //*************************************************************************
494 template <typename T1>
495 T& emplace(const T1& value1)
496 {
497 if (has_value())
498 {
499 // Destroy the old one.
500 storage.destroy();
501 }
502
503 T* p = ::new (&storage.u.value) T(value1);
504 storage.valid = true;
505
506 return *p;
507 }
508
509 //*************************************************************************
512 //*************************************************************************
513 template <typename T1, typename T2>
514 T& emplace(const T1& value1, const T2& value2)
515 {
516 if (has_value())
517 {
518 // Destroy the old one.
519 storage.destroy();
520 }
521
522 T* p = ::new (&storage.u.value) T(value1, value2);
523 storage.valid = true;
524
525 return *p;
526 }
527
528 //*************************************************************************
531 //*************************************************************************
532 template <typename T1, typename T2, typename T3>
533 T& emplace(const T1& value1, const T2& value2, const T3& value3)
534 {
535 if (has_value())
536 {
537 // Destroy the old one.
538 storage.destroy();
539 }
540
541 T* p = ::new (&storage.u.value) T(value1, value2, value3);
542 storage.valid = true;
543
544 return *p;
545 }
546
547 //*************************************************************************
550 //*************************************************************************
551 template <typename T1, typename T2, typename T3, typename T4>
552 T& emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
553 {
554 if (has_value())
555 {
556 // Destroy the old one.
557 storage.destroy();
558 }
559
560 T* p = ::new (&storage.u.value) T(value1, value2, value3, value4);
561 storage.valid = true;
562
563 return *p;
564 }
565#endif
566
567 private:
568
569 struct storage_type
570 {
571 //*******************************
572 ETL_CONSTEXPR20_STL
573 storage_type()
574 : u()
575 , valid(false)
576 {
577 }
578
579 //*******************************
580 ETL_CONSTEXPR20_STL
581 ~storage_type()
582 {
583 destroy();
584 }
585
586 //*******************************
587 ETL_CONSTEXPR20_STL
588 void construct(const T& value_)
589 {
590 if (valid)
591 {
592 u.value = value_;
593 }
594 else
595 {
596 etl::construct_at(&u.value, value_);
597 valid = true;
598 }
599 }
600
601#if ETL_USING_CPP11
602 //*******************************
603 ETL_CONSTEXPR20_STL
604 void construct(T&& value_)
605 {
606 if (valid)
607 {
608 u.value = etl::move(value_);
609 }
610 else
611 {
612 etl::construct_at(&u.value, etl::move(value_));
613 valid = true;
614 }
615 }
616
617 //*******************************
618 template <typename... TArgs>
619 ETL_CONSTEXPR20_STL
620 void construct(TArgs&&... args)
621 {
622 destroy();
623 etl::construct_at(&u.value, etl::forward<TArgs>(args)...);
624 valid = true;
625 }
626#endif
627
628 //*******************************
629 ETL_CONSTEXPR20_STL
630 void destroy()
631 {
632 if (valid)
633 {
634 etl::destroy_at(&u.value);
635 valid = false;
636 }
637 }
638
639 //*******************************
640 union union_type
641 {
642 ETL_CONSTEXPR20_STL
643 union_type()
644 : dummy(0)
645 {
646 }
647
648 ETL_CONSTEXPR20_STL
649 ~union_type()
650 {
651 }
652
653 char dummy;
654 T value;
655 } u;
656
657 bool valid;
658 };
659
660 storage_type storage;
661 };
662
663 //*****************************************************************************
667 //*****************************************************************************
668 template <typename T>
669 class optional<T, true>
670 {
671 public:
672
673 //***************************************************************************
675 //***************************************************************************
676 ETL_CONSTEXPR14 optional()
677 : valid(false)
678 , storage()
679 {
680 }
681
682 //***************************************************************************
684 //***************************************************************************
685 ETL_CONSTEXPR14 optional(etl::nullopt_t)
686 : valid(false)
687 , storage()
688 {
689 }
690
691 //***************************************************************************
693 //***************************************************************************
694 ETL_CONSTEXPR14 optional(const optional& other)
695 : valid(bool(other))
696 , storage(other.storage)
697 {
698 }
699
700#if ETL_USING_CPP11
701 //***************************************************************************
703 //***************************************************************************
704 ETL_CONSTEXPR14 optional(optional&& other)
705 : valid(bool(other))
706 , storage(etl::move(other.storage))
707 {
708 }
709#endif
710
711 //***************************************************************************
713 //***************************************************************************
714 ETL_CONSTEXPR14 optional(const T& value_)
715 : valid(true)
716 {
717 storage.u.value = value_;
718 }
719
720#if ETL_USING_CPP11
721 //***************************************************************************
723 //***************************************************************************
724 ETL_CONSTEXPR14 optional(T&& value_)
725 : valid(true)
726 {
727 storage.u.value = etl::move(value_);
728 }
729#endif
730
731 //***************************************************************************
733 //***************************************************************************
734 ETL_CONSTEXPR14 optional& operator =(etl::nullopt_t)
735 {
736 valid = false;
737 return *this;
738 }
739
740 //***************************************************************************
742 //***************************************************************************
743 ETL_CONSTEXPR14 optional& operator =(const optional& other)
744 {
745 if (this != &other)
746 {
747 storage.u = other.storage.u;
748 valid = other.valid;
749 }
750
751 return *this;
752 }
753
754#if ETL_USING_CPP11
755 //***************************************************************************
757 //***************************************************************************
758 ETL_CONSTEXPR14 optional& operator =(optional&& other)
759 {
760 if (this != &other)
761 {
762 storage.u = etl::move(other.storage.u);
763 valid = other.valid;
764 }
765
766 return *this;
767 }
768#endif
769
770 //***************************************************************************
772 //***************************************************************************
773 ETL_CONSTEXPR14 optional& operator =(const T& value_)
774 {
775 storage.u.value = value_;
776 valid = true;
777
778 return *this;
779 }
780
781#if ETL_USING_CPP11
782 //***************************************************************************
784 //***************************************************************************
785 ETL_CONSTEXPR14 optional& operator =(T&& value_)
786 {
787 storage.u.value = etl::move(value_);
788 valid = true;
789
790 return *this;
791 }
792#endif
793
794 //***************************************************************************
796 //***************************************************************************
797 ETL_CONSTEXPR14 T* operator ->()
798 {
799#if ETL_IS_DEBUG_BUILD
800 ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
801#endif
802
803 return &storage.u.value;
804 }
805
806 //***************************************************************************
808 //***************************************************************************
809 ETL_CONSTEXPR14 const T* operator ->() const
810 {
811#if ETL_IS_DEBUG_BUILD
812 ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
813#endif
814
815 return &storage.u.value;
816 }
817
818 //***************************************************************************
820 //***************************************************************************
821 ETL_CONSTEXPR14 T& operator *() ETL_LVALUE_REF_QUALIFIER
822 {
823#if ETL_IS_DEBUG_BUILD
824 ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
825#endif
826
827 return storage.u.value;
828 }
829
830 //***************************************************************************
832 //***************************************************************************
833 ETL_CONSTEXPR14 const T& operator *() const ETL_LVALUE_REF_QUALIFIER
834 {
835#if ETL_IS_DEBUG_BUILD
836 ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
837#endif
838
839 return storage.u.value;
840 }
841
842#if ETL_USING_CPP11
843 //***************************************************************************
845 //***************************************************************************
846 ETL_CONSTEXPR14 T&& operator *()&&
847 {
848#if ETL_IS_DEBUG_BUILD
849 ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
850#endif
851
852 return etl::move(storage.u.value);
853 }
854
855 //***************************************************************************
857 //***************************************************************************
858 ETL_CONSTEXPR14 const T&& operator *() const&&
859 {
860#if ETL_IS_DEBUG_BUILD
861 ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
862#endif
863
864 return etl::move(storage.u.value);
865 }
866#endif
867
868 //***************************************************************************
870 //***************************************************************************
871 ETL_CONSTEXPR14
872 ETL_EXPLICIT operator bool() const
873 {
874 return valid;
875 }
876
877 //***************************************************************************
878 // Check whether optional contains value
879 //***************************************************************************
880 ETL_CONSTEXPR14 bool has_value() const ETL_NOEXCEPT
881 {
882 return valid;
883 }
884
885 //***************************************************************************
887 //***************************************************************************
888 ETL_CONSTEXPR14 T& value() ETL_LVALUE_REF_QUALIFIER
889 {
890#if ETL_IS_DEBUG_BUILD
891 ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
892#endif
893
894 return storage.u.value;
895 }
896
897 //***************************************************************************
899 //***************************************************************************
900 ETL_CONSTEXPR14 const T& value() const ETL_LVALUE_REF_QUALIFIER
901 {
902#if ETL_IS_DEBUG_BUILD
903 ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
904#endif
905
906 return storage.u.value;
907 }
908
909 //***************************************************************************
911 //***************************************************************************
912 ETL_CONSTEXPR14 T value_or(const T& default_value) const ETL_LVALUE_REF_QUALIFIER
913 {
914 return valid ? value() : default_value;
915 }
916
917#if ETL_USING_CPP11
918 //***************************************************************************
920 //***************************************************************************
921 ETL_CONSTEXPR14 T&& value()&&
922 {
923#if ETL_IS_DEBUG_BUILD
924 ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
925#endif
926
927 return etl::move(storage.u.value);
928 }
929
930 //***************************************************************************
932 //***************************************************************************
933 ETL_CONSTEXPR14 const T&& value() const&&
934 {
935#if ETL_IS_DEBUG_BUILD
936 ETL_ASSERT(valid, ETL_ERROR(optional_invalid));
937#endif
938
939 return etl::move(storage.u.value);
940 }
941
942 //***************************************************************************
944 //***************************************************************************
945 template <typename U>
946 ETL_CONSTEXPR20_STL
947 etl::enable_if_t<etl::is_convertible<U, T>::value, T>
948 value_or(U&& default_value) const&
949 {
950 if (has_value())
951 {
952 return value();
953 }
954 else
955 {
956 return static_cast<T>(etl::forward<U>(default_value));
957 }
958 }
959
960 //***************************************************************************
962 //***************************************************************************
963 template <typename U>
964 ETL_CONSTEXPR20_STL
965 etl::enable_if_t<etl::is_convertible<U, T>::value, T>
966 value_or(U&& default_value) &&
967 {
968 if (has_value())
969 {
970 return etl::move(value());
971 }
972 else
973 {
974 return static_cast<T>(etl::forward<U>(default_value));
975 }
976 }
977#endif
978
979 //***************************************************************************
981 //***************************************************************************
982 ETL_CONSTEXPR14 void swap(optional& other)
983 {
984 optional temp(*this);
985 *this = other;
986 other = temp;
987 }
988
989 //***************************************************************************
991 //***************************************************************************
992 ETL_CONSTEXPR14 void reset()
993 {
994 valid = false;
995 }
996
997#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_OPTIONAL_FORCE_CPP03_IMPLEMENTATION)
998 //*************************************************************************
1001 //*************************************************************************
1002 template <typename ... Args>
1003 ETL_CONSTEXPR14 void emplace(Args && ... args)
1004 {
1005 storage.u.value = T(ETL_OR_STD::forward<Args>(args)...);
1006 valid = true;
1007 }
1008#else
1009 //*************************************************************************
1012 //*************************************************************************
1013 template <typename T1>
1014 void emplace(const T1& value1)
1015 {
1016 storage.u.value = value1;
1017 valid = true;
1018 }
1019
1020 //*************************************************************************
1023 //*************************************************************************
1024 template <typename T1, typename T2>
1025 void emplace(const T1& value1, const T2& value2)
1026 {
1027 storage.u.value = T(value1, value2);
1028 valid = true;
1029 }
1030
1031 //*************************************************************************
1034 //*************************************************************************
1035 template <typename T1, typename T2, typename T3>
1036 void emplace(const T1& value1, const T2& value2, const T3& value3)
1037 {
1038 storage.u.value = T(value1, value2, value3);
1039 valid = true;
1040 }
1041
1042 //*************************************************************************
1045 //*************************************************************************
1046 template <typename T1, typename T2, typename T3, typename T4>
1047 void emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
1048 {
1049 storage.u.value = T(value1, value2, value3, value4);
1050 valid = true;
1051 }
1052#endif
1053
1054 private:
1055
1056 bool valid;
1057
1058 struct storage_type
1059 {
1060 storage_type()
1061 {
1062 }
1063
1064 union union_type
1065 {
1066 union_type()
1067 : dummy(0)
1068 {
1069 }
1070
1071 char dummy;
1072 T value;
1073 };
1074
1075 union_type u;
1076 };
1077
1078 storage_type storage;
1079 };
1080
1082
1083 //***************************************************************************
1085 //***************************************************************************
1086 template <typename T>
1087 ETL_CONSTEXPR14 bool operator ==(const etl::optional<T>& lhs, const etl::optional<T>& rhs)
1088 {
1089 if (lhs.has_value() != rhs.has_value())
1090 {
1091 return false;
1092 }
1093 else if (!lhs.has_value() && !rhs.has_value())
1094 {
1095 return true;
1096 }
1097 else
1098 {
1099 return lhs.value() == rhs.value();
1100 }
1101 }
1102
1103 //***************************************************************************
1105 //***************************************************************************
1106 template <typename T>
1107 ETL_CONSTEXPR14 bool operator !=(const etl::optional<T>& lhs, const etl::optional<T>& rhs)
1108 {
1109 return !(lhs == rhs);
1110 }
1111
1112 //***************************************************************************
1114 //***************************************************************************
1115 template <typename T>
1116 ETL_CONSTEXPR14 bool operator <(const etl::optional<T>& lhs, const etl::optional<T>& rhs)
1117 {
1118 if (!rhs.has_value())
1119 {
1120 return false;
1121 }
1122 else if (!lhs.has_value())
1123 {
1124 return true;
1125 }
1126 else
1127 {
1128 return lhs.value() < rhs.value();
1129 }
1130 }
1131
1132 //***************************************************************************
1134 //***************************************************************************
1135 template <typename T>
1136 ETL_CONSTEXPR14 bool operator <=(const etl::optional<T>& lhs, const etl::optional<T>& rhs)
1137 {
1138 return !(rhs < lhs);
1139 }
1140
1141 //***************************************************************************
1143 //***************************************************************************
1144 template <typename T>
1145 ETL_CONSTEXPR14 bool operator >(const etl::optional<T>& lhs, const etl::optional<T>& rhs)
1146 {
1147 return (rhs < lhs);
1148 }
1149
1150 //***************************************************************************
1152 //***************************************************************************
1153 template <typename T>
1154 ETL_CONSTEXPR14 bool operator >=(const etl::optional<T>& lhs, const etl::optional<T>& rhs)
1155 {
1156 return !(lhs < rhs);
1157 }
1158
1159 //***************************************************************************
1161 //***************************************************************************
1162 template <typename T>
1163 ETL_CONSTEXPR14 bool operator ==(const etl::optional<T>& lhs, etl::nullopt_t)
1164 {
1165 return !lhs.has_value();
1166 }
1167
1168 //***************************************************************************
1170 //***************************************************************************
1171 template <typename T>
1172 ETL_CONSTEXPR14 bool operator ==(etl::nullopt_t, const etl::optional<T>& rhs)
1173 {
1174 return !rhs.has_value();
1175 }
1176
1177 //***************************************************************************
1179 //***************************************************************************
1180 template <typename T>
1181 ETL_CONSTEXPR14 bool operator !=(const etl::optional<T>& lhs, etl::nullopt_t)
1182 {
1183 return !(lhs == etl::nullopt);
1184 }
1185
1186 //***************************************************************************
1188 //***************************************************************************
1189 template <typename T>
1190 ETL_CONSTEXPR14 bool operator !=(etl::nullopt_t , const etl::optional<T>& rhs)
1191 {
1192 return !(etl::nullopt == rhs);
1193 }
1194
1195 //***************************************************************************
1197 //***************************************************************************
1198 template <typename T>
1199 ETL_CONSTEXPR14 bool operator <(const etl::optional<T>&, etl::nullopt_t)
1200 {
1201 return false;
1202 }
1203
1204 //***************************************************************************
1206 //***************************************************************************
1207 template <typename T>
1208 ETL_CONSTEXPR14 bool operator <(etl::nullopt_t, const etl::optional<T>& rhs)
1209 {
1210 return rhs.has_value();
1211 }
1212
1213 //***************************************************************************
1215 //***************************************************************************
1216 template <typename T>
1217 ETL_CONSTEXPR14 bool operator <=(const etl::optional<T>& lhs, etl::nullopt_t)
1218 {
1219 return !lhs.has_value();
1220 }
1221
1222 //***************************************************************************
1224 //***************************************************************************
1225 template <typename T>
1226 ETL_CONSTEXPR14 bool operator <=(etl::nullopt_t, const etl::optional<T>&)
1227 {
1228 return true;
1229 }
1230
1231 //***************************************************************************
1233 //***************************************************************************
1234 template <typename T>
1235 ETL_CONSTEXPR14 bool operator >(const etl::optional<T>& lhs, etl::nullopt_t)
1236 {
1237 return lhs.has_value();
1238 }
1239
1240 //***************************************************************************
1242 //***************************************************************************
1243 template <typename T>
1244 ETL_CONSTEXPR14 bool operator >(etl::nullopt_t, const etl::optional<T>&)
1245 {
1246 return false;
1247 }
1248
1249 //***************************************************************************
1251 //***************************************************************************
1252 template <typename T>
1253 ETL_CONSTEXPR14 bool operator >=(const etl::optional<T>&, etl::nullopt_t)
1254 {
1255 return true;
1256 }
1257
1258 //***************************************************************************
1260 //***************************************************************************
1261 template <typename T>
1262 ETL_CONSTEXPR14 bool operator >=(etl::nullopt_t, const etl::optional<T>& rhs)
1263 {
1264 return !rhs.has_value();
1265 }
1266
1267 //***************************************************************************
1269 //**************************************************************************
1270 template <typename T, typename U>
1271 ETL_CONSTEXPR14 bool operator ==(const etl::optional<T>& lhs, const U& rhs)
1272 {
1273 return lhs.has_value() ? lhs.value() == rhs : false;
1274 }
1275
1276 //***************************************************************************
1278 //**************************************************************************
1279 template <typename T, typename U>
1280 ETL_CONSTEXPR14 bool operator !=(const etl::optional<T>& lhs, const U& rhs)
1281 {
1282 return !(lhs == rhs);
1283 }
1284
1285 //***************************************************************************
1287 //**************************************************************************
1288 template <typename T, typename U>
1289 ETL_CONSTEXPR14 bool operator ==(const U& lhs, const etl::optional<T>& rhs)
1290 {
1291 return rhs.has_value() ? rhs.value() == lhs : false;
1292 }
1293
1294 //***************************************************************************
1296 //**************************************************************************
1297 template <typename T, typename U>
1298 ETL_CONSTEXPR14 bool operator !=(const U& lhs, const etl::optional<T>& rhs)
1299 {
1300 return !(lhs == rhs);
1301 }
1302
1303 //***************************************************************************
1305 //***************************************************************************
1306 template <typename T, typename U>
1307 ETL_CONSTEXPR14 bool operator <(const etl::optional<T>& lhs, const U& rhs)
1308 {
1309 return lhs.has_value() ? lhs.value() < rhs : true;
1310 }
1311
1312 //***************************************************************************
1314 //***************************************************************************
1315 template <typename T, typename U>
1316 ETL_CONSTEXPR14 bool operator <(const U& lhs, const etl::optional<T>& rhs)
1317 {
1318 return rhs.has_value() ? lhs < rhs.value() : false;
1319 }
1320
1321 //***************************************************************************
1323 //***************************************************************************
1324 template <typename T, typename U>
1325 ETL_CONSTEXPR14 bool operator <=(const etl::optional<T>& lhs, const U& rhs)
1326 {
1327 return lhs.has_value() ? lhs.value() <= rhs : true;
1328 }
1329
1330 //***************************************************************************
1332 //***************************************************************************
1333 template <typename T, typename U>
1334 ETL_CONSTEXPR14 bool operator <=(const U& lhs, const etl::optional<T>& rhs)
1335 {
1336 return rhs.has_value() ? lhs <= rhs.value() : false;
1337 }
1338
1339 //***************************************************************************
1341 //***************************************************************************
1342 template <typename T, typename U>
1343 ETL_CONSTEXPR14 bool operator >(const etl::optional<T>& lhs, const U& rhs)
1344 {
1345 return lhs.has_value() ? lhs.value() > rhs : false;
1346 }
1347
1348 //***************************************************************************
1350 //***************************************************************************
1351 template <typename T, typename U>
1352 ETL_CONSTEXPR14 bool operator >(const U& lhs, const etl::optional<T>& rhs)
1353 {
1354 return rhs.has_value() ? lhs > rhs.value() : true;
1355 }
1356
1357 //***************************************************************************
1359 //***************************************************************************
1360 template <typename T, typename U>
1361 ETL_CONSTEXPR14 bool operator >=(const etl::optional<T>& lhs, const U& rhs)
1362 {
1363 return lhs.has_value() ? lhs.value() >= rhs : false;
1364 }
1365
1366 //***************************************************************************
1368 //***************************************************************************
1369 template <typename T, typename U>
1370 ETL_CONSTEXPR14 bool operator >=(const U& lhs, const etl::optional<T>& rhs)
1371 {
1372 return rhs.has_value() ? lhs >= rhs.value() : true;
1373 }
1374
1376
1377 //***************************************************************************
1379 //***************************************************************************
1380 template <typename T>
1382 {
1384 }
1385
1386 //***************************************************************************
1388 //***************************************************************************
1389#if ETL_CPP17_SUPPORTED
1390 template <typename T>
1391 optional(T) -> optional<T>;
1392#endif
1393}
1394
1395//*************************************************************************
1397//*************************************************************************
1398template <typename T>
1399ETL_CONSTEXPR14 void swap(etl::optional<T>& lhs, etl::optional<T>& rhs)
1400{
1401 lhs.swap(rhs);
1402}
1403
1404#endif
Definition: optional.h:50
ETL_CONSTEXPR20_STL T value_or(const T &default_value) const ETL_LVALUE_REF_QUALIFIER
Gets the value or a default if not valid.
Definition: optional.h:403
ETL_CONSTEXPR20_STL void reset()
Reset back to invalid.
Definition: optional.h:473
ETL_CONSTEXPR20_STL ~optional()
Destructor.
Definition: optional.h:188
ETL_CONSTEXPR20_STL optional(const optional &other)
Copy constructor.
Definition: optional.h:141
ETL_CONSTEXPR optional()
Constructor.
Definition: optional.h:122
T & emplace(const T1 &value1, const T2 &value2)
Definition: optional.h:514
ETL_CONSTEXPR optional(etl::nullopt_t)
Constructor with nullopt.
Definition: optional.h:131
T & emplace(const T1 &value1)
Definition: optional.h:495
ETL_CONSTEXPR20_STL const T & value() const ETL_LVALUE_REF_QUALIFIER
Get a const reference to the value.
Definition: optional.h:390
ETL_CONSTEXPR20_STL T & value() ETL_LVALUE_REF_QUALIFIER
Get a reference to the value.
Definition: optional.h:377
T & emplace(const T1 &value1, const T2 &value2, const T3 &value3)
Definition: optional.h:533
T & emplace(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Definition: optional.h:552
ETL_CONSTEXPR20_STL void swap(optional &other)
Swaps this value with another.
Definition: optional.h:462
ETL_CONSTEXPR20_STL optional(const T &value_)
Constructor from value type.
Definition: optional.h:168
void emplace(const T1 &value1, const T2 &value2, const T3 &value3)
Definition: optional.h:1036
void emplace(const T1 &value1, const T2 &value2)
Definition: optional.h:1025
void emplace(const T1 &value1)
Definition: optional.h:1014
void emplace(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Definition: optional.h:1047
Definition: optional.h:108
#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: exception.h:47
Definition: optional.h:77
Definition: optional.h:91
T * construct_at(T *p)
Definition: memory.h:956
etl::enable_if< etl::is_trivially_destructible< T >::value, void >::type destroy_at(T *)
Definition: memory.h:1006
bitset_ext
Definition: absolute.h:38
bool operator>(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition: array.h:684
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
void destroy(const T *const p)
Destroys the object.
Definition: variant_pool_generator.h:256
ETL_CONSTEXPR14 etl::optional< typename etl::decay< T >::type > make_optional(T &value)
Make an optional.
Definition: optional.h:1381
const nullopt_t nullopt
Definition: optional.h:70
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
ETL_CONSTEXPR14 void swap(etl::optional< T > &lhs, etl::optional< T > &rhs)
Swaps the values.
Definition: optional.h:1399