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