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