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 // [optional.observe]
158 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& value() const& {
159 if (!this->has_value())
160 std::__throw_bad_optional_access();
161 return this->__val_;
162 }
163
164 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & {
165 if (!this->has_value())
166 std::__throw_bad_optional_access();
167 return this->__val_;
168 }
169
170 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && {
171 if (!this->has_value())
172 std::__throw_bad_optional_access();
173 return std::move(this->__val_);
174 }
175
176 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp const&& value() const&& {
177 if (!this->has_value())
178 std::__throw_bad_optional_access();
179 return std::move(this->__val_);
180 }
181
182 template <class... _Args>
183 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_Args&&... __args) {
184 _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage");
185 std::__construct_at(std::addressof(this->__val_), std::forward<_Args>(__args)...);
186 this->__engaged_ = true;
187 }
188
189 template <class _That>
190 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_from(_That&& __opt) {
191 if (__opt.has_value())
192 __construct(std::forward<_That>(__opt).value());
193 }
194
195 template <class _That>
196 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from(_That&& __opt) {
197 if (this->__engaged_ == __opt.has_value()) {
198 if (this->__engaged_)
199 static_cast<_Tp&>(this->__val_) = std::forward<_That>(__opt).value();
200 } else {
201 if (this->__engaged_)
202 this->reset();
203 else
204 __construct(std::forward<_That>(__opt).value());
205 }
206 }
207};
208
209template <class _Tp, bool = is_trivially_copy_constructible_v<_Tp>>
210struct __optional_copy_base : __optional_storage_base<_Tp> {
211 using __optional_storage_base<_Tp>::__optional_storage_base;
212};
213
214template <class _Tp>
215struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp> {
216 using __optional_storage_base<_Tp>::__optional_storage_base;
217
218 _LIBCPP_HIDE_FROM_ABI __optional_copy_base() = default;
219
220 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_base(const __optional_copy_base& __opt) {
221 this->__construct_from(__opt);
222 }
223
224 _LIBCPP_HIDE_FROM_ABI __optional_copy_base(__optional_copy_base&&) = default;
225 _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(const __optional_copy_base&) = default;
226 _LIBCPP_HIDE_FROM_ABI __optional_copy_base& operator=(__optional_copy_base&&) = default;
227};
228
229template <class _Tp, bool = is_trivially_move_constructible_v<_Tp>>
230struct __optional_move_base : __optional_copy_base<_Tp> {
231 using __optional_copy_base<_Tp>::__optional_copy_base;
232};
233
234template <class _Tp>
235struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp> {
236 using value_type = _Tp;
237 using __optional_copy_base<_Tp>::__optional_copy_base;
238
239 _LIBCPP_HIDE_FROM_ABI __optional_move_base() = default;
240 _LIBCPP_HIDE_FROM_ABI __optional_move_base(const __optional_move_base&) = default;
241
242 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
243 __optional_move_base(__optional_move_base&& __opt) noexcept(is_nothrow_move_constructible_v<value_type>) {
244 this->__construct_from(std::move(__opt));
245 }
246
247 _LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(const __optional_move_base&) = default;
248 _LIBCPP_HIDE_FROM_ABI __optional_move_base& operator=(__optional_move_base&&) = default;
249};
250
251template <class _Tp,
252 bool = (is_trivially_destructible_v<_Tp> && is_trivially_copy_constructible_v<_Tp> &&
253 is_trivially_copy_assignable_v<_Tp>)>
254struct __optional_copy_assign_base : __optional_move_base<_Tp> {
255 using __optional_move_base<_Tp>::__optional_move_base;
256};
257
258template <class _Tp>
259struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp> {
260 using __optional_move_base<_Tp>::__optional_move_base;
261
262 _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base() = default;
263 _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
264 _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
265
266 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_copy_assign_base&
267 operator=(const __optional_copy_assign_base& __opt) {
268 this->__assign_from(__opt);
269 return *this;
270 }
271
272 _LIBCPP_HIDE_FROM_ABI __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
273};
274
275template <class _Tp,
276 bool = (is_trivially_destructible_v<_Tp> && is_trivially_move_constructible_v<_Tp> &&
277 is_trivially_move_assignable_v<_Tp>)>
278struct __optional_move_assign_base : __optional_copy_assign_base<_Tp> {
279 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
280};
281
282template <class _Tp>
283struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp> {
284 using value_type = _Tp;
285 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
286
287 _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base() = default;
288 _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
289 _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base(__optional_move_assign_base&&) = default;
290 _LIBCPP_HIDE_FROM_ABI __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
291
292 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __optional_move_assign_base&
293 operator=(__optional_move_assign_base&& __opt) noexcept(
294 is_nothrow_move_assignable_v<value_type> && is_nothrow_move_constructible_v<value_type>) {
295 this->__assign_from(std::move(__opt));
296 return *this;
297 }
298};
299
300template <class _Tp>
301using __optional_sfinae_ctor_base_t _LIBCPP_NODEBUG =
302 __sfinae_ctor_base< is_copy_constructible<_Tp>::value, is_move_constructible<_Tp>::value >;
303
304template <class _Tp>
305using __optional_sfinae_assign_base_t _LIBCPP_NODEBUG =
306 __sfinae_assign_base< (is_copy_constructible_v<_Tp> && is_copy_assignable_v<_Tp>),
307 (is_move_constructible_v<_Tp> && is_move_assignable_v<_Tp>)>;
308
309template <class _Tp>
310class _LIBCPP_DECLSPEC_EMPTY_BASES optional
311 : public __optional_move_assign_base<_Tp>,
312 private __optional_sfinae_ctor_base_t<_Tp>,
313 private __optional_sfinae_assign_base_t<_Tp> {
314 using __base _LIBCPP_NODEBUG = __optional_move_assign_base<_Tp>;
315
316public:
317 using value_type = __libcpp_remove_reference_t<_Tp>;
318
319 using __trivially_relocatable _LIBCPP_NODEBUG = conditional_t<__is_trivially_relocatable_v<_Tp>, optional, void>;
320
321private:
322 static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>, "instantiation of optional with in_place_t is ill-formed");
323 static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>, "instantiation of optional with nullopt_t is ill-formed");
324 static_assert(is_destructible_v<_Tp>, "instantiation of optional with a non-destructible type is ill-formed");
325 static_assert(!is_array_v<_Tp>, "instantiation of optional with an array type is ill-formed");
326
327 // LWG2756: conditionally explicit conversion from _Up
328 struct _CheckOptionalArgsConstructor {
329 template <class _Up>
330 _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
331 return is_constructible_v<_Tp, _Up&&> && is_convertible_v<_Up&&, _Tp>;
332 }
333
334 template <class _Up>
335 _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
336 return is_constructible_v<_Tp, _Up&&> && !is_convertible_v<_Up&&, _Tp>;
337 }
338 };
339 template <class _Up>
340 using _CheckOptionalArgsCtor _LIBCPP_NODEBUG =
341 _If< _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value && _IsNotSame<__remove_cvref_t<_Up>, optional>::value &&
342 (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_optional_v<__remove_cvref_t<_Up>>),
343 _CheckOptionalArgsConstructor,
344 __check_tuple_constructor_fail >;
345 template <class _QualUp>
346 struct _CheckOptionalLikeConstructor {
347 template <class _Up, class _Opt = optional<_Up>>
348 using __check_constructible_from_opt _LIBCPP_NODEBUG =
349 _Or< is_constructible<_Tp, _Opt&>,
350 is_constructible<_Tp, _Opt const&>,
351 is_constructible<_Tp, _Opt&&>,
352 is_constructible<_Tp, _Opt const&&>,
353 is_convertible<_Opt&, _Tp>,
354 is_convertible<_Opt const&, _Tp>,
355 is_convertible<_Opt&&, _Tp>,
356 is_convertible<_Opt const&&, _Tp> >;
357 template <class _Up, class _Opt = optional<_Up>>
358 using __check_assignable_from_opt _LIBCPP_NODEBUG =
359 _Or< is_assignable<_Tp&, _Opt&>,
360 is_assignable<_Tp&, _Opt const&>,
361 is_assignable<_Tp&, _Opt&&>,
362 is_assignable<_Tp&, _Opt const&&> >;
363 template <class _Up, class _QUp = _QualUp>
364 _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
365 return is_convertible<_QUp, _Tp>::value &&
366 (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value);
367 }
368 template <class _Up, class _QUp = _QualUp>
369 _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
370 return !is_convertible<_QUp, _Tp>::value &&
371 (is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value);
372 }
373 template <class _Up, class _QUp = _QualUp>
374 _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_assign() {
375 // Construction and assignability of _QUp to _Tp has already been
376 // checked.
377 return !__check_constructible_from_opt<_Up>::value && !__check_assignable_from_opt<_Up>::value;
378 }
379 };
380
381 template <class _Up, class _QualUp>
382 using _CheckOptionalLikeCtor _LIBCPP_NODEBUG =
383 _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp> >::value,
384 _CheckOptionalLikeConstructor<_QualUp>,
385 __check_tuple_constructor_fail >;
386 template <class _Up, class _QualUp>
387 using _CheckOptionalLikeAssign _LIBCPP_NODEBUG =
388 _If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp>, is_assignable<_Tp&, _QualUp> >::value,
389 _CheckOptionalLikeConstructor<_QualUp>,
390 __check_tuple_constructor_fail >;
391
392public:
393 _LIBCPP_HIDE_FROM_ABI constexpr optional() noexcept {}
394 _LIBCPP_HIDE_FROM_ABI constexpr optional(const optional&) = default;
395 _LIBCPP_HIDE_FROM_ABI constexpr optional(optional&&) = default;
396 _LIBCPP_HIDE_FROM_ABI constexpr optional(nullopt_t) noexcept {}
397
398 template <class _InPlaceT,
399 class... _Args,
400 enable_if_t<_And<_IsSame<_InPlaceT, in_place_t>, is_constructible<_Tp, _Args...>>::value, int> = 0>
401 _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_InPlaceT, _Args&&... __args)
402 : __base(in_place, std::forward<_Args>(__args)...) {}
403
404 template <class _Up, class... _Args, enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>, int> = 0>
405 _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
406 : __base(in_place, __il, std::forward<_Args>(__args)...) {}
407
408 template <class _Up = _Tp, enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
409 _LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v) noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened
410 : __base(in_place, std::forward<_Up>(__v)) {}
411
412 template <class _Up = remove_cv_t<_Tp>,
413 enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0>
414 _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v) noexcept(
415 is_nothrow_constructible_v<_Tp, _Up>) // strengthened
416 : __base(in_place, std::forward<_Up>(__v)) {}
417
418 // LWG2756: conditionally explicit conversion from const optional<_Up>&
419 template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0>
420 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) {
421 this->__construct_from(__v);
422 }
423
424 template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0>
425 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) {
426 this->__construct_from(__v);
427 }
428
429 // LWG2756: conditionally explicit conversion from optional<_Up>&&
430 template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0>
431 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) {
432 this->__construct_from(std::move(__v));
433 }
434
435 template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0>
436 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) {
437 this->__construct_from(std::move(__v));
438 }
439
440# if _LIBCPP_STD_VER >= 23
441 template <class _Tag,
442 class _Fp,
443 class... _Args,
444 enable_if_t<_IsSame<_Tag, __optional_construct_from_invoke_tag>::value, int> = 0>
445 _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Tag, _Fp&& __f, _Args&&... __args)
446 : __base(__optional_construct_from_invoke_tag{}, std::forward<_Fp>(__f), std::forward<_Args>(__args)...) {}
447# endif
448
449 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(nullopt_t) noexcept {
450 reset();
451 return *this;
452 }
453
454 _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(const optional&) = default;
455 _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(optional&&) = default;
456
457 // LWG2756
458 template <class _Up = remove_cv_t<_Tp>,
459 enable_if_t<_And<_IsNotSame<__remove_cvref_t<_Up>, optional>,
460 _Or<_IsNotSame<__remove_cvref_t<_Up>, _Tp>, _Not<is_scalar<_Tp>>>,
461 is_constructible<_Tp, _Up>,
462 is_assignable<_Tp&, _Up>>::value,
463 int> = 0>
464 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(_Up&& __v) {
465 if (this->has_value())
466 this->__val_ = std::forward<_Up>(__v);
467 else
468 this->__construct(std::forward<_Up>(__v));
469 return *this;
470 }
471
472 // LWG2756
473 template <class _Up, enable_if_t<_CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>(), int> = 0>
474 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(const optional<_Up>& __v) {
475 this->__assign_from(__v);
476 return *this;
477 }
478
479 // LWG2756
480 template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_assign<_Up>(), int> = 0>
481 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(optional<_Up>&& __v) {
482 this->__assign_from(std::move(__v));
483 return *this;
484 }
485
486 template <class... _Args, enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0>
487 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(_Args&&... __args) {
488 reset();
489 this->__construct(std::forward<_Args>(__args)...);
490 return this->__val_;
491 }
492
493 template <class _Up, class... _Args, enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>, int> = 0>
494 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) {
495 reset();
496 this->__construct(__il, std::forward<_Args>(__args)...);
497 return this->__val_;
498 }
499
500 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
501 swap(optional& __opt) noexcept((is_nothrow_move_constructible_v<_Tp> && is_nothrow_swappable_v<_Tp>)) {
502 using std::swap;
503 if (this->has_value() == __opt.has_value()) {
504 if (this->has_value())
505 swap(this->__val_, __opt.__val_);
506 } else {
507 if (this->has_value()) {
508 __opt.__construct(std::move(this->__val_));
509 this->reset();
510 } else {
511 this->__construct(std::move(__opt.__val_));
512 __opt.reset();
513 }
514 }
515 }
516
517 // [optional.observe]
518 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept {
519 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
520 return this->__val_;
521 }
522
523 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept {
524 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
525 return this->__val_;
526 }
527
528 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept {
529 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
530 return std::move(this->__val_);
531 }
532
533 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept {
534 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
535 return std::move(this->__val_);
536 }
537 _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<_Tp const> operator->() const noexcept {
538 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
539 return std::addressof(this->__val_);
540 }
541
542 _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<_Tp> operator->() noexcept {
543 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
544 return std::addressof(this->__val_);
545 }
546
547 _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return has_value(); }
548
549 using __base::has_value;
550 using __base::value;
551
552 template <class _Up = remove_cv_t<_Tp>>
553 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& {
554 static_assert(is_copy_constructible_v<_Tp>, "optional<T>::value_or: T must be copy constructible");
555 static_assert(is_convertible_v<_Up, _Tp>, "optional<T>::value_or: U must be convertible to T");
556 return this->has_value() ? this->__val_ : static_cast<_Tp>(std::forward<_Up>(__v));
557 }
558
559 template <class _Up = remove_cv_t<_Tp>>
560 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && {
561 static_assert(is_move_constructible_v<_Tp>, "optional<T>::value_or: T must be move constructible");
562 static_assert(is_convertible_v<_Up, _Tp>, "optional<T>::value_or: U must be convertible to T");
563 return this->has_value() ? std::move(this->__val_) : static_cast<_Tp>(std::forward<_Up>(__v));
564 }
565
566# if _LIBCPP_STD_VER >= 23
567 template <class _Func>
568 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & {
569 using _Up = invoke_result_t<_Func, _Tp&>;
570 static_assert(
571 __is_std_optional_v<remove_cvref_t<_Up>>, "Result of f(value()) must be a specialization of std::optional");
572 if (*this)
573 return std::invoke(std::forward<_Func>(__f), value());
574 return remove_cvref_t<_Up>();
575 }
576
577 template <class _Func>
578 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& {
579 using _Up = invoke_result_t<_Func, const _Tp&>;
580 static_assert(
581 __is_std_optional_v<remove_cvref_t<_Up>>, "Result of f(value()) must be a specialization of std::optional");
582 if (*this)
583 return std::invoke(std::forward<_Func>(__f), value());
584 return remove_cvref_t<_Up>();
585 }
586
587 template <class _Func>
588 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && {
589 using _Up = invoke_result_t<_Func, _Tp&&>;
590 static_assert(__is_std_optional_v<remove_cvref_t<_Up>>,
591 "Result of f(std::move(value())) must be a specialization of std::optional");
592 if (*this)
593 return std::invoke(std::forward<_Func>(__f), std::move(value()));
594 return remove_cvref_t<_Up>();
595 }
596
597 template <class _Func>
598 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& {
599 using _Up = invoke_result_t<_Func, const _Tp&&>;
600 static_assert(__is_std_optional_v<remove_cvref_t<_Up>>,
601 "Result of f(std::move(value())) must be a specialization of std::optional");
602 if (*this)
603 return std::invoke(std::forward<_Func>(__f), std::move(value()));
604 return remove_cvref_t<_Up>();
605 }
606
607 template <class _Func>
608 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & {
609 using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&>>;
610 static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
611 static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
612 static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
613 static_assert(
614 __is_valid_optional_contained_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
615 if (*this)
616 return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
617 return optional<_Up>();
618 }
619
620 template <class _Func>
621 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& {
622 using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&>>;
623 static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
624 static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
625 static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
626 static_assert(
627 __is_valid_optional_contained_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
628 if (*this)
629 return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
630 return optional<_Up>();
631 }
632
633 template <class _Func>
634 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && {
635 using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&&>>;
636 static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
637 static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
638 static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
639 static_assert(
640 __is_valid_optional_contained_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
641 if (*this)
642 return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value()));
643 return optional<_Up>();
644 }
645
646 template <class _Func>
647 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& {
648 using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&&>>;
649 static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
650 static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
651 static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
652 static_assert(
653 __is_valid_optional_contained_type<_Up>, "Result of f(value()) should be a valid contained type for optional");
654 if (*this)
655 return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value()));
656 return optional<_Up>();
657 }
658
659 template <invocable _Func>
660 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const&
661 requires is_copy_constructible_v<_Tp>
662 {
663 static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
664 "Result of f() should be the same type as this optional");
665 if (*this)
666 return *this;
667 return std::forward<_Func>(__f)();
668 }
669
670 template <invocable _Func>
671 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) &&
672 requires is_move_constructible_v<_Tp>
673 {
674 static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
675 "Result of f() should be the same type as this optional");
676 if (*this)
677 return std::move(*this);
678 return std::forward<_Func>(__f)();
679 }
680# endif // _LIBCPP_STD_VER >= 23
681
682 using __base::reset;
683
684# if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
685
686private:
687 using __pointer _LIBCPP_NODEBUG = add_pointer_t<_Tp>;
688 using __const_pointer _LIBCPP_NODEBUG = add_pointer_t<const _Tp>;
689
690public:
691# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
692 using iterator = __bounded_iter<__pointer>;
693 using const_iterator = __bounded_iter<__const_pointer>;
694# else
695 using iterator = __capacity_aware_iterator<__pointer, optional<_Tp>, 1>;
696 using const_iterator = __capacity_aware_iterator<__const_pointer, optional<_Tp>, 1>;
697# endif
698
699 // [optional.iterators], iterator support
700 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator begin() noexcept {
701 auto* __ptr = std::addressof(this->__val_);
702
703# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
704 return std::__make_bounded_iter(__ptr, __ptr, __ptr + (this->has_value() ? 1 : 0));
705# else
706 return std::__make_capacity_aware_iterator<__pointer, optional<_Tp>, 1>(__ptr);
707# endif
708 }
709
710 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const_iterator begin() const noexcept {
711 auto* __ptr = std::addressof(this->__val_);
712
713# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
714 return std::__make_bounded_iter(__ptr, __ptr, __ptr + (this->has_value() ? 1 : 0));
715# else
716 return std::__make_capacity_aware_iterator<__const_pointer, optional<_Tp>, 1>(__ptr);
717# endif
718 }
719
720 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator end() noexcept {
721 return begin() + (this->has_value() ? 1 : 0);
722 }
723 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const_iterator end() const noexcept {
724 return begin() + (this->has_value() ? 1 : 0);
725 }
726
727# endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
728};
729
730_LIBCPP_END_NAMESPACE_STD
731
732#endif // _LIBCPP_STD_VER >= 17
733
734_LIBCPP_POP_MACROS
735
736#endif // _LIBCPP___OPTIONAL_OPTIONAL_H
737