@@ -25,7 +25,7 @@ struct nullopt_t {
25
25
LIBC_INLINE_VAR constexpr nullopt_t nullopt{};
26
26
27
27
// This is very simple implementation of the std::optional class. It makes
28
- // several assumptions that the underlying type is trivially constructable ,
28
+ // several assumptions that the underlying type is trivially constructible ,
29
29
// copyable, or movable.
30
30
template <typename T> class optional {
31
31
template <typename U, bool = !is_trivially_destructible<U>::value>
@@ -35,46 +35,63 @@ template <typename T> class optional {
35
35
U stored_value;
36
36
};
37
37
38
- LIBC_INLINE ~OptionalStorage () { stored_value.~U (); }
38
+ bool in_use = false ;
39
+
40
+ LIBC_INLINE ~OptionalStorage () { reset (); }
41
+
39
42
LIBC_INLINE constexpr OptionalStorage () : empty() {}
40
43
41
44
template <typename ... Args>
42
45
LIBC_INLINE constexpr explicit OptionalStorage (in_place_t , Args &&...args)
43
46
: stored_value(forward<Args>(args)...) {}
47
+
48
+ LIBC_INLINE constexpr void reset () {
49
+ if (in_use)
50
+ stored_value.~U ();
51
+ in_use = false ;
52
+ }
44
53
};
45
54
55
+ // The only difference is that this type U doesn't have a nontrivial
56
+ // destructor.
46
57
template <typename U> struct OptionalStorage <U, false > {
47
58
union {
48
59
char empty;
49
60
U stored_value;
50
61
};
51
62
52
- // The only difference is that this class doesn't have a destructor.
63
+ bool in_use = false ;
64
+
53
65
LIBC_INLINE constexpr OptionalStorage () : empty() {}
54
66
55
67
template <typename ... Args>
56
68
LIBC_INLINE constexpr explicit OptionalStorage (in_place_t , Args &&...args)
57
69
: stored_value(forward<Args>(args)...) {}
70
+
71
+ LIBC_INLINE constexpr void reset () { in_use = false ; }
58
72
};
59
73
60
74
OptionalStorage<T> storage;
61
- bool in_use = false ;
62
75
63
76
public:
64
77
LIBC_INLINE constexpr optional () = default;
65
78
LIBC_INLINE constexpr optional (nullopt_t ) {}
66
79
67
- LIBC_INLINE constexpr optional (const T &t)
68
- : storage(in_place, t), in_use(true ) {}
80
+ LIBC_INLINE constexpr optional (const T &t) : storage(in_place, t) {
81
+ storage.in_use = true ;
82
+ }
69
83
LIBC_INLINE constexpr optional (const optional &) = default;
70
84
71
- LIBC_INLINE constexpr optional (T &&t)
72
- : storage(in_place, move(t)), in_use(true ) {}
85
+ LIBC_INLINE constexpr optional (T &&t) : storage(in_place, move(t)) {
86
+ storage.in_use = true ;
87
+ }
73
88
LIBC_INLINE constexpr optional (optional &&O) = default;
74
89
75
90
template <typename ... ArgTypes>
76
91
LIBC_INLINE constexpr optional (in_place_t , ArgTypes &&...Args)
77
- : storage(in_place, forward<ArgTypes>(Args)...), in_use(true ) {}
92
+ : storage(in_place, forward<ArgTypes>(Args)...) {
93
+ storage.in_use = true ;
94
+ }
78
95
79
96
LIBC_INLINE constexpr optional &operator =(T &&t) {
80
97
storage = move (t);
@@ -88,20 +105,18 @@ template <typename T> class optional {
88
105
}
89
106
LIBC_INLINE constexpr optional &operator =(const optional &) = default ;
90
107
91
- LIBC_INLINE constexpr void reset () {
92
- if (in_use)
93
- storage.~OptionalStorage ();
94
- in_use = false ;
95
- }
108
+ LIBC_INLINE constexpr void reset () { storage.reset (); }
96
109
97
110
LIBC_INLINE constexpr const T &value () const & {
98
111
return storage.stored_value ;
99
112
}
100
113
101
114
LIBC_INLINE constexpr T &value () & { return storage.stored_value ; }
102
115
103
- LIBC_INLINE constexpr explicit operator bool () const { return in_use; }
104
- LIBC_INLINE constexpr bool has_value () const { return in_use; }
116
+ LIBC_INLINE constexpr explicit operator bool () const {
117
+ return storage.in_use ;
118
+ }
119
+ LIBC_INLINE constexpr bool has_value () const { return storage.in_use ; }
105
120
LIBC_INLINE constexpr const T *operator ->() const {
106
121
return &storage.stored_value ;
107
122
}
0 commit comments