1 | // -*- C++ -*- |
2 | //===----------------------------------------------------------------------===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef _LIBCPP_OPTIONAL |
11 | #define _LIBCPP_OPTIONAL |
12 | |
13 | /* |
14 | optional synopsis |
15 | |
16 | // C++1z |
17 | |
18 | namespace std { |
19 | // [optional.optional], class template optional |
20 | template <class T> |
21 | class optional; |
22 | |
23 | template<class T> |
24 | concept is-derived-from-optional = requires(const T& t) { // exposition only |
25 | []<class U>(const optional<U>&){ }(t); |
26 | }; |
27 | |
28 | // [optional.nullopt], no-value state indicator |
29 | struct nullopt_t{see below }; |
30 | inline constexpr nullopt_t nullopt(unspecified ); |
31 | |
32 | // [optional.bad.access], class bad_optional_access |
33 | class bad_optional_access; |
34 | |
35 | // [optional.relops], relational operators |
36 | template <class T, class U> |
37 | constexpr bool operator==(const optional<T>&, const optional<U>&); |
38 | template <class T, class U> |
39 | constexpr bool operator!=(const optional<T>&, const optional<U>&); |
40 | template <class T, class U> |
41 | constexpr bool operator<(const optional<T>&, const optional<U>&); |
42 | template <class T, class U> |
43 | constexpr bool operator>(const optional<T>&, const optional<U>&); |
44 | template <class T, class U> |
45 | constexpr bool operator<=(const optional<T>&, const optional<U>&); |
46 | template <class T, class U> |
47 | constexpr bool operator>=(const optional<T>&, const optional<U>&); |
48 | template<class T, three_way_comparable_with<T> U> |
49 | constexpr compare_three_way_result_t<T, U> |
50 | operator<=>(const optional<T>&, const optional<U>&); // since C++20 |
51 | |
52 | // [optional.nullops], comparison with nullopt |
53 | template<class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; |
54 | template<class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; // until C++17 |
55 | template<class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; // until C++17 |
56 | template<class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; // until C++17 |
57 | template<class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; // until C++17 |
58 | template<class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; // until C++17 |
59 | template<class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; // until C++17 |
60 | template<class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; // until C++17 |
61 | template<class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept; // until C++17 |
62 | template<class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept; // until C++17 |
63 | template<class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; // until C++17 |
64 | template<class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; // until C++17 |
65 | template<class T> |
66 | constexpr strong_ordering operator<=>(const optional<T>&, nullopt_t) noexcept; // since C++20 |
67 | |
68 | // [optional.comp.with.t], comparison with T |
69 | template<class T, class U> constexpr bool operator==(const optional<T>&, const U&); |
70 | template<class T, class U> constexpr bool operator==(const T&, const optional<U>&); |
71 | template<class T, class U> constexpr bool operator!=(const optional<T>&, const U&); |
72 | template<class T, class U> constexpr bool operator!=(const T&, const optional<U>&); |
73 | template<class T, class U> constexpr bool operator<(const optional<T>&, const U&); |
74 | template<class T, class U> constexpr bool operator<(const T&, const optional<U>&); |
75 | template<class T, class U> constexpr bool operator<=(const optional<T>&, const U&); |
76 | template<class T, class U> constexpr bool operator<=(const T&, const optional<U>&); |
77 | template<class T, class U> constexpr bool operator>(const optional<T>&, const U&); |
78 | template<class T, class U> constexpr bool operator>(const T&, const optional<U>&); |
79 | template<class T, class U> constexpr bool operator>=(const optional<T>&, const U&); |
80 | template<class T, class U> constexpr bool operator>=(const T&, const optional<U>&); |
81 | template<class T, class U> |
82 | requires (!is-derived-from-optional<U>) && three_way_comparable_with<T, U> |
83 | constexpr compare_three_way_result_t<T, U> |
84 | operator<=>(const optional<T>&, const U&); // since C++20 |
85 | |
86 | // [optional.specalg], specialized algorithms |
87 | template<class T> |
88 | void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20 |
89 | |
90 | template<class T> |
91 | constexpr optional<see below > make_optional(T&&); |
92 | template<class T, class... Args> |
93 | constexpr optional<T> make_optional(Args&&... args); |
94 | template<class T, class U, class... Args> |
95 | constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); |
96 | |
97 | // [optional.hash], hash support |
98 | template<class T> struct hash; |
99 | template<class T> struct hash<optional<T>>; |
100 | |
101 | template<class T> |
102 | class optional { |
103 | public: |
104 | using value_type = T; |
105 | |
106 | // [optional.ctor], constructors |
107 | constexpr optional() noexcept; |
108 | constexpr optional(nullopt_t) noexcept; |
109 | constexpr optional(const optional &); |
110 | constexpr optional(optional &&) noexcept(see below); |
111 | template<class... Args> |
112 | constexpr explicit optional(in_place_t, Args &&...); |
113 | template<class U, class... Args> |
114 | constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...); |
115 | template<class U = T> |
116 | constexpr explicit(see-below) optional(U &&); |
117 | template<class U> |
118 | explicit(see-below) optional(const optional<U> &); // constexpr in C++20 |
119 | template<class U> |
120 | explicit(see-below) optional(optional<U> &&); // constexpr in C++20 |
121 | |
122 | // [optional.dtor], destructor |
123 | ~optional(); // constexpr in C++20 |
124 | |
125 | // [optional.assign], assignment |
126 | optional &operator=(nullopt_t) noexcept; // constexpr in C++20 |
127 | constexpr optional &operator=(const optional &); |
128 | constexpr optional &operator=(optional &&) noexcept(see below); |
129 | template<class U = T> optional &operator=(U &&); // constexpr in C++20 |
130 | template<class U> optional &operator=(const optional<U> &); // constexpr in C++20 |
131 | template<class U> optional &operator=(optional<U> &&); // constexpr in C++20 |
132 | template<class... Args> T& emplace(Args &&...); // constexpr in C++20 |
133 | template<class U, class... Args> T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20 |
134 | |
135 | // [optional.swap], swap |
136 | void swap(optional &) noexcept(see below ); // constexpr in C++20 |
137 | |
138 | // [optional.observe], observers |
139 | constexpr T const *operator->() const noexcept; |
140 | constexpr T *operator->() noexcept; |
141 | constexpr T const &operator*() const & noexcept; |
142 | constexpr T &operator*() & noexcept; |
143 | constexpr T &&operator*() && noexcept; |
144 | constexpr const T &&operator*() const && noexcept; |
145 | constexpr explicit operator bool() const noexcept; |
146 | constexpr bool has_value() const noexcept; |
147 | constexpr T const &value() const &; |
148 | constexpr T &value() &; |
149 | constexpr T &&value() &&; |
150 | constexpr const T &&value() const &&; |
151 | template<class U> constexpr T value_or(U &&) const &; |
152 | template<class U> constexpr T value_or(U &&) &&; |
153 | |
154 | // [optional.monadic], monadic operations |
155 | template<class F> constexpr auto and_then(F&& f) &; // since C++23 |
156 | template<class F> constexpr auto and_then(F&& f) &&; // since C++23 |
157 | template<class F> constexpr auto and_then(F&& f) const&; // since C++23 |
158 | template<class F> constexpr auto and_then(F&& f) const&&; // since C++23 |
159 | template<class F> constexpr auto transform(F&& f) &; // since C++23 |
160 | template<class F> constexpr auto transform(F&& f) &&; // since C++23 |
161 | template<class F> constexpr auto transform(F&& f) const&; // since C++23 |
162 | template<class F> constexpr auto transform(F&& f) const&&; // since C++23 |
163 | template<class F> constexpr optional or_else(F&& f) &&; // since C++23 |
164 | template<class F> constexpr optional or_else(F&& f) const&; // since C++23 |
165 | |
166 | // [optional.mod], modifiers |
167 | void reset() noexcept; // constexpr in C++20 |
168 | |
169 | private: |
170 | T *val; // exposition only |
171 | }; |
172 | |
173 | template<class T> |
174 | optional(T) -> optional<T>; |
175 | |
176 | } // namespace std |
177 | |
178 | */ |
179 | |
180 | #if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) |
181 | # include <__cxx03/__config> |
182 | #else |
183 | # include <__assert> |
184 | # include <__compare/compare_three_way_result.h> |
185 | # include <__compare/ordering.h> |
186 | # include <__compare/three_way_comparable.h> |
187 | # include <__concepts/invocable.h> |
188 | # include <__config> |
189 | # include <__exception/exception.h> |
190 | # include <__functional/hash.h> |
191 | # include <__functional/invoke.h> |
192 | # include <__functional/unary_function.h> |
193 | # include <__fwd/functional.h> |
194 | # include <__memory/addressof.h> |
195 | # include <__memory/construct_at.h> |
196 | # include <__tuple/sfinae_helpers.h> |
197 | # include <__type_traits/add_pointer.h> |
198 | # include <__type_traits/conditional.h> |
199 | # include <__type_traits/conjunction.h> |
200 | # include <__type_traits/decay.h> |
201 | # include <__type_traits/disjunction.h> |
202 | # include <__type_traits/enable_if.h> |
203 | # include <__type_traits/invoke.h> |
204 | # include <__type_traits/is_array.h> |
205 | # include <__type_traits/is_assignable.h> |
206 | # include <__type_traits/is_constructible.h> |
207 | # include <__type_traits/is_convertible.h> |
208 | # include <__type_traits/is_destructible.h> |
209 | # include <__type_traits/is_nothrow_assignable.h> |
210 | # include <__type_traits/is_nothrow_constructible.h> |
211 | # include <__type_traits/is_object.h> |
212 | # include <__type_traits/is_reference.h> |
213 | # include <__type_traits/is_replaceable.h> |
214 | # include <__type_traits/is_same.h> |
215 | # include <__type_traits/is_scalar.h> |
216 | # include <__type_traits/is_swappable.h> |
217 | # include <__type_traits/is_trivially_assignable.h> |
218 | # include <__type_traits/is_trivially_constructible.h> |
219 | # include <__type_traits/is_trivially_destructible.h> |
220 | # include <__type_traits/is_trivially_relocatable.h> |
221 | # include <__type_traits/negation.h> |
222 | # include <__type_traits/remove_const.h> |
223 | # include <__type_traits/remove_cv.h> |
224 | # include <__type_traits/remove_cvref.h> |
225 | # include <__type_traits/remove_reference.h> |
226 | # include <__utility/declval.h> |
227 | # include <__utility/forward.h> |
228 | # include <__utility/in_place.h> |
229 | # include <__utility/move.h> |
230 | # include <__utility/swap.h> |
231 | # include <__verbose_abort> |
232 | # include <initializer_list> |
233 | # include <version> |
234 | |
235 | // standard-mandated includes |
236 | |
237 | // [optional.syn] |
238 | # include <compare> |
239 | |
240 | # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
241 | # pragma GCC system_header |
242 | # endif |
243 | |
244 | _LIBCPP_PUSH_MACROS |
245 | # include <__undef_macros> |
246 | |
247 | namespace std // purposefully not using versioning namespace |
248 | { |
249 | |
250 | class _LIBCPP_EXPORTED_FROM_ABI bad_optional_access : public exception { |
251 | public: |
252 | _LIBCPP_HIDE_FROM_ABI bad_optional_access() _NOEXCEPT = default; |
253 | _LIBCPP_HIDE_FROM_ABI bad_optional_access(const bad_optional_access&) _NOEXCEPT = default; |
254 | _LIBCPP_HIDE_FROM_ABI bad_optional_access& operator=(const bad_optional_access&) _NOEXCEPT = default; |
255 | // Get the key function ~bad_optional_access() into the dylib |
256 | ~bad_optional_access() _NOEXCEPT override; |
257 | const char* what() const _NOEXCEPT override; |
258 | }; |
259 | |
260 | } // namespace std |
261 | |
262 | # if _LIBCPP_STD_VER >= 17 |
263 | |
264 | _LIBCPP_BEGIN_NAMESPACE_STD |
265 | |
266 | [[noreturn]] inline _LIBCPP_HIDE_FROM_ABI void __throw_bad_optional_access() { |
267 | # if _LIBCPP_HAS_EXCEPTIONS |
268 | throw bad_optional_access(); |
269 | # else |
270 | _LIBCPP_VERBOSE_ABORT("bad_optional_access was thrown in -fno-exceptions mode" ); |
271 | # endif |
272 | } |
273 | |
274 | struct nullopt_t { |
275 | struct __secret_tag { |
276 | explicit __secret_tag() = default; |
277 | }; |
278 | _LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {} |
279 | }; |
280 | |
281 | inline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}}; |
282 | |
283 | struct __optional_construct_from_invoke_tag {}; |
284 | |
285 | template <class _Tp, bool = is_trivially_destructible<_Tp>::value> |
286 | struct __optional_destruct_base; |
287 | |
288 | template <class _Tp> |
289 | struct __optional_destruct_base<_Tp, false> { |
290 | typedef _Tp value_type; |
291 | static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior" ); |
292 | union { |
293 | char __null_state_; |
294 | remove_cv_t<value_type> __val_; |
295 | }; |
296 | bool __engaged_; |
297 | |
298 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__optional_destruct_base() { |
299 | if (__engaged_) |
300 | __val_.~value_type(); |
301 | } |
302 | |
303 | _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {} |
304 | |
305 | template <class... _Args> |
306 | _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) |
307 | : __val_(std::forward<_Args>(__args)...), __engaged_(true) {} |
308 | |
309 | # if _LIBCPP_STD_VER >= 23 |
310 | template <class _Fp, class... _Args> |
311 | _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base( |
312 | __optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) |
313 | : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {} |
314 | # endif |
315 | |
316 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { |
317 | if (__engaged_) { |
318 | __val_.~value_type(); |
319 | __engaged_ = false; |
320 | } |
321 | } |
322 | }; |
323 | |
324 | template <class _Tp> |
325 | struct __optional_destruct_base<_Tp, true> { |
326 | typedef _Tp value_type; |
327 | static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior" ); |
328 | union { |
329 | char __null_state_; |
330 | remove_cv_t<value_type> __val_; |
331 | }; |
332 | bool __engaged_; |
333 | |
334 | _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {} |
335 | |
336 | template <class... _Args> |
337 | _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) |
338 | : __val_(std::forward<_Args>(__args)...), __engaged_(true) {} |
339 | |
340 | # if _LIBCPP_STD_VER >= 23 |
341 | template <class _Fp, class... _Args> |
342 | _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base( |
343 | __optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) |
344 | : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {} |
345 | # endif |
346 | |
347 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { |
348 | if (__engaged_) { |
349 | __engaged_ = false; |
350 | } |
351 | } |
352 | }; |
353 | |
354 | template <class _Tp, bool = is_reference<_Tp>::value> |
355 | struct __optional_storage_base : __optional_destruct_base<_Tp> { |
356 | using __base _LIBCPP_NODEBUG = __optional_destruct_base<_Tp>; |
357 | using value_type = _Tp; |
358 | using __base::__base; |
359 | |
360 | _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__engaged_; } |
361 | |
362 | _LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() & noexcept { return this->__val_; } |
363 | _LIBCPP_HIDE_FROM_ABI constexpr const value_type& __get() const& noexcept { return this->__val_; } |
364 | _LIBCPP_HIDE_FROM_ABI constexpr value_type&& __get() && noexcept { return std::move(this->__val_); } |
365 | _LIBCPP_HIDE_FROM_ABI constexpr const value_type&& __get() const&& noexcept { return std::move(this->__val_); } |
366 | |
367 | template <class... _Args> |
368 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_Args&&... __args) { |
369 | _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage" ); |
370 | std::__construct_at(std::addressof(this->__val_), std::forward<_Args>(__args)...); |
371 | this->__engaged_ = true; |
372 | } |
373 | |
374 | template <class _That> |
375 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) { |
376 | if (__opt.has_value()) |
377 | __construct(std::forward<_That>(__opt).__get()); |
378 | } |
379 | |
380 | template <class _That> |
381 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) { |
382 | if (this->__engaged_ == __opt.has_value()) { |
383 | if (this->__engaged_) |
384 | static_cast<_Tp&>(this->__val_) = std::forward<_That>(__opt).__get(); |
385 | } else { |
386 | if (this->__engaged_) |
387 | this->reset(); |
388 | else |
389 | __construct(std::forward<_That>(__opt).__get()); |
390 | } |
391 | } |
392 | }; |
393 | |
394 | // optional<T&> is currently required to be ill-formed. However, it may |
395 | // be allowed in the future. For this reason, it has already been implemented |
396 | // to ensure we can make the change in an ABI-compatible manner. |
397 | template <class _Tp> |
398 | struct __optional_storage_base<_Tp, true> { |
399 | using value_type = _Tp; |
400 | using __raw_type _LIBCPP_NODEBUG = remove_reference_t<_Tp>; |
401 | __raw_type* __value_; |
402 | |
403 | template <class _Up> |
404 | static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() { |
405 | using _RawUp = __libcpp_remove_reference_t<_Up>; |
406 | using _UpPtr = _RawUp*; |
407 | using _RawTp = __libcpp_remove_reference_t<_Tp>; |
408 | using _TpPtr = _RawTp*; |
409 | using _CheckLValueArg = |
410 | integral_constant<bool, |
411 | (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value) || |
412 | is_same<_RawUp, reference_wrapper<_RawTp>>::value || |
413 | is_same<_RawUp, reference_wrapper<__remove_const_t<_RawTp>>>::value >; |
414 | return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) || |
415 | (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value && |
416 | is_convertible<_UpPtr, _TpPtr>::value); |
417 | } |
418 | |
419 | _LIBCPP_HIDE_FROM_ABI constexpr __optional_storage_base() noexcept : __value_(nullptr) {} |
420 | |
421 | template <class _UArg> |
422 | _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg) |
423 | : __value_(std::addressof(__uarg)) { |
424 | static_assert(__can_bind_reference<_UArg>(), |
425 | "Attempted to construct a reference element in tuple from a " |
426 | "possible temporary" ); |
427 | } |
428 | |
429 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; } |
430 | |
431 | _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __value_ != nullptr; } |
432 | |
433 | _LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() const& noexcept { return *__value_; } |
434 | |
435 | _LIBCPP_HIDE_FROM_ABI constexpr value_type&& __get() const&& noexcept { return std::forward<value_type>(*__value_); } |
436 | |
437 | template <class _UArg> |
438 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val) { |
439 | _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage" ); |
440 | static_assert(__can_bind_reference<_UArg>(), |
441 | "Attempted to construct a reference element in tuple from a " |
442 | "possible temporary" ); |
443 | __value_ = std::addressof(__val); |
444 | } |
445 | |
446 | template <class _That> |
447 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) { |
448 | if (__opt.has_value()) |
449 | __construct(std::forward<_That>(__opt).__get()); |
450 | } |
451 | |
452 | template <class _That> |
453 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) { |
454 | if (has_value() == __opt.has_value()) { |
455 | if (has_value()) |
456 | *__value_ = std::forward<_That>(__opt).__get(); |
457 | } else { |
458 | if (has_value()) |
459 | reset(); |
460 | else |
461 | __construct(std::forward<_That>(__opt).__get()); |
462 | } |
463 | } |
464 | }; |
465 | |
466 | template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value> |
467 | struct __optional_copy_base : __optional_storage_base<_Tp> { |
468 | using __optional_storage_base<_Tp>::__optional_storage_base; |
469 | }; |
470 | |
471 | template <class _Tp> |
472 | struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> { |
473 | using __optional_storage_base<_Tp>::__optional_storage_base; |
474 | |
475 | _LIBCPP_HIDE_FROM_ABI __optional_copy_base() = default; |
476 | |
477 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_base(const __optional_copy_base& __opt) { |
478 | this->__construct_from(__opt); |
479 | } |
480 | |
481 | _LIBCPP_HIDE_FROM_ABI __optional_copy_base(__optional_copy_base&&) = default; |
482 | _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(const __optional_copy_base&) = default; |
483 | _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(__optional_copy_base&&) = default; |
484 | }; |
485 | |
486 | template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value> |
487 | struct __optional_move_base : __optional_copy_base<_Tp> { |
488 | using __optional_copy_base<_Tp>::__optional_copy_base; |
489 | }; |
490 | |
491 | template <class _Tp> |
492 | struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> { |
493 | using value_type = _Tp; |
494 | using __optional_copy_base<_Tp>::__optional_copy_base; |
495 | |
496 | _LIBCPP_HIDE_FROM_ABI __optional_move_base() = default; |
497 | _LIBCPP_HIDE_FROM_ABI __optional_move_base(const __optional_move_base&) = default; |
498 | |
499 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 |
500 | __optional_move_base(__optional_move_base&& __opt) noexcept(is_nothrow_move_constructible_v<value_type>) { |
501 | this->__construct_from(std::move(__opt)); |
502 | } |
503 | |
504 | _LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(const __optional_move_base&) = default; |
505 | _LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(__optional_move_base&&) = default; |
506 | }; |
507 | |
508 | template <class _Tp, |
509 | bool = is_trivially_destructible<_Tp>::value && is_trivially_copy_constructible<_Tp>::value && |
510 | is_trivially_copy_assignable<_Tp>::value> |
511 | struct __optional_copy_assign_base : __optional_move_base<_Tp> { |
512 | using __optional_move_base<_Tp>::__optional_move_base; |
513 | }; |
514 | |
515 | template <class _Tp> |
516 | struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> { |
517 | using __optional_move_base<_Tp>::__optional_move_base; |
518 | |
519 | _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base() = default; |
520 | _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(const __optional_copy_assign_base&) = default; |
521 | _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(__optional_copy_assign_base&&) = default; |
522 | |
523 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_assign_base& |
524 | operator=(const __optional_copy_assign_base& __opt) { |
525 | this->__assign_from(__opt); |
526 | return *this; |
527 | } |
528 | |
529 | _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; |
530 | }; |
531 | |
532 | template <class _Tp, |
533 | bool = is_trivially_destructible<_Tp>::value && is_trivially_move_constructible<_Tp>::value && |
534 | is_trivially_move_assignable<_Tp>::value> |
535 | struct __optional_move_assign_base : __optional_copy_assign_base<_Tp> { |
536 | using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; |
537 | }; |
538 | |
539 | template <class _Tp> |
540 | struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> { |
541 | using value_type = _Tp; |
542 | using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base; |
543 | |
544 | _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base() = default; |
545 | _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(const __optional_move_assign_base& __opt) = default; |
546 | _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(__optional_move_assign_base&&) = default; |
547 | _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; |
548 | |
549 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_assign_base& |
550 | operator=(__optional_move_assign_base&& __opt) noexcept( |
551 | is_nothrow_move_assignable_v<value_type> && is_nothrow_move_constructible_v<value_type>) { |
552 | this->__assign_from(std::move(__opt)); |
553 | return *this; |
554 | } |
555 | }; |
556 | |
557 | template <class _Tp> |
558 | using __optional_sfinae_ctor_base_t _LIBCPP_NODEBUG = |
559 | __sfinae_ctor_base< is_copy_constructible<_Tp>::value, is_move_constructible<_Tp>::value >; |
560 | |
561 | template <class _Tp> |
562 | using __optional_sfinae_assign_base_t _LIBCPP_NODEBUG = |
563 | __sfinae_assign_base< (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value), |
564 | (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) >; |
565 | |
566 | template <class _Tp> |
567 | class optional; |
568 | |
569 | # if _LIBCPP_STD_VER >= 20 |
570 | |
571 | template <class _Tp> |
572 | concept __is_derived_from_optional = requires(const _Tp& __t) { []<class _Up>(const optional<_Up>&) {}(__t); }; |
573 | |
574 | # endif // _LIBCPP_STD_VER >= 20 |
575 | |
576 | template <class _Tp> |
577 | struct __is_std_optional : false_type {}; |
578 | template <class _Tp> |
579 | struct __is_std_optional<optional<_Tp>> : true_type {}; |
580 | |
581 | template <class _Tp> |
582 | class _LIBCPP_DECLSPEC_EMPTY_BASES optional |
583 | : private __optional_move_assign_base<_Tp>, |
584 | private __optional_sfinae_ctor_base_t<_Tp>, |
585 | private __optional_sfinae_assign_base_t<_Tp> { |
586 | using __base _LIBCPP_NODEBUG = __optional_move_assign_base<_Tp>; |
587 | |
588 | public: |
589 | using value_type = _Tp; |
590 | |
591 | using __trivially_relocatable _LIBCPP_NODEBUG = |
592 | conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, optional, void>; |
593 | using __replaceable _LIBCPP_NODEBUG = conditional_t<__is_replaceable_v<_Tp>, optional, void>; |
594 | |
595 | private: |
596 | // Disable the reference extension using this static assert. |
597 | static_assert(!is_same_v<__remove_cvref_t<value_type>, in_place_t>, |
598 | "instantiation of optional with in_place_t is ill-formed" ); |
599 | static_assert(!is_same_v<__remove_cvref_t<value_type>, nullopt_t>, |
600 | "instantiation of optional with nullopt_t is ill-formed" ); |
601 | static_assert(!is_reference_v<value_type>, "instantiation of optional with a reference type is ill-formed" ); |
602 | static_assert(is_destructible_v<value_type>, "instantiation of optional with a non-destructible type is ill-formed" ); |
603 | static_assert(!is_array_v<value_type>, "instantiation of optional with an array type is ill-formed" ); |
604 | |
605 | // LWG2756: conditionally explicit conversion from _Up |
606 | struct _CheckOptionalArgsConstructor { |
607 | template <class _Up> |
608 | _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() { |
609 | return is_constructible_v<_Tp, _Up&&> && is_convertible_v<_Up&&, _Tp>; |
610 | } |
611 | |
612 | template <class _Up> |
613 | _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() { |
614 | return is_constructible_v<_Tp, _Up&&> && !is_convertible_v<_Up&&, _Tp>; |
615 | } |
616 | }; |
617 | template <class _Up> |
618 | using _CheckOptionalArgsCtor _LIBCPP_NODEBUG = |
619 | _If< _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value && _IsNotSame<__remove_cvref_t<_Up>, optional>::value && |
620 | (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_optional<__remove_cvref_t<_Up>>::value), |
621 | _CheckOptionalArgsConstructor, |
622 | __check_tuple_constructor_fail >; |
623 | template <class _QualUp> |
624 | struct _CheckOptionalLikeConstructor { |
625 | template <class _Up, class _Opt = optional<_Up>> |
626 | using __check_constructible_from_opt _LIBCPP_NODEBUG = |
627 | _Or< is_constructible<_Tp, _Opt&>, |
628 | is_constructible<_Tp, _Opt const&>, |
629 | is_constructible<_Tp, _Opt&&>, |
630 | is_constructible<_Tp, _Opt const&&>, |
631 | is_convertible<_Opt&, _Tp>, |
632 | is_convertible<_Opt const&, _Tp>, |
633 | is_convertible<_Opt&&, _Tp>, |
634 | is_convertible<_Opt const&&, _Tp> >; |
635 | template <class _Up, class _Opt = optional<_Up>> |
636 | using __check_assignable_from_opt _LIBCPP_NODEBUG = |
637 | _Or< is_assignable<_Tp&, _Opt&>, |
638 | is_assignable<_Tp&, _Opt const&>, |
639 | is_assignable<_Tp&, _Opt&&>, |
640 | is_assignable<_Tp&, _Opt const&&> >; |
641 | template <class _Up, class _QUp = _QualUp> |
642 | _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() { |
643 | return is_convertible<_QUp, _Tp>::value && |
644 | (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value); |
645 | } |
646 | template <class _Up, class _QUp = _QualUp> |
647 | _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() { |
648 | return !is_convertible<_QUp, _Tp>::value && |
649 | (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value); |
650 | } |
651 | template <class _Up, class _QUp = _QualUp> |
652 | _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_assign() { |
653 | // Construction and assignability of _QUp to _Tp has already been |
654 | // checked. |
655 | return !__check_constructible_from_opt<_Up>::value && !__check_assignable_from_opt<_Up>::value; |
656 | } |
657 | }; |
658 | |
659 | template <class _Up, class _QualUp> |
660 | using _CheckOptionalLikeCtor _LIBCPP_NODEBUG = |
661 | _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp> >::value, |
662 | _CheckOptionalLikeConstructor<_QualUp>, |
663 | __check_tuple_constructor_fail >; |
664 | template <class _Up, class _QualUp> |
665 | using _CheckOptionalLikeAssign _LIBCPP_NODEBUG = |
666 | _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp>, is_assignable<_Tp&, _QualUp> >::value, |
667 | _CheckOptionalLikeConstructor<_QualUp>, |
668 | __check_tuple_constructor_fail >; |
669 | |
670 | public: |
671 | _LIBCPP_HIDE_FROM_ABI constexpr optional() noexcept {} |
672 | _LIBCPP_HIDE_FROM_ABI constexpr optional(const optional&) = default; |
673 | _LIBCPP_HIDE_FROM_ABI constexpr optional(optional&&) = default; |
674 | _LIBCPP_HIDE_FROM_ABI constexpr optional(nullopt_t) noexcept {} |
675 | |
676 | template <class _InPlaceT, |
677 | class... _Args, |
678 | enable_if_t<_And<_IsSame<_InPlaceT, in_place_t>, is_constructible<value_type, _Args...>>::value, int> = 0> |
679 | _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_InPlaceT, _Args&&... __args) |
680 | : __base(in_place, std::forward<_Args>(__args)...) {} |
681 | |
682 | template <class _Up, |
683 | class... _Args, |
684 | enable_if_t<is_constructible_v<value_type, initializer_list<_Up>&, _Args...>, int> = 0> |
685 | _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) |
686 | : __base(in_place, __il, std::forward<_Args>(__args)...) {} |
687 | |
688 | template <class _Up = value_type, |
689 | enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0> |
690 | _LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {} |
691 | |
692 | template <class _Up, enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0> |
693 | _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {} |
694 | |
695 | // LWG2756: conditionally explicit conversion from const optional<_Up>& |
696 | template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0> |
697 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) { |
698 | this->__construct_from(__v); |
699 | } |
700 | template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0> |
701 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) { |
702 | this->__construct_from(__v); |
703 | } |
704 | |
705 | // LWG2756: conditionally explicit conversion from optional<_Up>&& |
706 | template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0> |
707 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) { |
708 | this->__construct_from(std::move(__v)); |
709 | } |
710 | template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0> |
711 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) { |
712 | this->__construct_from(std::move(__v)); |
713 | } |
714 | |
715 | # if _LIBCPP_STD_VER >= 23 |
716 | template <class _Tag, |
717 | class _Fp, |
718 | class... _Args, |
719 | enable_if_t<_IsSame<_Tag, __optional_construct_from_invoke_tag>::value, int> = 0> |
720 | _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Tag, _Fp&& __f, _Args&&... __args) |
721 | : __base(__optional_construct_from_invoke_tag{}, std::forward<_Fp>(__f), std::forward<_Args>(__args)...) {} |
722 | # endif |
723 | |
724 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(nullopt_t) noexcept { |
725 | reset(); |
726 | return *this; |
727 | } |
728 | |
729 | _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(const optional&) = default; |
730 | _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(optional&&) = default; |
731 | |
732 | // LWG2756 |
733 | template <class _Up = value_type, |
734 | enable_if_t<_And<_IsNotSame<__remove_cvref_t<_Up>, optional>, |
735 | _Or<_IsNotSame<__remove_cvref_t<_Up>, value_type>, _Not<is_scalar<value_type>>>, |
736 | is_constructible<value_type, _Up>, |
737 | is_assignable<value_type&, _Up>>::value, |
738 | int> = 0> |
739 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(_Up&& __v) { |
740 | if (this->has_value()) |
741 | this->__get() = std::forward<_Up>(__v); |
742 | else |
743 | this->__construct(std::forward<_Up>(__v)); |
744 | return *this; |
745 | } |
746 | |
747 | // LWG2756 |
748 | template <class _Up, enable_if_t<_CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>(), int> = 0> |
749 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(const optional<_Up>& __v) { |
750 | this->__assign_from(__v); |
751 | return *this; |
752 | } |
753 | |
754 | // LWG2756 |
755 | template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_assign<_Up>(), int> = 0> |
756 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(optional<_Up>&& __v) { |
757 | this->__assign_from(std::move(__v)); |
758 | return *this; |
759 | } |
760 | |
761 | template <class... _Args, enable_if_t<is_constructible_v<value_type, _Args...>, int> = 0> |
762 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(_Args&&... __args) { |
763 | reset(); |
764 | this->__construct(std::forward<_Args>(__args)...); |
765 | return this->__get(); |
766 | } |
767 | |
768 | template <class _Up, |
769 | class... _Args, |
770 | enable_if_t<is_constructible_v<value_type, initializer_list<_Up>&, _Args...>, int> = 0> |
771 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) { |
772 | reset(); |
773 | this->__construct(__il, std::forward<_Args>(__args)...); |
774 | return this->__get(); |
775 | } |
776 | |
777 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void |
778 | swap(optional& __opt) noexcept(is_nothrow_move_constructible_v<value_type> && is_nothrow_swappable_v<value_type>) { |
779 | if (this->has_value() == __opt.has_value()) { |
780 | using std::swap; |
781 | if (this->has_value()) |
782 | swap(this->__get(), __opt.__get()); |
783 | } else { |
784 | if (this->has_value()) { |
785 | __opt.__construct(std::move(this->__get())); |
786 | reset(); |
787 | } else { |
788 | this->__construct(std::move(__opt.__get())); |
789 | __opt.reset(); |
790 | } |
791 | } |
792 | } |
793 | |
794 | _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type const> operator->() const noexcept { |
795 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value" ); |
796 | return std::addressof(this->__get()); |
797 | } |
798 | |
799 | _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type> operator->() noexcept { |
800 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value" ); |
801 | return std::addressof(this->__get()); |
802 | } |
803 | |
804 | _LIBCPP_HIDE_FROM_ABI constexpr const value_type& operator*() const& noexcept { |
805 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value" ); |
806 | return this->__get(); |
807 | } |
808 | |
809 | _LIBCPP_HIDE_FROM_ABI constexpr value_type& operator*() & noexcept { |
810 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value" ); |
811 | return this->__get(); |
812 | } |
813 | |
814 | _LIBCPP_HIDE_FROM_ABI constexpr value_type&& operator*() && noexcept { |
815 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value" ); |
816 | return std::move(this->__get()); |
817 | } |
818 | |
819 | _LIBCPP_HIDE_FROM_ABI constexpr const value_type&& operator*() const&& noexcept { |
820 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value" ); |
821 | return std::move(this->__get()); |
822 | } |
823 | |
824 | _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return has_value(); } |
825 | |
826 | using __base::__get; |
827 | using __base::has_value; |
828 | |
829 | _LIBCPP_HIDE_FROM_ABI constexpr value_type const& value() const& { |
830 | if (!this->has_value()) |
831 | std::__throw_bad_optional_access(); |
832 | return this->__get(); |
833 | } |
834 | |
835 | _LIBCPP_HIDE_FROM_ABI constexpr value_type& value() & { |
836 | if (!this->has_value()) |
837 | std::__throw_bad_optional_access(); |
838 | return this->__get(); |
839 | } |
840 | |
841 | _LIBCPP_HIDE_FROM_ABI constexpr value_type&& value() && { |
842 | if (!this->has_value()) |
843 | std::__throw_bad_optional_access(); |
844 | return std::move(this->__get()); |
845 | } |
846 | |
847 | _LIBCPP_HIDE_FROM_ABI constexpr value_type const&& value() const&& { |
848 | if (!this->has_value()) |
849 | std::__throw_bad_optional_access(); |
850 | return std::move(this->__get()); |
851 | } |
852 | |
853 | template <class _Up> |
854 | _LIBCPP_HIDE_FROM_ABI constexpr value_type value_or(_Up&& __v) const& { |
855 | static_assert(is_copy_constructible_v<value_type>, "optional<T>::value_or: T must be copy constructible" ); |
856 | static_assert(is_convertible_v<_Up, value_type>, "optional<T>::value_or: U must be convertible to T" ); |
857 | return this->has_value() ? this->__get() : static_cast<value_type>(std::forward<_Up>(__v)); |
858 | } |
859 | |
860 | template <class _Up> |
861 | _LIBCPP_HIDE_FROM_ABI constexpr value_type value_or(_Up&& __v) && { |
862 | static_assert(is_move_constructible_v<value_type>, "optional<T>::value_or: T must be move constructible" ); |
863 | static_assert(is_convertible_v<_Up, value_type>, "optional<T>::value_or: U must be convertible to T" ); |
864 | return this->has_value() ? std::move(this->__get()) : static_cast<value_type>(std::forward<_Up>(__v)); |
865 | } |
866 | |
867 | # if _LIBCPP_STD_VER >= 23 |
868 | template <class _Func> |
869 | _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { |
870 | using _Up = invoke_result_t<_Func, value_type&>; |
871 | static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, |
872 | "Result of f(value()) must be a specialization of std::optional" ); |
873 | if (*this) |
874 | return std::invoke(std::forward<_Func>(__f), value()); |
875 | return remove_cvref_t<_Up>(); |
876 | } |
877 | |
878 | template <class _Func> |
879 | _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { |
880 | using _Up = invoke_result_t<_Func, const value_type&>; |
881 | static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, |
882 | "Result of f(value()) must be a specialization of std::optional" ); |
883 | if (*this) |
884 | return std::invoke(std::forward<_Func>(__f), value()); |
885 | return remove_cvref_t<_Up>(); |
886 | } |
887 | |
888 | template <class _Func> |
889 | _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { |
890 | using _Up = invoke_result_t<_Func, value_type&&>; |
891 | static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, |
892 | "Result of f(std::move(value())) must be a specialization of std::optional" ); |
893 | if (*this) |
894 | return std::invoke(std::forward<_Func>(__f), std::move(value())); |
895 | return remove_cvref_t<_Up>(); |
896 | } |
897 | |
898 | template <class _Func> |
899 | _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { |
900 | using _Up = invoke_result_t<_Func, const value_type&&>; |
901 | static_assert(__is_std_optional<remove_cvref_t<_Up>>::value, |
902 | "Result of f(std::move(value())) must be a specialization of std::optional" ); |
903 | if (*this) |
904 | return std::invoke(std::forward<_Func>(__f), std::move(value())); |
905 | return remove_cvref_t<_Up>(); |
906 | } |
907 | |
908 | template <class _Func> |
909 | _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { |
910 | using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>; |
911 | static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array" ); |
912 | static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t" ); |
913 | static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t" ); |
914 | static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type" ); |
915 | if (*this) |
916 | return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value()); |
917 | return optional<_Up>(); |
918 | } |
919 | |
920 | template <class _Func> |
921 | _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { |
922 | using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>; |
923 | static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array" ); |
924 | static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t" ); |
925 | static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t" ); |
926 | static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type" ); |
927 | if (*this) |
928 | return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value()); |
929 | return optional<_Up>(); |
930 | } |
931 | |
932 | template <class _Func> |
933 | _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { |
934 | using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>; |
935 | static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array" ); |
936 | static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t" ); |
937 | static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t" ); |
938 | static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type" ); |
939 | if (*this) |
940 | return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); |
941 | return optional<_Up>(); |
942 | } |
943 | |
944 | template <class _Func> |
945 | _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { |
946 | using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>; |
947 | static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array" ); |
948 | static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t" ); |
949 | static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t" ); |
950 | static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type" ); |
951 | if (*this) |
952 | return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); |
953 | return optional<_Up>(); |
954 | } |
955 | |
956 | template <invocable _Func> |
957 | _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const& |
958 | requires is_copy_constructible_v<value_type> |
959 | { |
960 | static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, |
961 | "Result of f() should be the same type as this optional" ); |
962 | if (*this) |
963 | return *this; |
964 | return std::forward<_Func>(__f)(); |
965 | } |
966 | |
967 | template <invocable _Func> |
968 | _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) && |
969 | requires is_move_constructible_v<value_type> |
970 | { |
971 | static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>, |
972 | "Result of f() should be the same type as this optional" ); |
973 | if (*this) |
974 | return std::move(*this); |
975 | return std::forward<_Func>(__f)(); |
976 | } |
977 | # endif // _LIBCPP_STD_VER >= 23 |
978 | |
979 | using __base::reset; |
980 | }; |
981 | |
982 | template <class _Tp> |
983 | optional(_Tp) -> optional<_Tp>; |
984 | |
985 | // Comparisons between optionals |
986 | template < |
987 | class _Tp, |
988 | class _Up, |
989 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>, int> = 0> |
990 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const optional<_Tp>& __x, const optional<_Up>& __y) { |
991 | if (static_cast<bool>(__x) != static_cast<bool>(__y)) |
992 | return false; |
993 | if (!static_cast<bool>(__x)) |
994 | return true; |
995 | return *__x == *__y; |
996 | } |
997 | |
998 | template < |
999 | class _Tp, |
1000 | class _Up, |
1001 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>, int> = 0> |
1002 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const optional<_Tp>& __x, const optional<_Up>& __y) { |
1003 | if (static_cast<bool>(__x) != static_cast<bool>(__y)) |
1004 | return true; |
1005 | if (!static_cast<bool>(__x)) |
1006 | return false; |
1007 | return *__x != *__y; |
1008 | } |
1009 | |
1010 | template < |
1011 | class _Tp, |
1012 | class _Up, |
1013 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>, int> = 0> |
1014 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const optional<_Tp>& __x, const optional<_Up>& __y) { |
1015 | if (!static_cast<bool>(__y)) |
1016 | return false; |
1017 | if (!static_cast<bool>(__x)) |
1018 | return true; |
1019 | return *__x < *__y; |
1020 | } |
1021 | |
1022 | template < |
1023 | class _Tp, |
1024 | class _Up, |
1025 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>, int> = 0> |
1026 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const optional<_Tp>& __x, const optional<_Up>& __y) { |
1027 | if (!static_cast<bool>(__x)) |
1028 | return false; |
1029 | if (!static_cast<bool>(__y)) |
1030 | return true; |
1031 | return *__x > *__y; |
1032 | } |
1033 | |
1034 | template < |
1035 | class _Tp, |
1036 | class _Up, |
1037 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>, int> = 0> |
1038 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const optional<_Tp>& __x, const optional<_Up>& __y) { |
1039 | if (!static_cast<bool>(__x)) |
1040 | return true; |
1041 | if (!static_cast<bool>(__y)) |
1042 | return false; |
1043 | return *__x <= *__y; |
1044 | } |
1045 | |
1046 | template < |
1047 | class _Tp, |
1048 | class _Up, |
1049 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>, int> = 0> |
1050 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const optional<_Tp>& __x, const optional<_Up>& __y) { |
1051 | if (!static_cast<bool>(__y)) |
1052 | return true; |
1053 | if (!static_cast<bool>(__x)) |
1054 | return false; |
1055 | return *__x >= *__y; |
1056 | } |
1057 | |
1058 | # if _LIBCPP_STD_VER >= 20 |
1059 | |
1060 | template <class _Tp, three_way_comparable_with<_Tp> _Up> |
1061 | _LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up> |
1062 | operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) { |
1063 | if (__x && __y) |
1064 | return *__x <=> *__y; |
1065 | return __x.has_value() <=> __y.has_value(); |
1066 | } |
1067 | |
1068 | # endif // _LIBCPP_STD_VER >= 20 |
1069 | |
1070 | // Comparisons with nullopt |
1071 | template <class _Tp> |
1072 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const optional<_Tp>& __x, nullopt_t) noexcept { |
1073 | return !static_cast<bool>(__x); |
1074 | } |
1075 | |
1076 | # if _LIBCPP_STD_VER <= 17 |
1077 | |
1078 | template <class _Tp> |
1079 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(nullopt_t, const optional<_Tp>& __x) noexcept { |
1080 | return !static_cast<bool>(__x); |
1081 | } |
1082 | |
1083 | template <class _Tp> |
1084 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const optional<_Tp>& __x, nullopt_t) noexcept { |
1085 | return static_cast<bool>(__x); |
1086 | } |
1087 | |
1088 | template <class _Tp> |
1089 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(nullopt_t, const optional<_Tp>& __x) noexcept { |
1090 | return static_cast<bool>(__x); |
1091 | } |
1092 | |
1093 | template <class _Tp> |
1094 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const optional<_Tp>&, nullopt_t) noexcept { |
1095 | return false; |
1096 | } |
1097 | |
1098 | template <class _Tp> |
1099 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator<(nullopt_t, const optional<_Tp>& __x) noexcept { |
1100 | return static_cast<bool>(__x); |
1101 | } |
1102 | |
1103 | template <class _Tp> |
1104 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const optional<_Tp>& __x, nullopt_t) noexcept { |
1105 | return !static_cast<bool>(__x); |
1106 | } |
1107 | |
1108 | template <class _Tp> |
1109 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(nullopt_t, const optional<_Tp>&) noexcept { |
1110 | return true; |
1111 | } |
1112 | |
1113 | template <class _Tp> |
1114 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const optional<_Tp>& __x, nullopt_t) noexcept { |
1115 | return static_cast<bool>(__x); |
1116 | } |
1117 | |
1118 | template <class _Tp> |
1119 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator>(nullopt_t, const optional<_Tp>&) noexcept { |
1120 | return false; |
1121 | } |
1122 | |
1123 | template <class _Tp> |
1124 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const optional<_Tp>&, nullopt_t) noexcept { |
1125 | return true; |
1126 | } |
1127 | |
1128 | template <class _Tp> |
1129 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(nullopt_t, const optional<_Tp>& __x) noexcept { |
1130 | return !static_cast<bool>(__x); |
1131 | } |
1132 | |
1133 | # else // _LIBCPP_STD_VER <= 17 |
1134 | |
1135 | template <class _Tp> |
1136 | _LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept { |
1137 | return __x.has_value() <=> false; |
1138 | } |
1139 | |
1140 | # endif // _LIBCPP_STD_VER <= 17 |
1141 | |
1142 | // Comparisons with T |
1143 | template < |
1144 | class _Tp, |
1145 | class _Up, |
1146 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>, int> = 0> |
1147 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const optional<_Tp>& __x, const _Up& __v) { |
1148 | return static_cast<bool>(__x) ? *__x == __v : false; |
1149 | } |
1150 | |
1151 | template < |
1152 | class _Tp, |
1153 | class _Up, |
1154 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>, int> = 0> |
1155 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const _Tp& __v, const optional<_Up>& __x) { |
1156 | return static_cast<bool>(__x) ? __v == *__x : false; |
1157 | } |
1158 | |
1159 | template < |
1160 | class _Tp, |
1161 | class _Up, |
1162 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>, int> = 0> |
1163 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const optional<_Tp>& __x, const _Up& __v) { |
1164 | return static_cast<bool>(__x) ? *__x != __v : true; |
1165 | } |
1166 | |
1167 | template < |
1168 | class _Tp, |
1169 | class _Up, |
1170 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>, int> = 0> |
1171 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const _Tp& __v, const optional<_Up>& __x) { |
1172 | return static_cast<bool>(__x) ? __v != *__x : true; |
1173 | } |
1174 | |
1175 | template < |
1176 | class _Tp, |
1177 | class _Up, |
1178 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>, int> = 0> |
1179 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const optional<_Tp>& __x, const _Up& __v) { |
1180 | return static_cast<bool>(__x) ? *__x < __v : true; |
1181 | } |
1182 | |
1183 | template < |
1184 | class _Tp, |
1185 | class _Up, |
1186 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>, int> = 0> |
1187 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const _Tp& __v, const optional<_Up>& __x) { |
1188 | return static_cast<bool>(__x) ? __v < *__x : false; |
1189 | } |
1190 | |
1191 | template < |
1192 | class _Tp, |
1193 | class _Up, |
1194 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>, int> = 0> |
1195 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const optional<_Tp>& __x, const _Up& __v) { |
1196 | return static_cast<bool>(__x) ? *__x <= __v : true; |
1197 | } |
1198 | |
1199 | template < |
1200 | class _Tp, |
1201 | class _Up, |
1202 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>, int> = 0> |
1203 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const _Tp& __v, const optional<_Up>& __x) { |
1204 | return static_cast<bool>(__x) ? __v <= *__x : false; |
1205 | } |
1206 | |
1207 | template < |
1208 | class _Tp, |
1209 | class _Up, |
1210 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>, int> = 0> |
1211 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const optional<_Tp>& __x, const _Up& __v) { |
1212 | return static_cast<bool>(__x) ? *__x > __v : false; |
1213 | } |
1214 | |
1215 | template < |
1216 | class _Tp, |
1217 | class _Up, |
1218 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>, int> = 0> |
1219 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const _Tp& __v, const optional<_Up>& __x) { |
1220 | return static_cast<bool>(__x) ? __v > *__x : true; |
1221 | } |
1222 | |
1223 | template < |
1224 | class _Tp, |
1225 | class _Up, |
1226 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>, int> = 0> |
1227 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const optional<_Tp>& __x, const _Up& __v) { |
1228 | return static_cast<bool>(__x) ? *__x >= __v : false; |
1229 | } |
1230 | |
1231 | template < |
1232 | class _Tp, |
1233 | class _Up, |
1234 | enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>, int> = 0> |
1235 | _LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const _Tp& __v, const optional<_Up>& __x) { |
1236 | return static_cast<bool>(__x) ? __v >= *__x : true; |
1237 | } |
1238 | |
1239 | # if _LIBCPP_STD_VER >= 20 |
1240 | |
1241 | template <class _Tp, class _Up> |
1242 | requires(!__is_derived_from_optional<_Up>) && three_way_comparable_with<_Tp, _Up> |
1243 | _LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up> |
1244 | operator<=>(const optional<_Tp>& __x, const _Up& __v) { |
1245 | return __x.has_value() ? *__x <=> __v : strong_ordering::less; |
1246 | } |
1247 | |
1248 | # endif // _LIBCPP_STD_VER >= 20 |
1249 | |
1250 | template <class _Tp, enable_if_t< is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, int> = 0> |
1251 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void |
1252 | swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) { |
1253 | __x.swap(__y); |
1254 | } |
1255 | |
1256 | template <class _Tp> |
1257 | _LIBCPP_HIDE_FROM_ABI constexpr optional<decay_t<_Tp>> make_optional(_Tp&& __v) { |
1258 | return optional<decay_t<_Tp>>(std::forward<_Tp>(__v)); |
1259 | } |
1260 | |
1261 | template <class _Tp, class... _Args> |
1262 | _LIBCPP_HIDE_FROM_ABI constexpr optional<_Tp> make_optional(_Args&&... __args) { |
1263 | return optional<_Tp>(in_place, std::forward<_Args>(__args)...); |
1264 | } |
1265 | |
1266 | template <class _Tp, class _Up, class... _Args> |
1267 | _LIBCPP_HIDE_FROM_ABI constexpr optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) { |
1268 | return optional<_Tp>(in_place, __il, std::forward<_Args>(__args)...); |
1269 | } |
1270 | |
1271 | template <class _Tp> |
1272 | struct hash< __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>> > { |
1273 | # if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) |
1274 | _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type; |
1275 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; |
1276 | # endif |
1277 | |
1278 | _LIBCPP_HIDE_FROM_ABI size_t operator()(const optional<_Tp>& __opt) const { |
1279 | return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0; |
1280 | } |
1281 | }; |
1282 | |
1283 | _LIBCPP_END_NAMESPACE_STD |
1284 | |
1285 | # endif // _LIBCPP_STD_VER >= 17 |
1286 | |
1287 | _LIBCPP_POP_MACROS |
1288 | |
1289 | # if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 |
1290 | # include <atomic> |
1291 | # include <climits> |
1292 | # include <concepts> |
1293 | # include <ctime> |
1294 | # include <iterator> |
1295 | # include <limits> |
1296 | # include <memory> |
1297 | # include <ratio> |
1298 | # include <stdexcept> |
1299 | # include <tuple> |
1300 | # include <type_traits> |
1301 | # include <typeinfo> |
1302 | # include <utility> |
1303 | # include <variant> |
1304 | # endif |
1305 | #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) |
1306 | |
1307 | #endif // _LIBCPP_OPTIONAL |
1308 | |