@@ -23,205 +23,246 @@ namespace vcpkg
2323
2424 namespace details
2525 {
26+ struct EngageTag
27+ {
28+ };
29+
30+ template <class T , bool IsTrivallyDestructible = std::is_trivially_destructible_v<T>>
31+ struct OptionalStorageDtor
32+ {
33+ bool m_is_present;
34+ union
35+ {
36+ char m_inactive;
37+ T m_t ;
38+ };
39+
40+ constexpr OptionalStorageDtor () : m_is_present(false ), m_inactive() { }
41+ template <class ... Args>
42+ constexpr OptionalStorageDtor (EngageTag,
43+ Args&&... args) noexcept (std::is_nothrow_constructible_v<T, Args...>)
44+ : m_is_present(true ), m_t(std::forward<Args>(args)...)
45+ {
46+ }
47+ };
48+
49+ template <class T >
50+ struct OptionalStorageDtor <T, false >
51+ {
52+ bool m_is_present;
53+ union
54+ {
55+ char m_inactive;
56+ T m_t ;
57+ };
58+
59+ constexpr OptionalStorageDtor () : m_is_present(false ), m_inactive() { }
60+ template <class ... Args>
61+ constexpr OptionalStorageDtor (EngageTag,
62+ Args&&... args) noexcept (std::is_nothrow_constructible_v<T, Args...>)
63+ : m_is_present(true ), m_t(std::forward<Args>(args)...)
64+ {
65+ }
66+
67+ ~OptionalStorageDtor ()
68+ {
69+ if (m_is_present)
70+ {
71+ m_t .~T ();
72+ }
73+ }
74+ };
75+
2676 template <class T , bool B = std::is_copy_constructible_v<T>>
27- struct OptionalStorage
77+ struct OptionalStorage : OptionalStorageDtor<T>
2878 {
29- constexpr OptionalStorage () noexcept : m_is_present( false ), m_inactive() { }
79+ OptionalStorage () = default ;
3080 constexpr OptionalStorage (const T& t) noexcept (std::is_nothrow_copy_constructible_v<T>)
31- : m_is_present( true ), m_t( t)
81+ : OptionalStorageDtor<T>(EngageTag{}, t)
3282 {
3383 }
3484 constexpr OptionalStorage (T&& t) noexcept (std::is_nothrow_move_constructible_v<T>)
35- : m_is_present( true ), m_t( std::move(t))
85+ : OptionalStorageDtor<T>(EngageTag{}, std::move(t))
3686 {
3787 }
3888 template <class U , class = std::enable_if_t <!std::is_reference_v<U>>>
3989 explicit OptionalStorage (Optional<U>&& t) noexcept (std::is_nothrow_constructible_v<T, U>)
40- : m_is_present( false ), m_inactive ()
90+ : OptionalStorageDtor<T> ()
4191 {
4292 if (auto p = t.get ())
4393 {
44- m_is_present = true ;
45- new (&m_t ) T (std::move (*p));
94+ this -> m_is_present = true ;
95+ new (&this -> m_t ) T (std::move (*p));
4696 }
4797 }
4898 template <class U >
4999 explicit OptionalStorage (const Optional<U>& t) noexcept (std::is_nothrow_constructible_v<T, const U&>)
50- : m_is_present( false ), m_inactive ()
100+ : OptionalStorageDtor<T> ()
51101 {
52102 if (auto p = t.get ())
53103 {
54- m_is_present = true ;
55- new (&m_t ) T (*p);
104+ this -> m_is_present = true ;
105+ new (&this -> m_t ) T (*p);
56106 }
57107 }
58108
59- ~OptionalStorage ()
60- {
61- if (m_is_present) m_t .~T ();
62- }
63-
64109 OptionalStorage (const OptionalStorage& o) noexcept (std::is_nothrow_copy_constructible_v<T>)
65- : m_is_present(o.m_is_present), m_inactive ()
110+ : OptionalStorageDtor<T> ()
66111 {
67- if (m_is_present) new (&m_t ) T (o.m_t );
112+ if (o.m_is_present )
113+ {
114+ this ->m_is_present = true ;
115+ new (&this ->m_t ) T (o.m_t );
116+ }
68117 }
69118
70119 OptionalStorage (OptionalStorage&& o) noexcept (std::is_nothrow_move_constructible_v<T>)
71- : m_is_present(o.m_is_present), m_inactive ()
120+ : OptionalStorageDtor<T> ()
72121 {
73- if (m_is_present)
122+ if (o. m_is_present )
74123 {
75- new (&m_t ) T (std::move (o.m_t ));
124+ this ->m_is_present = true ;
125+ new (&this ->m_t ) T (std::move (o.m_t ));
76126 }
77127 }
78128
79129 OptionalStorage& operator =(const OptionalStorage& o) noexcept (std::is_nothrow_copy_constructible_v<T> &&
80130 std::is_nothrow_copy_assignable_v<T>)
81131 {
82- if (m_is_present && o.m_is_present )
132+ if (this -> m_is_present && o.m_is_present )
83133 {
84- m_t = o.m_t ;
134+ this -> m_t = o.m_t ;
85135 }
86- else if (!m_is_present && o.m_is_present )
136+ else if (!this -> m_is_present && o.m_is_present )
87137 {
88- new (&m_t ) T (o.m_t );
89- m_is_present = true ;
138+ new (&this -> m_t ) T (o.m_t );
139+ this -> m_is_present = true ;
90140 }
91- else if (m_is_present && !o.m_is_present )
141+ else if (this -> m_is_present && !o.m_is_present )
92142 {
93143 destroy ();
94144 }
145+
95146 return *this ;
96147 }
97148
98149 OptionalStorage& operator =(OptionalStorage&& o) noexcept // enforces termination
99150 {
100- if (m_is_present && o.m_is_present )
151+ if (this -> m_is_present && o.m_is_present )
101152 {
102- m_t = std::move (o.m_t );
153+ this -> m_t = std::move (o.m_t );
103154 }
104- else if (!m_is_present && o.m_is_present )
155+ else if (!this -> m_is_present && o.m_is_present )
105156 {
106- new (&m_t ) T (std::move (o.m_t ));
107- m_is_present = true ;
157+ new (&this -> m_t ) T (std::move (o.m_t ));
158+ this -> m_is_present = true ;
108159 }
109- else if (m_is_present && !o.m_is_present )
160+ else if (this -> m_is_present && !o.m_is_present )
110161 {
111162 destroy ();
112163 }
113164 return *this ;
114165 }
115166
116- constexpr bool has_value () const noexcept { return m_is_present; }
167+ constexpr bool has_value () const noexcept { return this -> m_is_present ; }
117168
118169 const T& value () const noexcept { return this ->m_t ; }
119170 T& value () noexcept { return this ->m_t ; }
120171
121- const T* get () const & noexcept { return m_is_present ? &m_t : nullptr ; }
122- T* get () & noexcept { return m_is_present ? &m_t : nullptr ; }
172+ const T* get () const & noexcept { return this -> m_is_present ? &this -> m_t : nullptr ; }
173+ T* get () & noexcept { return this -> m_is_present ? &this -> m_t : nullptr ; }
123174 const T* get () const && = delete;
124175 T* get () && = delete;
125176
126177 void destroy () noexcept // enforces termination
127178 {
128- m_is_present = false ;
129- m_t .~T ();
130- m_inactive = ' \0 ' ;
179+ this -> m_is_present = false ;
180+ this -> m_t .~T ();
181+ this -> m_inactive = ' \0 ' ;
131182 }
132183
133184 template <class ... Args>
134185 T& emplace (Args&&... args) noexcept (std::is_nothrow_constructible_v<T, Args...>)
135186 {
136- if (m_is_present) destroy ();
137- new (&m_t ) T (static_cast <Args&&>(args)...);
138- m_is_present = true ;
139- return m_t ;
187+ if (this -> m_is_present ) destroy ();
188+ new (&this -> m_t ) T (static_cast <Args&&>(args)...);
189+ this -> m_is_present = true ;
190+ return this -> m_t ;
140191 }
141-
142- private:
143- bool m_is_present;
144- union
145- {
146- char m_inactive;
147- T m_t ;
148- };
149192 };
150193
151194 template <class T >
152- struct OptionalStorage <T, false >
195+ struct OptionalStorage <T, false > : OptionalStorageDtor<T>
153196 {
154- constexpr OptionalStorage () noexcept : m_is_present( false ), m_inactive() { }
197+ OptionalStorage () = default ;
155198 constexpr OptionalStorage (T&& t) noexcept (std::is_nothrow_move_constructible_v<T>)
156- : m_is_present( true ), m_t( std::move(t))
199+ : OptionalStorageDtor<T>(EngageTag{}, std::move(t))
157200 {
158201 }
159-
160- ~OptionalStorage ()
202+ template <class U , class = std::enable_if_t <!std::is_reference_v<U>>>
203+ explicit OptionalStorage (Optional<U>&& t) noexcept (std::is_nothrow_constructible_v<T, U>)
204+ : OptionalStorageDtor<T>()
161205 {
162- if (m_is_present) m_t .~T ();
206+ if (auto p = t.get ())
207+ {
208+ this ->m_is_present = true ;
209+ new (&this ->m_t ) T (std::move (*p));
210+ }
163211 }
164-
165212 OptionalStorage (OptionalStorage&& o) noexcept (std::is_nothrow_move_constructible_v<T>)
166- : m_is_present(o.m_is_present), m_inactive ()
213+ : OptionalStorageDtor<T> ()
167214 {
168- if (m_is_present)
215+ if (o. m_is_present )
169216 {
170- new (&m_t ) T (std::move (o.m_t ));
217+ this ->m_is_present = true ;
218+ new (&this ->m_t ) T (std::move (o.m_t ));
171219 }
172220 }
173221
174222 OptionalStorage& operator =(OptionalStorage&& o) noexcept // enforces termination
175223 {
176- if (m_is_present && o.m_is_present )
224+ if (this -> m_is_present && o.m_is_present )
177225 {
178- m_t = std::move (o.m_t );
226+ this -> m_t = std::move (o.m_t );
179227 }
180- else if (!m_is_present && o.m_is_present )
228+ else if (!this -> m_is_present && o.m_is_present )
181229 {
182- m_is_present = true ;
183- new (&m_t ) T (std::move (o.m_t ));
230+ this -> m_is_present = true ;
231+ new (&this -> m_t ) T (std::move (o.m_t ));
184232 }
185- else if (m_is_present && !o.m_is_present )
233+ else if (this -> m_is_present && !o.m_is_present )
186234 {
187235 destroy ();
188236 }
237+
189238 return *this ;
190239 }
191240
192- constexpr bool has_value () const noexcept { return m_is_present; }
241+ constexpr bool has_value () const noexcept { return this -> m_is_present ; }
193242
194243 const T& value () const noexcept { return this ->m_t ; }
195244 T& value () noexcept { return this ->m_t ; }
196245
197- const T* get () const & noexcept { return m_is_present ? &m_t : nullptr ; }
198- T* get () & noexcept { return m_is_present ? &m_t : nullptr ; }
246+ const T* get () const & noexcept { return this -> m_is_present ? &this -> m_t : nullptr ; }
247+ T* get () & noexcept { return this -> m_is_present ? &this -> m_t : nullptr ; }
199248 const T* get () const && = delete;
200249 T* get () && = delete;
201250
202251 template <class ... Args>
203252 T& emplace (Args&&... args) noexcept (std::is_nothrow_constructible_v<T, Args...>)
204253 {
205- if (m_is_present) destroy ();
206- new (&m_t ) T (static_cast <Args&&>(args)...);
207- m_is_present = true ;
208- return m_t ;
254+ if (this -> m_is_present ) destroy ();
255+ new (&this -> m_t ) T (static_cast <Args&&>(args)...);
256+ this -> m_is_present = true ;
257+ return this -> m_t ;
209258 }
210259
211260 void destroy () noexcept
212261 {
213- m_is_present = false ;
214- m_t .~T ();
215- m_inactive = ' \0 ' ;
262+ this -> m_is_present = false ;
263+ this -> m_t .~T ();
264+ this -> m_inactive = ' \0 ' ;
216265 }
217-
218- private:
219- bool m_is_present;
220- union
221- {
222- char m_inactive;
223- T m_t ;
224- };
225266 };
226267
227268 template <class T , bool B>
0 commit comments