1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef _LIBCPP___OPTIONAL_OPTIONAL_H
10#define _LIBCPP___OPTIONAL_OPTIONAL_H
11
12#include <__assert>
13#include <__concepts/invocable.h>
14#include <__config>
15#include <__functional/invoke.h>
16#include <__fwd/optional.h>
17#include <__iterator/bounded_iter.h>
18#include <__iterator/capacity_aware_iterator.h>
19#include <__memory/addressof.h>
20#include <__memory/construct_at.h>
21#include <__optional/common.h>
22#include <__optional/comparison.h>
23#include <__optional/hash.h>
24#include <__optional/nullopt_t.h>
25#include <__optional/swap.h>
26#include <__tuple/sfinae_helpers.h>
27#include <__type_traits/add_pointer.h>
28#include <__type_traits/conditional.h>
29#include <__type_traits/conjunction.h>
30#include <__type_traits/decay.h>
31#include <__type_traits/disjunction.h>
32#include <__type_traits/enable_if.h>
33#include <__type_traits/invoke.h>
34#include <__type_traits/is_array.h>
35#include <__type_traits/is_assignable.h>
36#include <__type_traits/is_constructible.h>
37#include <__type_traits/is_convertible.h>
38#include <__type_traits/is_destructible.h>
39#include <__type_traits/is_nothrow_assignable.h>
40#include <__type_traits/is_nothrow_constructible.h>
41#include <__type_traits/is_object.h>
42#include <__type_traits/is_reference.h>
43#include <__type_traits/is_relocatable.h>
44#include <__type_traits/is_same.h>
45#include <__type_traits/is_scalar.h>
46#include <__type_traits/is_swappable.h>
47#include <__type_traits/is_trivially_assignable.h>
48#include <__type_traits/is_trivially_constructible.h>
49#include <__type_traits/is_trivially_destructible.h>
50#include <__type_traits/negation.h>
51#include <__type_traits/remove_cv.h>
52#include <__type_traits/remove_cvref.h>
53#include <__type_traits/remove_reference.h>
54#include <__utility/forward.h>
55#include <__utility/in_place.h>
56#include <__utility/move.h>
57#include <initializer_list>
58
59#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
60# pragma GCC system_header
61#endif
62
63_LIBCPP_PUSH_MACROS
64#include <__undef_macros>
65
66#if _LIBCPP_STD_VER >= 17
67
68_LIBCPP_BEGIN_NAMESPACE_STD
69
70template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
71struct __optional_destruct_base;
72
73template <class _Tp>
74struct __optional_destruct_base<_Tp, false> {
75 typedef _Tp value_type;
76# if _LIBCPP_STD_VER >= 26
77 static_assert(!is_rvalue_reference_v<_Tp>, "instantiation of optional with an rvalue reference type is ill-formed");
78# else
79 static_assert(!is_reference_v<_Tp>, "instantiation of optional with a reference type is ill-formed");
80# endif
81 static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior");
82 union {
83 char __null_state_;
84 remove_cv_t<value_type> __val_;
85 };
86 bool __engaged_;
87
88 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__optional_destruct_base() {
89 if (__engaged_)
90 __val_.~value_type();
91 }
92
93 _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {}
94
95 template <class... _Args>
96 _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
97 : __val_(std::forward<_Args>(__args)...), __engaged_(true) {}
98
99# if _LIBCPP_STD_VER >= 23
100 template <class _Fp, class... _Args>
101 _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(
102 __optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
103 : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {}
104# endif
105
106 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept {
107 if (__engaged_) {
108 __val_.~value_type();
109 __engaged_ = false;
110 }
111 }
112};
113
114template <class _Tp>
115struct __optional_destruct_base<_Tp, true> {
116 typedef _Tp value_type;
117# if _LIBCPP_STD_VER >= 26
118 static_assert(!is_rvalue_reference_v<_Tp>, "instantiation of optional with an rvalue reference type is ill-formed");
119# else
120 static_assert(!is_reference_v<_Tp>, "instantiation of optional with a reference type is ill-formed");
121# endif
122 static_assert(is_object_v<value_type>, "instantiation of optional with a non-object type is undefined behavior");
123 union {
124 char __null_state_;
125 remove_cv_t<value_type> __val_;
126 };
127 bool __engaged_;
128
129 _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base() noexcept : __null_state_(), __engaged_(false) {}
130
131 template <class... _Args>
132 _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
133 : __val_(std::forward<_Args>(__args)...), __engaged_(true) {}
134
135# if _LIBCPP_STD_VER >= 23
136 template <class _Fp, class... _Args>
137 _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base(
138 __optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
139 : __val_(std::invoke(std::forward<_Fp>(__f), std::forward<_Args>(__args)...)), __engaged_(true) {}
140# endif
141
142 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept {
143 if (__engaged_) {
144 __engaged_ = false;
145 }
146 }
147};
148
149template <class _Tp>
150struct __optional_storage_base : __optional_destruct_base<_Tp> {
151 using __base _LIBCPP_NODEBUG = __optional_destruct_base<_Tp>;
152 using value_type = _Tp;
153 using __base::__base;
154
155 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__engaged_; }
156
157 _LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() & noexcept { return this->__val_; }
158 _LIBCPP_HIDE_FROM_ABI constexpr const value_type& __get() const& noexcept { return this->__val_; }
159 _LIBCPP_HIDE_FROM_ABI constexpr value_type&& __get() && noexcept { return std::move(this->__val_); }
160 _LIBCPP_HIDE_FROM_ABI constexpr const value_type&& __get() const&& noexcept { return std::move(this->__val_); }
161
162 template <class... _Args>
163 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_Args&&... __args) {
164 _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage");
165 std::__construct_at(std::addressof(this->__val_), std::forward<_Args>(__args)...);
166 this->__engaged_ = true;
167 }
168
169 template <class _That>
170 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) {
171 if (__opt.has_value())
172 __construct(std::forward<_That>(__opt).__get());
173 }
174
175 template <class _That>
176 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) {
177 if (this->__engaged_ == __opt.has_value()) {
178 if (this->__engaged_)
179 static_cast<_Tp&>(this->__val_) = std::forward<_That>(__opt).__get();
180 } else {
181 if (this->__engaged_)
182 this->reset();
183 else
184 __construct(std::forward<_That>(__opt).__get());
185 }
186 }
187};
188
189template <class _Tp, bool = is_trivially_copy_constructible_v<_Tp>>
190struct __optional_copy_base : __optional_storage_base<_Tp> {
191 using __optional_storage_base<_Tp>::__optional_storage_base;
192};
193
194template <class _Tp>
195struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> {
196 using __optional_storage_base<_Tp>::__optional_storage_base;
197
198 _LIBCPP_HIDE_FROM_ABI __optional_copy_base() = default;
199
200 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_base(const __optional_copy_base& __opt) {
201 this->__construct_from(__opt);
202 }
203
204 _LIBCPP_HIDE_FROM_ABI __optional_copy_base(__optional_copy_base&&) = default;
205 _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(const __optional_copy_base&) = default;
206 _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(__optional_copy_base&&) = default;
207};
208
209template <class _Tp, bool = is_trivially_move_constructible_v<_Tp>>
210struct __optional_move_base : __optional_copy_base<_Tp> {
211 using __optional_copy_base<_Tp>::__optional_copy_base;
212};
213
214template <class _Tp>
215struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> {
216 using value_type = _Tp;
217 using __optional_copy_base<_Tp>::__optional_copy_base;
218
219 _LIBCPP_HIDE_FROM_ABI __optional_move_base() = default;
220 _LIBCPP_HIDE_FROM_ABI __optional_move_base(const __optional_move_base&) = default;
221
222 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
223 __optional_move_base(__optional_move_base&& __opt) noexcept(is_nothrow_move_constructible_v<value_type>) {
224 this->__construct_from(std::move(__opt));
225 }
226
227 _LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(const __optional_move_base&) = default;
228 _LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(__optional_move_base&&) = default;
229};
230
231template <class _Tp,
232 bool = (is_trivially_destructible_v<_Tp> && is_trivially_copy_constructible_v<_Tp> &&
233 is_trivially_copy_assignable_v<_Tp>)>
234struct __optional_copy_assign_base : __optional_move_base<_Tp> {
235 using __optional_move_base<_Tp>::__optional_move_base;
236};
237
238template <class _Tp>
239struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> {
240 using __optional_move_base<_Tp>::__optional_move_base;
241
242 _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base() = default;
243 _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
244 _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
245
246 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_assign_base&
247 operator=(const __optional_copy_assign_base& __opt) {
248 this->__assign_from(__opt);
249 return *this;
250 }
251
252 _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
253};
254
255template <class _Tp,
256 bool = (is_trivially_destructible_v<_Tp> && is_trivially_move_constructible_v<_Tp> &&
257 is_trivially_move_assignable_v<_Tp>)>
258struct __optional_move_assign_base : __optional_copy_assign_base<_Tp> {
259 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
260};
261
262template <class _Tp>
263struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> {
264 using value_type = _Tp;
265 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
266
267 _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base() = default;
268 _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
269 _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(__optional_move_assign_base&&) = default;
270 _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
271
272 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_assign_base&
273 operator=(__optional_move_assign_base&& __opt) noexcept(
274 is_nothrow_move_assignable_v<value_type> && is_nothrow_move_constructible_v<value_type>) {
275 this->__assign_from(std::move(__opt));
276 return *this;
277 }
278};
279
280template <class _Tp>
281using __optional_sfinae_ctor_base_t _LIBCPP_NODEBUG =
282 __sfinae_ctor_base< is_copy_constructible<_Tp>::value, is_move_constructible<_Tp>::value >;
283
284template <class _Tp>
285using __optional_sfinae_assign_base_t _LIBCPP_NODEBUG =
286 __sfinae_assign_base< (is_copy_constructible_v<_Tp> && is_copy_assignable_v<_Tp>),
287 (is_move_constructible_v<_Tp> && is_move_assignable_v<_Tp>)>;
288
289template <class _Tp>
290class _LIBCPP_DECLSPEC_EMPTY_BASES optional
291 : public __optional_move_assign_base<_Tp>,
292 private __optional_sfinae_ctor_base_t<_Tp>,
293 private __optional_sfinae_assign_base_t<_Tp> {
294 using __base _LIBCPP_NODEBUG = __optional_move_assign_base<_Tp>;
295
296public:
297 using value_type = __libcpp_remove_reference_t<_Tp>;
298
299 using __trivially_relocatable _LIBCPP_NODEBUG = conditional_t<__is_trivially_relocatable_v<_Tp>, optional, void>;
300
301private:
302 static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>, "instantiation of optional with in_place_t is ill-formed");
303 static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>, "instantiation of optional with nullopt_t is ill-formed");
304 static_assert(is_destructible_v<_Tp>, "instantiation of optional with a non-destructible type is ill-formed");
305 static_assert(!is_array_v<_Tp>, "instantiation of optional with an array type is ill-formed");
306
307 // LWG2756: conditionally explicit conversion from _Up
308 struct _CheckOptionalArgsConstructor {
309 template <class _Up>
310 _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
311 return is_constructible_v<_Tp, _Up&&> && is_convertible_v<_Up&&, _Tp>;
312 }
313
314 template <class _Up>
315 _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
316 return is_constructible_v<_Tp, _Up&&> && !is_convertible_v<_Up&&, _Tp>;
317 }
318 };
319 template <class _Up>
320 using _CheckOptionalArgsCtor _LIBCPP_NODEBUG =
321 _If< _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value && _IsNotSame<__remove_cvref_t<_Up>, optional>::value &&
322 (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_optional_v<__remove_cvref_t<_Up>>),
323 _CheckOptionalArgsConstructor,
324 __check_tuple_constructor_fail >;
325 template <class _QualUp>
326 struct _CheckOptionalLikeConstructor {
327 template <class _Up, class _Opt = optional<_Up>>
328 using __check_constructible_from_opt _LIBCPP_NODEBUG =
329 _Or< is_constructible<_Tp, _Opt&>,
330 is_constructible<_Tp, _Opt const&>,
331 is_constructible<_Tp, _Opt&&>,
332 is_constructible<_Tp, _Opt const&&>,
333 is_convertible<_Opt&, _Tp>,
334 is_convertible<_Opt const&, _Tp>,
335 is_convertible<_Opt&&, _Tp>,
336 is_convertible<_Opt const&&, _Tp> >;
337 template <class _Up, class _Opt = optional<_Up>>
338 using __check_assignable_from_opt _LIBCPP_NODEBUG =
339 _Or< is_assignable<_Tp&, _Opt&>,
340 is_assignable<_Tp&, _Opt const&>,
341 is_assignable<_Tp&, _Opt&&>,
342 is_assignable<_Tp&, _Opt const&&> >;
343 template <class _Up, class _QUp = _QualUp>
344 _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
345 return is_convertible<_QUp, _Tp>::value &&
346 (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value);
347 }
348 template <class _Up, class _QUp = _QualUp>
349 _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
350 return !is_convertible<_QUp, _Tp>::value &&
351 (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value);
352 }
353 template <class _Up, class _QUp = _QualUp>
354 _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_assign() {
355 // Construction and assignability of _QUp to _Tp has already been
356 // checked.
357 return !__check_constructible_from_opt<_Up>::value && !__check_assignable_from_opt<_Up>::value;
358 }
359 };
360
361 template <class _Up, class _QualUp>
362 using _CheckOptionalLikeCtor _LIBCPP_NODEBUG =
363 _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp> >::value,
364 _CheckOptionalLikeConstructor<_QualUp>,
365 __check_tuple_constructor_fail >;
366 template <class _Up, class _QualUp>
367 using _CheckOptionalLikeAssign _LIBCPP_NODEBUG =
368 _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp>, is_assignable<_Tp&, _QualUp> >::value,
369 _CheckOptionalLikeConstructor<_QualUp>,
370 __check_tuple_constructor_fail >;
371
372public:
373 _LIBCPP_HIDE_FROM_ABI constexpr optional() noexcept {}
374 _LIBCPP_HIDE_FROM_ABI constexpr optional(const optional&) = default;
375 _LIBCPP_HIDE_FROM_ABI constexpr optional(optional&&) = default;
376 _LIBCPP_HIDE_FROM_ABI constexpr optional(nullopt_t) noexcept {}
377
378 template <class _InPlaceT,
379 class... _Args,
380 enable_if_t<_And<_IsSame<_InPlaceT, in_place_t>, is_constructible<_Tp, _Args...>>::value, int> = 0>
381 _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_InPlaceT, _Args&&... __args)
382 : __base(in_place, std::forward<_Args>(__args)...) {}
383
384 template <class _Up, class... _Args, enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>, int> = 0>
385 _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
386 : __base(in_place, __il, std::forward<_Args>(__args)...) {}
387
388 template <class _Up = _Tp, enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
389 _LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v) noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened
390 : __base(in_place, std::forward<_Up>(__v)) {}
391
392 template <class _Up = remove_cv_t<_Tp>,
393 enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0>
394 _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v) noexcept(
395 is_nothrow_constructible_v<_Tp, _Up>) // strengthened
396 : __base(in_place, std::forward<_Up>(__v)) {}
397
398 // LWG2756: conditionally explicit conversion from const optional<_Up>&
399 template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0>
400 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) {
401 this->__construct_from(__v);
402 }
403
404 template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0>
405 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) {
406 this->__construct_from(__v);
407 }
408
409 // LWG2756: conditionally explicit conversion from optional<_Up>&&
410 template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0>
411 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) {
412 this->__construct_from(std::move(__v));
413 }
414
415 template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0>
416 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) {
417 this->__construct_from(std::move(__v));
418 }
419
420# if _LIBCPP_STD_VER >= 23
421 template <class _Tag,
422 class _Fp,
423 class... _Args,
424 enable_if_t<_IsSame<_Tag, __optional_construct_from_invoke_tag>::value, int> = 0>
425 _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Tag, _Fp&& __f, _Args&&... __args)
426 : __base(__optional_construct_from_invoke_tag{}, std::forward<_Fp>(__f), std::forward<_Args>(__args)...) {}
427# endif
428
429 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(nullopt_t) noexcept {
430 reset();
431 return *this;
432 }
433
434 _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(const optional&) = default;
435 _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(optional&&) = default;
436
437 // LWG2756
438 template <class _Up = remove_cv_t<_Tp>,
439 enable_if_t<_And<_IsNotSame<__remove_cvref_t<_Up>, optional>,
440 _Or<_IsNotSame<__remove_cvref_t<_Up>, _Tp>, _Not<is_scalar<_Tp>>>,
441 is_constructible<_Tp, _Up>,
442 is_assignable<_Tp&, _Up>>::value,
443 int> = 0>
444 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(_Up&& __v) {
445 if (this->has_value())
446 this->__get() = std::forward<_Up>(__v);
447 else
448 this->__construct(std::forward<_Up>(__v));
449 return *this;
450 }
451
452 // LWG2756
453 template <class _Up, enable_if_t<_CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>(), int> = 0>
454 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(const optional<_Up>& __v) {
455 this->__assign_from(__v);
456 return *this;
457 }
458
459 // LWG2756
460 template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_assign<_Up>(), int> = 0>
461 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(optional<_Up>&& __v) {
462 this->__assign_from(std::move(__v));
463 return *this;
464 }
465
466 template <class... _Args, enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0>
467 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(_Args&&... __args) {
468 reset();
469 this->__construct(std::forward<_Args>(__args)...);
470 return this->__get();
471 }
472
473 template <class _Up, class... _Args, enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>, int> = 0>
474 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) {
475 reset();
476 this->__construct(__il, std::forward<_Args>(__args)...);
477 return this->__get();
478 }
479
480 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
481 swap(optional& __opt) noexcept((is_nothrow_move_constructible_v<_Tp> && is_nothrow_swappable_v<_Tp>)) {
482 using std::swap;
483 if (this->has_value() == __opt.has_value()) {
484 if (this->has_value())
485 swap(this->__get(), __opt.__get());
486 } else {
487 if (this->has_value()) {
488 __opt.__construct(std::move(this->__get()));
489 this->reset();
490 } else {
491 this->__construct(std::move(__opt.__get()));
492 __opt.reset();
493 }
494 }
495 }
496
497 // [optional.observe]
498 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept {
499 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
500 return this->__get();
501 }
502
503 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept {
504 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
505 return this->__get();
506 }
507
508 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept {
509 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
510 return std::move(this->__get());
511 }
512
513 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept {
514 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
515 return std::move(this->__get());
516 }
517 _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<_Tp const> operator->() const noexcept {
518 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
519 return std::addressof(this->__get());
520 }
521
522 _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<_Tp> operator->() noexcept {
523 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
524 return std::addressof(this->__get());
525 }
526
527 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& value() const& {
528 if (!this->has_value())
529 std::__throw_bad_optional_access();
530 return this->__get();
531 }
532
533 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & {
534 if (!this->has_value())
535 std::__throw_bad_optional_access();
536 return this->__get();
537 }
538
539 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && {
540 if (!this->has_value())
541 std::__throw_bad_optional_access();
542 return std::move(this->__get());
543 }
544
545 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp const&& value() const&& {
546 if (!this->has_value())
547 std::__throw_bad_optional_access();
548 return std::move(this->__get());
549 }
550
551 _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return has_value(); }
552
553 using __base::__get;
554 using __base::has_value;
555
556 template <class _Up = remove_cv_t<_Tp>>
557 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& {
558 static_assert(is_copy_constructible_v<_Tp>, "optional<T>::value_or: T must be copy constructible");
559 static_assert(is_convertible_v<_Up, _Tp>, "optional<T>::value_or: U must be convertible to T");
560 return this->has_value() ? this->__get() : static_cast<_Tp>(std::forward<_Up>(__v));
561 }
562
563 template <class _Up = remove_cv_t<_Tp>>
564 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && {
565 static_assert(is_move_constructible_v<_Tp>, "optional<T>::value_or: T must be move constructible");
566 static_assert(is_convertible_v<_Up, _Tp>, "optional<T>::value_or: U must be convertible to T");
567 return this->has_value() ? std::move(this->__get()) : static_cast<_Tp>(std::forward<_Up>(__v));
568 }
569
570# if _LIBCPP_STD_VER >= 23
571 template <class _Func>
572 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & {
573 using _Up = invoke_result_t<_Func, _Tp&>;
574 static_assert(
575 __is_std_optional_v<remove_cvref_t<_Up>>, "Result of f(value()) must be a specialization of std::optional");
576 if (*this)
577 return std::invoke(std::forward<_Func>(__f), value());
578 return remove_cvref_t<_Up>();
579 }
580
581 template <class _Func>
582 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& {
583 using _Up = invoke_result_t<_Func, const _Tp&>;
584 static_assert(
585 __is_std_optional_v<remove_cvref_t<_Up>>, "Result of f(value()) must be a specialization of std::optional");
586 if (*this)
587 return std::invoke(std::forward<_Func>(__f), value());
588 return remove_cvref_t<_Up>();
589 }
590
591 template <class _Func>
592 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && {
593 using _Up = invoke_result_t<_Func, _Tp&&>;
594 static_assert(__is_std_optional_v<remove_cvref_t<_Up>>,
595 "Result of f(std::move(value())) must be a specialization of std::optional");
596 if (*this)
597 return std::invoke(std::forward<_Func>(__f), std::move(value()));
598 return remove_cvref_t<_Up>();
599 }
600
601 template <class _Func>
602 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& {
603 using _Up = invoke_result_t<_Func, const _Tp&&>;
604 static_assert(__is_std_optional_v<remove_cvref_t<_Up>>,
605 "Result of f(std::move(value())) must be a specialization of std::optional");
606 if (*this)
607 return std::invoke(std::forward<_Func>(__f), std::move(value()));
608 return remove_cvref_t<_Up>();
609 }
610
611 template <class _Func>
612 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & {
613 using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&>>;
614 static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
615 static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
616 static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
617 static_assert(
618 __is_valid_optional_contained_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
619 if (*this)
620 return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
621 return optional<_Up>();
622 }
623
624 template <class _Func>
625 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& {
626 using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&>>;
627 static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
628 static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
629 static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
630 static_assert(
631 __is_valid_optional_contained_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
632 if (*this)
633 return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
634 return optional<_Up>();
635 }
636
637 template <class _Func>
638 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && {
639 using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&&>>;
640 static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
641 static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
642 static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
643 static_assert(
644 __is_valid_optional_contained_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
645 if (*this)
646 return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value()));
647 return optional<_Up>();
648 }
649
650 template <class _Func>
651 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& {
652 using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&&>>;
653 static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
654 static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
655 static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
656 static_assert(
657 __is_valid_optional_contained_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
658 if (*this)
659 return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value()));
660 return optional<_Up>();
661 }
662
663 template <invocable _Func>
664 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const&
665 requires is_copy_constructible_v<_Tp>
666 {
667 static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
668 "Result of f() should be the same type as this optional");
669 if (*this)
670 return *this;
671 return std::forward<_Func>(__f)();
672 }
673
674 template <invocable _Func>
675 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) &&
676 requires is_move_constructible_v<_Tp>
677 {
678 static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
679 "Result of f() should be the same type as this optional");
680 if (*this)
681 return std::move(*this);
682 return std::forward<_Func>(__f)();
683 }
684# endif // _LIBCPP_STD_VER >= 23
685
686 using __base::reset;
687
688# if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
689
690private:
691 using __pointer _LIBCPP_NODEBUG = add_pointer_t<_Tp>;
692 using __const_pointer _LIBCPP_NODEBUG = add_pointer_t<const _Tp>;
693
694public:
695# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
696 using iterator = __bounded_iter<__pointer>;
697 using const_iterator = __bounded_iter<__const_pointer>;
698# else
699 using iterator = __capacity_aware_iterator<__pointer, optional<_Tp>, 1>;
700 using const_iterator = __capacity_aware_iterator<__const_pointer, optional<_Tp>, 1>;
701# endif
702
703 // [optional.iterators], iterator support
704 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator begin() noexcept {
705 auto* __ptr = std::addressof(this->__get());
706
707# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
708 return std::__make_bounded_iter(__ptr, __ptr, __ptr + (this->has_value() ? 1 : 0));
709# else
710 return std::__make_capacity_aware_iterator<__pointer, optional<_Tp>, 1>(__ptr);
711# endif
712 }
713
714 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const_iterator begin() const noexcept {
715 auto* __ptr = std::addressof(this->__get());
716
717# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
718 return std::__make_bounded_iter(__ptr, __ptr, __ptr + (this->has_value() ? 1 : 0));
719# else
720 return std::__make_capacity_aware_iterator<__const_pointer, optional<_Tp>, 1>(__ptr);
721# endif
722 }
723
724 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator end() noexcept {
725 return begin() + (this->has_value() ? 1 : 0);
726 }
727 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const_iterator end() const noexcept {
728 return begin() + (this->has_value() ? 1 : 0);
729 }
730
731# endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
732};
733
734_LIBCPP_END_NAMESPACE_STD
735
736#endif // _LIBCPP_STD_VER >= 17
737
738_LIBCPP_POP_MACROS
739
740#endif // _LIBCPP___OPTIONAL_OPTIONAL_H
741