blob: 236842d627d938890934fb0ea546d736335ba94e [file] [log] [blame]
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001// -*- C++ -*-
Louis Dionne9bd93882021-11-17 16:25:01 -05002//===----------------------------------------------------------------------===//
Eric Fiselierd4ec6352016-10-12 07:46:20 +00003//
Chandler Carruthd2012102019-01-19 10:56:40 +00004// 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
Eric Fiselierd4ec6352016-10-12 07:46:20 +00007//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_OPTIONAL
11#define _LIBCPP_OPTIONAL
12
13/*
14 optional synopsis
15
16// C++1z
17
18namespace std {
Casey Carter84b8a402017-04-17 20:15:16 +000019 // 23.6.3, optional for object types
Eric Fiselierd4ec6352016-10-12 07:46:20 +000020 template <class T> class optional;
21
Casey Carter84b8a402017-04-17 20:15:16 +000022 // 23.6.4, no-value state indicator
Eric Fiselierd4ec6352016-10-12 07:46:20 +000023 struct nullopt_t{see below };
Marshall Clowf1bf62f2018-01-02 17:17:01 +000024 inline constexpr nullopt_t nullopt(unspecified );
Eric Fiselierd4ec6352016-10-12 07:46:20 +000025
Casey Carter84b8a402017-04-17 20:15:16 +000026 // 23.6.5, class bad_optional_access
Eric Fiselierd4ec6352016-10-12 07:46:20 +000027 class bad_optional_access;
28
Casey Carter84b8a402017-04-17 20:15:16 +000029 // 23.6.6, relational operators
30 template <class T, class U>
31 constexpr bool operator==(const optional<T>&, const optional<U>&);
32 template <class T, class U>
33 constexpr bool operator!=(const optional<T>&, const optional<U>&);
34 template <class T, class U>
35 constexpr bool operator<(const optional<T>&, const optional<U>&);
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
43 // 23.6.7 comparison with nullopt
Eric Fiselierd4ec6352016-10-12 07:46:20 +000044 template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
45 template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
46 template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
47 template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
48 template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
49 template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
50 template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
51 template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
52 template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
53 template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
54 template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
55 template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;
56
Casey Carter84b8a402017-04-17 20:15:16 +000057 // 23.6.8, comparison with T
58 template <class T, class U> constexpr bool operator==(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000059 template <class T, class U> constexpr bool operator==(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000060 template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000061 template <class T, class U> constexpr bool operator!=(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000062 template <class T, class U> constexpr bool operator<(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000063 template <class T, class U> constexpr bool operator<(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000064 template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000065 template <class T, class U> constexpr bool operator<=(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000066 template <class T, class U> constexpr bool operator>(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000067 template <class T, class U> constexpr bool operator>(const T&, const optional<U>&);
Casey Carter84b8a402017-04-17 20:15:16 +000068 template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
Marshall Clow29dd7e42017-11-01 01:27:25 +000069 template <class T, class U> constexpr bool operator>=(const T&, const optional<U>&);
Eric Fiselierd4ec6352016-10-12 07:46:20 +000070
Casey Carter84b8a402017-04-17 20:15:16 +000071 // 23.6.9, specialized algorithms
Christopher Di Bella80e8f642021-05-09 01:30:32 +000072 template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20
Eric Fiselierd4ec6352016-10-12 07:46:20 +000073 template <class T> constexpr optional<see below > make_optional(T&&);
74 template <class T, class... Args>
75 constexpr optional<T> make_optional(Args&&... args);
76 template <class T, class U, class... Args>
77 constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
78
Casey Carter84b8a402017-04-17 20:15:16 +000079 // 23.6.10, hash support
Eric Fiselierd4ec6352016-10-12 07:46:20 +000080 template <class T> struct hash;
81 template <class T> struct hash<optional<T>>;
82
83 template <class T> class optional {
84 public:
85 using value_type = T;
86
Casey Carter84b8a402017-04-17 20:15:16 +000087 // 23.6.3.1, constructors
Eric Fiselierd4ec6352016-10-12 07:46:20 +000088 constexpr optional() noexcept;
89 constexpr optional(nullopt_t) noexcept;
90 optional(const optional &);
Marshall Clow45ff9822017-04-12 22:51:27 +000091 optional(optional &&) noexcept(see below);
Eric Fiselierd4ec6352016-10-12 07:46:20 +000092 template <class... Args> constexpr explicit optional(in_place_t, Args &&...);
93 template <class U, class... Args>
94 constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...);
95 template <class U = T>
96 constexpr EXPLICIT optional(U &&);
97 template <class U>
Christopher Di Bella80e8f642021-05-09 01:30:32 +000098 EXPLICIT optional(const optional<U> &); // constexpr in C++20
Eric Fiselierd4ec6352016-10-12 07:46:20 +000099 template <class U>
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000100 EXPLICIT optional(optional<U> &&); // constexpr in C++20
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000101
Casey Carter84b8a402017-04-17 20:15:16 +0000102 // 23.6.3.2, destructor
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000103 ~optional(); // constexpr in C++20
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000104
Casey Carter84b8a402017-04-17 20:15:16 +0000105 // 23.6.3.3, assignment
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000106 optional &operator=(nullopt_t) noexcept; // constexpr in C++20
107 optional &operator=(const optional &); // constexpr in C++20
108 optional &operator=(optional &&) noexcept(see below); // constexpr in C++20
109 template <class U = T> optional &operator=(U &&); // constexpr in C++20
110 template <class U> optional &operator=(const optional<U> &); // constexpr in C++20
111 template <class U> optional &operator=(optional<U> &&); // constexpr in C++20
112 template <class... Args> T& emplace(Args &&...); // constexpr in C++20
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000113 template <class U, class... Args>
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000114 T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000115
Casey Carter84b8a402017-04-17 20:15:16 +0000116 // 23.6.3.4, swap
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000117 void swap(optional &) noexcept(see below ); // constexpr in C++20
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000118
Casey Carter84b8a402017-04-17 20:15:16 +0000119 // 23.6.3.5, observers
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000120 constexpr T const *operator->() const;
121 constexpr T *operator->();
122 constexpr T const &operator*() const &;
123 constexpr T &operator*() &;
124 constexpr T &&operator*() &&;
125 constexpr const T &&operator*() const &&;
126 constexpr explicit operator bool() const noexcept;
127 constexpr bool has_value() const noexcept;
128 constexpr T const &value() const &;
129 constexpr T &value() &;
130 constexpr T &&value() &&;
131 constexpr const T &&value() const &&;
132 template <class U> constexpr T value_or(U &&) const &;
133 template <class U> constexpr T value_or(U &&) &&;
134
Nikolas Klauserf6c419a2021-12-15 20:54:24 +0100135 // [optional.monadic], monadic operations
136 template<class F> constexpr auto and_then(F&& f) &; // since C++23
137 template<class F> constexpr auto and_then(F&& f) &&; // since C++23
138 template<class F> constexpr auto and_then(F&& f) const&; // since C++23
139 template<class F> constexpr auto and_then(F&& f) const&&; // since C++23
140 template<class F> constexpr auto transform(F&& f) &; // since C++23
141 template<class F> constexpr auto transform(F&& f) &&; // since C++23
142 template<class F> constexpr auto transform(F&& f) const&; // since C++23
143 template<class F> constexpr auto transform(F&& f) const&&; // since C++23
144 template<class F> constexpr optional or_else(F&& f) &&; // since C++23
145 template<class F> constexpr optional or_else(F&& f) const&; // since C++23
146
Casey Carter84b8a402017-04-17 20:15:16 +0000147 // 23.6.3.6, modifiers
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000148 void reset() noexcept; // constexpr in C++20
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000149
150 private:
151 T *val; // exposition only
152 };
Marshall Clowe3c71ae2018-05-25 02:08:49 +0000153
154template<class T>
155 optional(T) -> optional<T>;
156
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000157} // namespace std
158
159*/
160
Louis Dionne73912b22020-11-04 15:01:25 -0500161#include <__availability>
Nikolas Klauserf6c419a2021-12-15 20:54:24 +0100162#include <__concepts/invocable.h>
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400163#include <__config>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000164#include <__debug>
165#include <__functional_base>
Arthur O'Dwyer7deec122021-03-24 18:19:12 -0400166#include <compare>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000167#include <functional>
168#include <initializer_list>
169#include <new>
170#include <stdexcept>
171#include <type_traits>
172#include <utility>
Marshall Clow0a1e7502018-09-12 19:41:40 +0000173#include <version>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000174
175#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Arthur O'Dwyer6eeaa002022-02-01 20:16:40 -0500176# pragma GCC system_header
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000177#endif
178
179namespace std // purposefully not using versioning namespace
180{
181
Louis Dionnecef92e62018-11-19 15:37:04 +0000182class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
Marshall Clowa627d4a2017-02-05 20:06:38 +0000183 : public exception
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000184{
185public:
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000186 // Get the key function ~bad_optional_access() into the dylib
Marshall Clow53fc0372017-02-05 20:52:32 +0000187 virtual ~bad_optional_access() _NOEXCEPT;
Marshall Clowa627d4a2017-02-05 20:06:38 +0000188 virtual const char* what() const _NOEXCEPT;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000189};
190
Nikolas Klauserd26407a2021-12-02 14:12:51 +0100191} // namespace std
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000192
193#if _LIBCPP_STD_VER > 14
194
195_LIBCPP_BEGIN_NAMESPACE_STD
196
197_LIBCPP_NORETURN
198inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000199_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000200void __throw_bad_optional_access() {
201#ifndef _LIBCPP_NO_EXCEPTIONS
202 throw bad_optional_access();
203#else
204 _VSTD::abort();
205#endif
206}
207
208struct nullopt_t
209{
210 struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
211 _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
212};
213
Louis Dionne559be102021-09-22 09:35:32 -0400214inline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000215
Nikolas Klauserf6c419a2021-12-15 20:54:24 +0100216struct __optional_construct_from_invoke_tag {};
217
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000218template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
219struct __optional_destruct_base;
220
221template <class _Tp>
222struct __optional_destruct_base<_Tp, false>
223{
224 typedef _Tp value_type;
225 static_assert(is_object_v<value_type>,
226 "instantiation of optional with a non-object type is undefined behavior");
227 union
228 {
229 char __null_state_;
230 value_type __val_;
231 };
232 bool __engaged_;
233
234 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000235 _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__optional_destruct_base()
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000236 {
237 if (__engaged_)
238 __val_.~value_type();
239 }
240
241 _LIBCPP_INLINE_VISIBILITY
242 constexpr __optional_destruct_base() noexcept
243 : __null_state_(),
244 __engaged_(false) {}
245
246 template <class... _Args>
247 _LIBCPP_INLINE_VISIBILITY
248 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
249 : __val_(_VSTD::forward<_Args>(__args)...),
250 __engaged_(true) {}
251
Nikolas Klauserf6c419a2021-12-15 20:54:24 +0100252#if _LIBCPP_STD_VER > 20
253 template <class _Fp, class... _Args>
254 _LIBCPP_HIDE_FROM_ABI
255 constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
256 : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {}
257#endif
258
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000259 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000260 _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000261 {
262 if (__engaged_)
263 {
264 __val_.~value_type();
265 __engaged_ = false;
266 }
267 }
268};
269
270template <class _Tp>
271struct __optional_destruct_base<_Tp, true>
272{
273 typedef _Tp value_type;
274 static_assert(is_object_v<value_type>,
275 "instantiation of optional with a non-object type is undefined behavior");
276 union
277 {
278 char __null_state_;
279 value_type __val_;
280 };
281 bool __engaged_;
282
283 _LIBCPP_INLINE_VISIBILITY
284 constexpr __optional_destruct_base() noexcept
285 : __null_state_(),
286 __engaged_(false) {}
287
288 template <class... _Args>
289 _LIBCPP_INLINE_VISIBILITY
290 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
291 : __val_(_VSTD::forward<_Args>(__args)...),
292 __engaged_(true) {}
293
Nikolas Klauserf6c419a2021-12-15 20:54:24 +0100294#if _LIBCPP_STD_VER > 20
295 template <class _Fp, class... _Args>
296 _LIBCPP_HIDE_FROM_ABI
297 constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
298 : __val_(_VSTD::invoke(_VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...)), __engaged_(true) {}
299#endif
300
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000301 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000302 _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000303 {
304 if (__engaged_)
305 {
306 __engaged_ = false;
307 }
308 }
309};
310
311template <class _Tp, bool = is_reference<_Tp>::value>
312struct __optional_storage_base : __optional_destruct_base<_Tp>
313{
314 using __base = __optional_destruct_base<_Tp>;
315 using value_type = _Tp;
316 using __base::__base;
317
318 _LIBCPP_INLINE_VISIBILITY
319 constexpr bool has_value() const noexcept
320 {
321 return this->__engaged_;
322 }
323
324 _LIBCPP_INLINE_VISIBILITY
325 constexpr value_type& __get() & noexcept
326 {
327 return this->__val_;
328 }
329 _LIBCPP_INLINE_VISIBILITY
330 constexpr const value_type& __get() const& noexcept
331 {
332 return this->__val_;
333 }
334 _LIBCPP_INLINE_VISIBILITY
335 constexpr value_type&& __get() && noexcept
336 {
337 return _VSTD::move(this->__val_);
338 }
339 _LIBCPP_INLINE_VISIBILITY
340 constexpr const value_type&& __get() const&& noexcept
341 {
342 return _VSTD::move(this->__val_);
343 }
344
345 template <class... _Args>
346 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000347 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_Args&&... __args)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000348 {
349 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000350#if _LIBCPP_STD_VER > 17
351 _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...);
352#else
Arthur O'Dwyer0c4472a2020-12-11 20:30:28 -0500353 ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000354#endif
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000355 this->__engaged_ = true;
356 }
357
358 template <class _That>
359 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000360 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000361 {
362 if (__opt.has_value())
363 __construct(_VSTD::forward<_That>(__opt).__get());
364 }
365
366 template <class _That>
367 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000368 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000369 {
370 if (this->__engaged_ == __opt.has_value())
371 {
372 if (this->__engaged_)
373 this->__val_ = _VSTD::forward<_That>(__opt).__get();
374 }
375 else
376 {
377 if (this->__engaged_)
378 this->reset();
379 else
380 __construct(_VSTD::forward<_That>(__opt).__get());
381 }
382 }
383};
384
385// optional<T&> is currently required ill-formed, however it may to be in the
386// future. For this reason it has already been implemented to ensure we can
387// make the change in an ABI compatible manner.
388template <class _Tp>
389struct __optional_storage_base<_Tp, true>
390{
391 using value_type = _Tp;
392 using __raw_type = remove_reference_t<_Tp>;
393 __raw_type* __value_;
394
395 template <class _Up>
396 static constexpr bool __can_bind_reference() {
397 using _RawUp = typename remove_reference<_Up>::type;
398 using _UpPtr = _RawUp*;
399 using _RawTp = typename remove_reference<_Tp>::type;
400 using _TpPtr = _RawTp*;
401 using _CheckLValueArg = integral_constant<bool,
402 (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
403 || is_same<_RawUp, reference_wrapper<_RawTp>>::value
404 || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
405 >;
406 return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
407 || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
408 is_convertible<_UpPtr, _TpPtr>::value);
409 }
410
411 _LIBCPP_INLINE_VISIBILITY
412 constexpr __optional_storage_base() noexcept
413 : __value_(nullptr) {}
414
415 template <class _UArg>
416 _LIBCPP_INLINE_VISIBILITY
417 constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
418 : __value_(_VSTD::addressof(__uarg))
419 {
420 static_assert(__can_bind_reference<_UArg>(),
421 "Attempted to construct a reference element in tuple from a "
422 "possible temporary");
423 }
424
425 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000426 _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept { __value_ = nullptr; }
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000427
428 _LIBCPP_INLINE_VISIBILITY
429 constexpr bool has_value() const noexcept
430 { return __value_ != nullptr; }
431
432 _LIBCPP_INLINE_VISIBILITY
433 constexpr value_type& __get() const& noexcept
434 { return *__value_; }
435
436 _LIBCPP_INLINE_VISIBILITY
437 constexpr value_type&& __get() const&& noexcept
438 { return _VSTD::forward<value_type>(*__value_); }
439
440 template <class _UArg>
441 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000442 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_UArg&& __val)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000443 {
444 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
445 static_assert(__can_bind_reference<_UArg>(),
446 "Attempted to construct a reference element in tuple from a "
447 "possible temporary");
448 __value_ = _VSTD::addressof(__val);
449 }
450
451 template <class _That>
452 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000453 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000454 {
455 if (__opt.has_value())
456 __construct(_VSTD::forward<_That>(__opt).__get());
457 }
458
459 template <class _That>
460 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000461 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000462 {
463 if (has_value() == __opt.has_value())
464 {
465 if (has_value())
466 *__value_ = _VSTD::forward<_That>(__opt).__get();
467 }
468 else
469 {
470 if (has_value())
471 reset();
472 else
473 __construct(_VSTD::forward<_That>(__opt).__get());
474 }
475 }
476};
477
Casey Carterc189f7f2017-07-09 17:15:49 +0000478template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
479struct __optional_copy_base : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000480{
481 using __optional_storage_base<_Tp>::__optional_storage_base;
482};
483
484template <class _Tp>
Casey Carterc189f7f2017-07-09 17:15:49 +0000485struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000486{
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000487 using __optional_storage_base<_Tp>::__optional_storage_base;
488
489 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000490 __optional_copy_base() = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000491
492 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000493 _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_base(const __optional_copy_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000494 {
495 this->__construct_from(__opt);
496 }
497
498 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000499 __optional_copy_base(__optional_copy_base&&) = default;
500 _LIBCPP_INLINE_VISIBILITY
501 __optional_copy_base& operator=(const __optional_copy_base&) = default;
502 _LIBCPP_INLINE_VISIBILITY
503 __optional_copy_base& operator=(__optional_copy_base&&) = default;
504};
505
506template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
507struct __optional_move_base : __optional_copy_base<_Tp>
508{
509 using __optional_copy_base<_Tp>::__optional_copy_base;
510};
511
512template <class _Tp>
513struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
514{
515 using value_type = _Tp;
516 using __optional_copy_base<_Tp>::__optional_copy_base;
517
518 _LIBCPP_INLINE_VISIBILITY
519 __optional_move_base() = default;
520 _LIBCPP_INLINE_VISIBILITY
521 __optional_move_base(const __optional_move_base&) = default;
522
523 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000524 _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_base(__optional_move_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000525 noexcept(is_nothrow_move_constructible_v<value_type>)
526 {
527 this->__construct_from(_VSTD::move(__opt));
528 }
529
530 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000531 __optional_move_base& operator=(const __optional_move_base&) = default;
532 _LIBCPP_INLINE_VISIBILITY
533 __optional_move_base& operator=(__optional_move_base&&) = default;
534};
535
536template <class _Tp, bool =
537 is_trivially_destructible<_Tp>::value &&
538 is_trivially_copy_constructible<_Tp>::value &&
539 is_trivially_copy_assignable<_Tp>::value>
540struct __optional_copy_assign_base : __optional_move_base<_Tp>
541{
542 using __optional_move_base<_Tp>::__optional_move_base;
543};
544
545template <class _Tp>
546struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
547{
548 using __optional_move_base<_Tp>::__optional_move_base;
549
550 _LIBCPP_INLINE_VISIBILITY
551 __optional_copy_assign_base() = default;
552 _LIBCPP_INLINE_VISIBILITY
553 __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
554 _LIBCPP_INLINE_VISIBILITY
555 __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
556
557 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000558 _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000559 {
560 this->__assign_from(__opt);
561 return *this;
562 }
563
564 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000565 __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
566};
567
568template <class _Tp, bool =
569 is_trivially_destructible<_Tp>::value &&
570 is_trivially_move_constructible<_Tp>::value &&
571 is_trivially_move_assignable<_Tp>::value>
572struct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
573{
574 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
575};
576
577template <class _Tp>
578struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
579{
580 using value_type = _Tp;
581 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
582
583 _LIBCPP_INLINE_VISIBILITY
584 __optional_move_assign_base() = default;
585 _LIBCPP_INLINE_VISIBILITY
586 __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
587 _LIBCPP_INLINE_VISIBILITY
588 __optional_move_assign_base(__optional_move_assign_base&&) = default;
589 _LIBCPP_INLINE_VISIBILITY
590 __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
591
592 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000593 _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000594 noexcept(is_nothrow_move_assignable_v<value_type> &&
595 is_nothrow_move_constructible_v<value_type>)
596 {
597 this->__assign_from(_VSTD::move(__opt));
598 return *this;
599 }
600};
601
602template <class _Tp>
603using __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
604 is_copy_constructible<_Tp>::value,
605 is_move_constructible<_Tp>::value
606>;
607
608template <class _Tp>
609using __optional_sfinae_assign_base_t = __sfinae_assign_base<
610 (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
611 (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
612>;
613
Nikolas Klauserf6c419a2021-12-15 20:54:24 +0100614template<class _Tp>
615class optional;
616template <class _Tp>
617struct __is_std_optional : false_type {};
618template <class _Tp> struct __is_std_optional<optional<_Tp>> : true_type {};
619
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000620template <class _Tp>
621class optional
Casey Carterc189f7f2017-07-09 17:15:49 +0000622 : private __optional_move_assign_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000623 , private __optional_sfinae_ctor_base_t<_Tp>
624 , private __optional_sfinae_assign_base_t<_Tp>
625{
Casey Carterc189f7f2017-07-09 17:15:49 +0000626 using __base = __optional_move_assign_base<_Tp>;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000627public:
628 using value_type = _Tp;
629
630private:
631 // Disable the reference extension using this static assert.
Marshall Clowfa6a3342019-03-25 16:35:59 +0000632 static_assert(!is_same_v<__uncvref_t<value_type>, in_place_t>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000633 "instantiation of optional with in_place_t is ill-formed");
634 static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
635 "instantiation of optional with nullopt_t is ill-formed");
636 static_assert(!is_reference_v<value_type>,
637 "instantiation of optional with a reference type is ill-formed");
638 static_assert(is_destructible_v<value_type>,
639 "instantiation of optional with a non-destructible type is ill-formed");
Marshall Clowfa6a3342019-03-25 16:35:59 +0000640 static_assert(!is_array_v<value_type>,
641 "instantiation of optional with an array type is ill-formed");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000642
643 // LWG2756: conditionally explicit conversion from _Up
644 struct _CheckOptionalArgsConstructor {
645 template <class _Up>
646 static constexpr bool __enable_implicit() {
647 return is_constructible_v<_Tp, _Up&&> &&
648 is_convertible_v<_Up&&, _Tp>;
649 }
650
651 template <class _Up>
652 static constexpr bool __enable_explicit() {
653 return is_constructible_v<_Tp, _Up&&> &&
654 !is_convertible_v<_Up&&, _Tp>;
655 }
656 };
657 template <class _Up>
Eric Fiselier3906a132019-06-23 20:28:29 +0000658 using _CheckOptionalArgsCtor = _If<
659 _IsNotSame<__uncvref_t<_Up>, in_place_t>::value &&
660 _IsNotSame<__uncvref_t<_Up>, optional>::value,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000661 _CheckOptionalArgsConstructor,
662 __check_tuple_constructor_fail
663 >;
664 template <class _QualUp>
665 struct _CheckOptionalLikeConstructor {
666 template <class _Up, class _Opt = optional<_Up>>
Eric Fiselier3906a132019-06-23 20:28:29 +0000667 using __check_constructible_from_opt = _Or<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000668 is_constructible<_Tp, _Opt&>,
669 is_constructible<_Tp, _Opt const&>,
670 is_constructible<_Tp, _Opt&&>,
671 is_constructible<_Tp, _Opt const&&>,
672 is_convertible<_Opt&, _Tp>,
673 is_convertible<_Opt const&, _Tp>,
674 is_convertible<_Opt&&, _Tp>,
675 is_convertible<_Opt const&&, _Tp>
676 >;
677 template <class _Up, class _Opt = optional<_Up>>
Eric Fiselier3906a132019-06-23 20:28:29 +0000678 using __check_assignable_from_opt = _Or<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000679 is_assignable<_Tp&, _Opt&>,
680 is_assignable<_Tp&, _Opt const&>,
681 is_assignable<_Tp&, _Opt&&>,
682 is_assignable<_Tp&, _Opt const&&>
683 >;
684 template <class _Up, class _QUp = _QualUp>
685 static constexpr bool __enable_implicit() {
686 return is_convertible<_QUp, _Tp>::value &&
687 !__check_constructible_from_opt<_Up>::value;
688 }
689 template <class _Up, class _QUp = _QualUp>
690 static constexpr bool __enable_explicit() {
691 return !is_convertible<_QUp, _Tp>::value &&
692 !__check_constructible_from_opt<_Up>::value;
693 }
694 template <class _Up, class _QUp = _QualUp>
695 static constexpr bool __enable_assign() {
Arthur O'Dwyerdf5df562020-12-12 11:57:32 -0500696 // Construction and assignability of _QUp to _Tp has already been
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000697 // checked.
698 return !__check_constructible_from_opt<_Up>::value &&
699 !__check_assignable_from_opt<_Up>::value;
700 }
701 };
702
703 template <class _Up, class _QualUp>
Eric Fiselier3906a132019-06-23 20:28:29 +0000704 using _CheckOptionalLikeCtor = _If<
705 _And<
706 _IsNotSame<_Up, _Tp>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000707 is_constructible<_Tp, _QualUp>
708 >::value,
709 _CheckOptionalLikeConstructor<_QualUp>,
710 __check_tuple_constructor_fail
711 >;
712 template <class _Up, class _QualUp>
Eric Fiselier3906a132019-06-23 20:28:29 +0000713 using _CheckOptionalLikeAssign = _If<
714 _And<
715 _IsNotSame<_Up, _Tp>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000716 is_constructible<_Tp, _QualUp>,
717 is_assignable<_Tp&, _QualUp>
718 >::value,
719 _CheckOptionalLikeConstructor<_QualUp>,
720 __check_tuple_constructor_fail
721 >;
Nikolas Klauserf6c419a2021-12-15 20:54:24 +0100722
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000723public:
724
725 _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
Marshall Clowd44e2e32017-05-17 15:30:01 +0000726 _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
727 _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000728 _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
729
Louis Dionne25547162021-08-17 12:26:09 -0400730 template <class _InPlaceT, class... _Args, class = enable_if_t<
Eric Fiselier3906a132019-06-23 20:28:29 +0000731 _And<
732 _IsSame<_InPlaceT, in_place_t>,
733 is_constructible<value_type, _Args...>
Eric Fiselier82103932019-03-11 22:55:21 +0000734 >::value
735 >
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000736 >
737 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier82103932019-03-11 22:55:21 +0000738 constexpr explicit optional(_InPlaceT, _Args&&... __args)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000739 : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
740
Louis Dionne25547162021-08-17 12:26:09 -0400741 template <class _Up, class... _Args, class = enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000742 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
743 >
744 _LIBCPP_INLINE_VISIBILITY
745 constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
746 : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
747
Louis Dionne25547162021-08-17 12:26:09 -0400748 template <class _Up = value_type, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000749 _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
750 , int> = 0>
751 _LIBCPP_INLINE_VISIBILITY
752 constexpr optional(_Up&& __v)
753 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
754
Louis Dionne25547162021-08-17 12:26:09 -0400755 template <class _Up, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000756 _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
757 , int> = 0>
758 _LIBCPP_INLINE_VISIBILITY
759 constexpr explicit optional(_Up&& __v)
760 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
761
762 // LWG2756: conditionally explicit conversion from const optional<_Up>&
Louis Dionne25547162021-08-17 12:26:09 -0400763 template <class _Up, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000764 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
765 , int> = 0>
766 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000767 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(const optional<_Up>& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000768 {
769 this->__construct_from(__v);
770 }
Louis Dionne25547162021-08-17 12:26:09 -0400771 template <class _Up, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000772 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
773 , int> = 0>
774 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000775 _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(const optional<_Up>& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000776 {
777 this->__construct_from(__v);
778 }
779
780 // LWG2756: conditionally explicit conversion from optional<_Up>&&
Louis Dionne25547162021-08-17 12:26:09 -0400781 template <class _Up, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000782 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
783 , int> = 0>
784 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000785 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(optional<_Up>&& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000786 {
787 this->__construct_from(_VSTD::move(__v));
788 }
Louis Dionne25547162021-08-17 12:26:09 -0400789 template <class _Up, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000790 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
791 , int> = 0>
792 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000793 _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(optional<_Up>&& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000794 {
795 this->__construct_from(_VSTD::move(__v));
796 }
797
Nikolas Klauserf6c419a2021-12-15 20:54:24 +0100798#if _LIBCPP_STD_VER > 20
799 template<class _Fp, class... _Args>
800 _LIBCPP_HIDE_FROM_ABI
801 constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args)
802 : __base(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Fp>(__f), _VSTD::forward<_Args>(__args)...) {
803 }
804#endif
805
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000806 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000807 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& operator=(nullopt_t) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000808 {
809 reset();
810 return *this;
811 }
812
813 _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
814 _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
815
816 // LWG2756
817 template <class _Up = value_type,
Louis Dionne25547162021-08-17 12:26:09 -0400818 class = enable_if_t<
Eric Fiselier3906a132019-06-23 20:28:29 +0000819 _And<
820 _IsNotSame<__uncvref_t<_Up>, optional>,
821 _Or<
Marshall Clow99315112019-06-27 18:40:55 +0000822 _IsNotSame<__uncvref_t<_Up>, value_type>,
Eric Fiselier3906a132019-06-23 20:28:29 +0000823 _Not<is_scalar<value_type>>
Eric Fiselierb9014262016-10-16 03:21:35 +0000824 >,
825 is_constructible<value_type, _Up>,
826 is_assignable<value_type&, _Up>
827 >::value>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000828 >
829 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000830 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000831 operator=(_Up&& __v)
832 {
833 if (this->has_value())
834 this->__get() = _VSTD::forward<_Up>(__v);
835 else
836 this->__construct(_VSTD::forward<_Up>(__v));
837 return *this;
838 }
839
840 // LWG2756
Louis Dionne25547162021-08-17 12:26:09 -0400841 template <class _Up, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000842 _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
843 , int> = 0>
844 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000845 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000846 operator=(const optional<_Up>& __v)
847 {
848 this->__assign_from(__v);
849 return *this;
850 }
851
852 // LWG2756
Louis Dionne25547162021-08-17 12:26:09 -0400853 template <class _Up, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000854 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
855 , int> = 0>
856 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000857 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000858 operator=(optional<_Up>&& __v)
859 {
860 this->__assign_from(_VSTD::move(__v));
861 return *this;
862 }
863
864 template <class... _Args,
Louis Dionne25547162021-08-17 12:26:09 -0400865 class = enable_if_t
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000866 <
867 is_constructible_v<value_type, _Args...>
868 >
869 >
870 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000871 _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000872 emplace(_Args&&... __args)
873 {
874 reset();
875 this->__construct(_VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000876 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000877 }
878
879 template <class _Up, class... _Args,
Louis Dionne25547162021-08-17 12:26:09 -0400880 class = enable_if_t
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000881 <
882 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
883 >
884 >
885 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000886 _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000887 emplace(initializer_list<_Up> __il, _Args&&... __args)
888 {
889 reset();
890 this->__construct(__il, _VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000891 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000892 }
893
894 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000895 _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(optional& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000896 noexcept(is_nothrow_move_constructible_v<value_type> &&
897 is_nothrow_swappable_v<value_type>)
898 {
899 if (this->has_value() == __opt.has_value())
900 {
901 using _VSTD::swap;
902 if (this->has_value())
903 swap(this->__get(), __opt.__get());
904 }
905 else
906 {
907 if (this->has_value())
908 {
909 __opt.__construct(_VSTD::move(this->__get()));
910 reset();
911 }
912 else
913 {
914 this->__construct(_VSTD::move(__opt.__get()));
915 __opt.reset();
916 }
917 }
918 }
919
920 _LIBCPP_INLINE_VISIBILITY
921 constexpr
922 add_pointer_t<value_type const>
923 operator->() const
924 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200925 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000926 return _VSTD::addressof(this->__get());
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000927 }
928
929 _LIBCPP_INLINE_VISIBILITY
930 constexpr
931 add_pointer_t<value_type>
932 operator->()
933 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200934 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000935 return _VSTD::addressof(this->__get());
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000936 }
937
938 _LIBCPP_INLINE_VISIBILITY
939 constexpr
940 const value_type&
zoecarver73efa752021-07-01 10:18:27 -0700941 operator*() const& noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000942 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200943 _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000944 return this->__get();
945 }
946
947 _LIBCPP_INLINE_VISIBILITY
948 constexpr
949 value_type&
zoecarver73efa752021-07-01 10:18:27 -0700950 operator*() & noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000951 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200952 _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000953 return this->__get();
954 }
955
956 _LIBCPP_INLINE_VISIBILITY
957 constexpr
958 value_type&&
zoecarver73efa752021-07-01 10:18:27 -0700959 operator*() && noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000960 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200961 _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000962 return _VSTD::move(this->__get());
963 }
964
965 _LIBCPP_INLINE_VISIBILITY
966 constexpr
967 const value_type&&
zoecarver73efa752021-07-01 10:18:27 -0700968 operator*() const&& noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000969 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200970 _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000971 return _VSTD::move(this->__get());
972 }
973
974 _LIBCPP_INLINE_VISIBILITY
975 constexpr explicit operator bool() const noexcept { return has_value(); }
976
977 using __base::has_value;
978 using __base::__get;
979
980 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000981 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000982 constexpr value_type const& value() const&
983 {
984 if (!this->has_value())
985 __throw_bad_optional_access();
986 return this->__get();
987 }
988
989 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000990 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000991 constexpr value_type& value() &
992 {
993 if (!this->has_value())
994 __throw_bad_optional_access();
995 return this->__get();
996 }
997
998 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000999 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001000 constexpr value_type&& value() &&
1001 {
1002 if (!this->has_value())
1003 __throw_bad_optional_access();
1004 return _VSTD::move(this->__get());
1005 }
1006
1007 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +00001008 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001009 constexpr value_type const&& value() const&&
1010 {
1011 if (!this->has_value())
1012 __throw_bad_optional_access();
1013 return _VSTD::move(this->__get());
1014 }
1015
1016 template <class _Up>
1017 _LIBCPP_INLINE_VISIBILITY
1018 constexpr value_type value_or(_Up&& __v) const&
1019 {
1020 static_assert(is_copy_constructible_v<value_type>,
1021 "optional<T>::value_or: T must be copy constructible");
1022 static_assert(is_convertible_v<_Up, value_type>,
1023 "optional<T>::value_or: U must be convertible to T");
1024 return this->has_value() ? this->__get() :
1025 static_cast<value_type>(_VSTD::forward<_Up>(__v));
1026 }
1027
1028 template <class _Up>
1029 _LIBCPP_INLINE_VISIBILITY
Casey Cartercb05fae2017-06-06 18:47:26 +00001030 constexpr value_type value_or(_Up&& __v) &&
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001031 {
1032 static_assert(is_move_constructible_v<value_type>,
1033 "optional<T>::value_or: T must be move constructible");
1034 static_assert(is_convertible_v<_Up, value_type>,
1035 "optional<T>::value_or: U must be convertible to T");
1036 return this->has_value() ? _VSTD::move(this->__get()) :
1037 static_cast<value_type>(_VSTD::forward<_Up>(__v));
1038 }
1039
Nikolas Klauserf6c419a2021-12-15 20:54:24 +01001040#if _LIBCPP_STD_VER > 20
1041 template<class _Func>
1042 _LIBCPP_HIDE_FROM_ABI
1043 constexpr auto and_then(_Func&& __f) & {
1044 using _Up = invoke_result_t<_Func, value_type&>;
1045 static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
1046 "Result of f(value()) must be a specialization of std::optional");
1047 if (*this)
1048 return _VSTD::invoke(_VSTD::forward<_Func>(__f), value());
1049 return remove_cvref_t<_Up>();
1050 }
1051
1052 template<class _Func>
1053 _LIBCPP_HIDE_FROM_ABI
1054 constexpr auto and_then(_Func&& __f) const& {
1055 using _Up = invoke_result_t<_Func, const value_type&>;
1056 static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
1057 "Result of f(value()) must be a specialization of std::optional");
1058 if (*this)
1059 return _VSTD::invoke(_VSTD::forward<_Func>(__f), value());
1060 return remove_cvref_t<_Up>();
1061 }
1062
1063 template<class _Func>
1064 _LIBCPP_HIDE_FROM_ABI
1065 constexpr auto and_then(_Func&& __f) && {
1066 using _Up = invoke_result_t<_Func, value_type&&>;
1067 static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
1068 "Result of f(std::move(value())) must be a specialization of std::optional");
1069 if (*this)
1070 return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value()));
1071 return remove_cvref_t<_Up>();
1072 }
1073
1074 template<class _Func>
1075 _LIBCPP_HIDE_FROM_ABI
1076 constexpr auto and_then(_Func&& __f) const&& {
1077 using _Up = invoke_result_t<_Func, const value_type&&>;
1078 static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
1079 "Result of f(std::move(value())) must be a specialization of std::optional");
1080 if (*this)
1081 return _VSTD::invoke(_VSTD::forward<_Func>(__f), _VSTD::move(value()));
1082 return remove_cvref_t<_Up>();
1083 }
1084
1085 template<class _Func>
1086 _LIBCPP_HIDE_FROM_ABI
1087 constexpr auto transform(_Func&& __f) & {
1088 using _Up = remove_cv_t<invoke_result_t<_Func, value_type&>>;
1089 static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
1090 static_assert(!is_same_v<_Up, in_place_t>,
1091 "Result of f(value()) should not be std::in_place_t");
1092 static_assert(!is_same_v<_Up, nullopt_t>,
1093 "Result of f(value()) should not be std::nullopt_t");
1094 static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
1095 if (*this)
1096 return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value());
1097 return optional<_Up>();
1098 }
1099
1100 template<class _Func>
1101 _LIBCPP_HIDE_FROM_ABI
1102 constexpr auto transform(_Func&& __f) const& {
1103 using _Up = remove_cv_t<invoke_result_t<_Func, const value_type&>>;
1104 static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
1105 static_assert(!is_same_v<_Up, in_place_t>,
1106 "Result of f(value()) should not be std::in_place_t");
1107 static_assert(!is_same_v<_Up, nullopt_t>,
1108 "Result of f(value()) should not be std::nullopt_t");
1109 static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
1110 if (*this)
1111 return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), value());
1112 return optional<_Up>();
1113 }
1114
1115 template<class _Func>
1116 _LIBCPP_HIDE_FROM_ABI
1117 constexpr auto transform(_Func&& __f) && {
1118 using _Up = remove_cv_t<invoke_result_t<_Func, value_type&&>>;
1119 static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
1120 static_assert(!is_same_v<_Up, in_place_t>,
1121 "Result of f(std::move(value())) should not be std::in_place_t");
1122 static_assert(!is_same_v<_Up, nullopt_t>,
1123 "Result of f(std::move(value())) should not be std::nullopt_t");
1124 static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
1125 if (*this)
1126 return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value()));
1127 return optional<_Up>();
1128 }
1129
1130 template<class _Func>
1131 _LIBCPP_HIDE_FROM_ABI
1132 constexpr auto transform(_Func&& __f) const&& {
1133 using _Up = remove_cvref_t<invoke_result_t<_Func, const value_type&&>>;
1134 static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
1135 static_assert(!is_same_v<_Up, in_place_t>,
1136 "Result of f(std::move(value())) should not be std::in_place_t");
1137 static_assert(!is_same_v<_Up, nullopt_t>,
1138 "Result of f(std::move(value())) should not be std::nullopt_t");
1139 static_assert(is_object_v<_Up>, "Result of f(std::move(value())) should be an object type");
1140 if (*this)
1141 return optional<_Up>(__optional_construct_from_invoke_tag{}, _VSTD::forward<_Func>(__f), _VSTD::move(value()));
1142 return optional<_Up>();
1143 }
1144
1145 template<invocable _Func>
1146 _LIBCPP_HIDE_FROM_ABI
1147 constexpr optional or_else(_Func&& __f) const& requires is_copy_constructible_v<value_type> {
1148 static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
1149 "Result of f() should be the same type as this optional");
1150 if (*this)
1151 return *this;
1152 return _VSTD::forward<_Func>(__f)();
1153 }
1154
1155 template<invocable _Func>
1156 _LIBCPP_HIDE_FROM_ABI
1157 constexpr optional or_else(_Func&& __f) && requires is_move_constructible_v<value_type> {
1158 static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
1159 "Result of f() should be the same type as this optional");
1160 if (*this)
1161 return _VSTD::move(*this);
1162 return _VSTD::forward<_Func>(__f)();
1163 }
1164#endif // _LIBCPP_STD_VER > 20
1165
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001166 using __base::reset;
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001167};
1168
Louis Dionned59f8a52021-08-17 11:59:07 -04001169#if _LIBCPP_STD_VER >= 17
Arthur O'Dwyerbef95c72022-01-10 12:00:10 -05001170template<class _Tp>
1171 optional(_Tp) -> optional<_Tp>;
Marshall Clowe3c71ae2018-05-25 02:08:49 +00001172#endif
1173
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001174// Comparisons between optionals
Eric Fiselier8af90142017-03-30 20:06:52 +00001175template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001176_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001177enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001178 is_convertible_v<decltype(declval<const _Tp&>() ==
1179 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001180 bool
1181>
Eric Fiselier8af90142017-03-30 20:06:52 +00001182operator==(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001183{
1184 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1185 return false;
1186 if (!static_cast<bool>(__x))
1187 return true;
1188 return *__x == *__y;
1189}
1190
Eric Fiselier8af90142017-03-30 20:06:52 +00001191template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001192_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001193enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001194 is_convertible_v<decltype(declval<const _Tp&>() !=
1195 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001196 bool
1197>
Eric Fiselier8af90142017-03-30 20:06:52 +00001198operator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001199{
1200 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1201 return true;
1202 if (!static_cast<bool>(__x))
1203 return false;
1204 return *__x != *__y;
1205}
1206
Eric Fiselier8af90142017-03-30 20:06:52 +00001207template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001208_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001209enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001210 is_convertible_v<decltype(declval<const _Tp&>() <
1211 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001212 bool
1213>
Eric Fiselier8af90142017-03-30 20:06:52 +00001214operator<(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001215{
1216 if (!static_cast<bool>(__y))
1217 return false;
1218 if (!static_cast<bool>(__x))
1219 return true;
1220 return *__x < *__y;
1221}
1222
Eric Fiselier8af90142017-03-30 20:06:52 +00001223template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001224_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001225enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001226 is_convertible_v<decltype(declval<const _Tp&>() >
1227 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001228 bool
1229>
Eric Fiselier8af90142017-03-30 20:06:52 +00001230operator>(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001231{
1232 if (!static_cast<bool>(__x))
1233 return false;
1234 if (!static_cast<bool>(__y))
1235 return true;
1236 return *__x > *__y;
1237}
1238
Eric Fiselier8af90142017-03-30 20:06:52 +00001239template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001240_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001241enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001242 is_convertible_v<decltype(declval<const _Tp&>() <=
1243 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001244 bool
1245>
Eric Fiselier8af90142017-03-30 20:06:52 +00001246operator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001247{
1248 if (!static_cast<bool>(__x))
1249 return true;
1250 if (!static_cast<bool>(__y))
1251 return false;
1252 return *__x <= *__y;
1253}
1254
Eric Fiselier8af90142017-03-30 20:06:52 +00001255template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001256_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001257enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001258 is_convertible_v<decltype(declval<const _Tp&>() >=
1259 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001260 bool
1261>
Eric Fiselier8af90142017-03-30 20:06:52 +00001262operator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001263{
1264 if (!static_cast<bool>(__y))
1265 return true;
1266 if (!static_cast<bool>(__x))
1267 return false;
1268 return *__x >= *__y;
1269}
1270
1271// Comparisons with nullopt
1272template <class _Tp>
1273_LIBCPP_INLINE_VISIBILITY constexpr
1274bool
1275operator==(const optional<_Tp>& __x, nullopt_t) noexcept
1276{
1277 return !static_cast<bool>(__x);
1278}
1279
1280template <class _Tp>
1281_LIBCPP_INLINE_VISIBILITY constexpr
1282bool
1283operator==(nullopt_t, const optional<_Tp>& __x) noexcept
1284{
1285 return !static_cast<bool>(__x);
1286}
1287
1288template <class _Tp>
1289_LIBCPP_INLINE_VISIBILITY constexpr
1290bool
1291operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
1292{
1293 return static_cast<bool>(__x);
1294}
1295
1296template <class _Tp>
1297_LIBCPP_INLINE_VISIBILITY constexpr
1298bool
1299operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
1300{
1301 return static_cast<bool>(__x);
1302}
1303
1304template <class _Tp>
1305_LIBCPP_INLINE_VISIBILITY constexpr
1306bool
1307operator<(const optional<_Tp>&, nullopt_t) noexcept
1308{
1309 return false;
1310}
1311
1312template <class _Tp>
1313_LIBCPP_INLINE_VISIBILITY constexpr
1314bool
1315operator<(nullopt_t, const optional<_Tp>& __x) noexcept
1316{
1317 return static_cast<bool>(__x);
1318}
1319
1320template <class _Tp>
1321_LIBCPP_INLINE_VISIBILITY constexpr
1322bool
1323operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
1324{
1325 return !static_cast<bool>(__x);
1326}
1327
1328template <class _Tp>
1329_LIBCPP_INLINE_VISIBILITY constexpr
1330bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001331operator<=(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001332{
1333 return true;
1334}
1335
1336template <class _Tp>
1337_LIBCPP_INLINE_VISIBILITY constexpr
1338bool
1339operator>(const optional<_Tp>& __x, nullopt_t) noexcept
1340{
1341 return static_cast<bool>(__x);
1342}
1343
1344template <class _Tp>
1345_LIBCPP_INLINE_VISIBILITY constexpr
1346bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001347operator>(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001348{
1349 return false;
1350}
1351
1352template <class _Tp>
1353_LIBCPP_INLINE_VISIBILITY constexpr
1354bool
1355operator>=(const optional<_Tp>&, nullopt_t) noexcept
1356{
1357 return true;
1358}
1359
1360template <class _Tp>
1361_LIBCPP_INLINE_VISIBILITY constexpr
1362bool
1363operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1364{
1365 return !static_cast<bool>(__x);
1366}
1367
1368// Comparisons with T
Eric Fiselier8af90142017-03-30 20:06:52 +00001369template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001370_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001371enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001372 is_convertible_v<decltype(declval<const _Tp&>() ==
1373 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001374 bool
1375>
Eric Fiselier8af90142017-03-30 20:06:52 +00001376operator==(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001377{
1378 return static_cast<bool>(__x) ? *__x == __v : false;
1379}
1380
Eric Fiselier8af90142017-03-30 20:06:52 +00001381template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001382_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001383enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001384 is_convertible_v<decltype(declval<const _Tp&>() ==
1385 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001386 bool
1387>
Eric Fiselier8af90142017-03-30 20:06:52 +00001388operator==(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001389{
1390 return static_cast<bool>(__x) ? __v == *__x : false;
1391}
1392
Eric Fiselier8af90142017-03-30 20:06:52 +00001393template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001394_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001395enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001396 is_convertible_v<decltype(declval<const _Tp&>() !=
1397 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001398 bool
1399>
Eric Fiselier8af90142017-03-30 20:06:52 +00001400operator!=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001401{
1402 return static_cast<bool>(__x) ? *__x != __v : true;
1403}
1404
Eric Fiselier8af90142017-03-30 20:06:52 +00001405template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001406_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001407enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001408 is_convertible_v<decltype(declval<const _Tp&>() !=
1409 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001410 bool
1411>
Eric Fiselier8af90142017-03-30 20:06:52 +00001412operator!=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001413{
1414 return static_cast<bool>(__x) ? __v != *__x : true;
1415}
1416
Eric Fiselier8af90142017-03-30 20:06:52 +00001417template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001418_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001419enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001420 is_convertible_v<decltype(declval<const _Tp&>() <
1421 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001422 bool
1423>
Eric Fiselier8af90142017-03-30 20:06:52 +00001424operator<(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001425{
1426 return static_cast<bool>(__x) ? *__x < __v : true;
1427}
1428
Eric Fiselier8af90142017-03-30 20:06:52 +00001429template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001430_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001431enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001432 is_convertible_v<decltype(declval<const _Tp&>() <
1433 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001434 bool
1435>
Eric Fiselier8af90142017-03-30 20:06:52 +00001436operator<(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001437{
1438 return static_cast<bool>(__x) ? __v < *__x : false;
1439}
1440
Eric Fiselier8af90142017-03-30 20:06:52 +00001441template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001442_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001443enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001444 is_convertible_v<decltype(declval<const _Tp&>() <=
1445 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001446 bool
1447>
Eric Fiselier8af90142017-03-30 20:06:52 +00001448operator<=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001449{
1450 return static_cast<bool>(__x) ? *__x <= __v : true;
1451}
1452
Eric Fiselier8af90142017-03-30 20:06:52 +00001453template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001454_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001455enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001456 is_convertible_v<decltype(declval<const _Tp&>() <=
1457 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001458 bool
1459>
Eric Fiselier8af90142017-03-30 20:06:52 +00001460operator<=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001461{
1462 return static_cast<bool>(__x) ? __v <= *__x : false;
1463}
1464
Eric Fiselier8af90142017-03-30 20:06:52 +00001465template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001466_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001467enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001468 is_convertible_v<decltype(declval<const _Tp&>() >
1469 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001470 bool
1471>
Eric Fiselier8af90142017-03-30 20:06:52 +00001472operator>(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001473{
1474 return static_cast<bool>(__x) ? *__x > __v : false;
1475}
1476
Eric Fiselier8af90142017-03-30 20:06:52 +00001477template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001478_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001479enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001480 is_convertible_v<decltype(declval<const _Tp&>() >
1481 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001482 bool
1483>
Eric Fiselier8af90142017-03-30 20:06:52 +00001484operator>(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001485{
1486 return static_cast<bool>(__x) ? __v > *__x : true;
1487}
1488
Eric Fiselier8af90142017-03-30 20:06:52 +00001489template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001490_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001491enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001492 is_convertible_v<decltype(declval<const _Tp&>() >=
1493 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001494 bool
1495>
Eric Fiselier8af90142017-03-30 20:06:52 +00001496operator>=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001497{
1498 return static_cast<bool>(__x) ? *__x >= __v : false;
1499}
1500
Eric Fiselier8af90142017-03-30 20:06:52 +00001501template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001502_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001503enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001504 is_convertible_v<decltype(declval<const _Tp&>() >=
1505 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001506 bool
1507>
Eric Fiselier8af90142017-03-30 20:06:52 +00001508operator>=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001509{
1510 return static_cast<bool>(__x) ? __v >= *__x : true;
1511}
1512
1513
1514template <class _Tp>
Christopher Di Bella80e8f642021-05-09 01:30:32 +00001515inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Louis Dionne25547162021-08-17 12:26:09 -04001516enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001517 is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1518 void
1519>
1520swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1521{
1522 __x.swap(__y);
1523}
1524
1525template <class _Tp>
1526_LIBCPP_INLINE_VISIBILITY constexpr
1527optional<decay_t<_Tp>> make_optional(_Tp&& __v)
1528{
1529 return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1530}
1531
1532template <class _Tp, class... _Args>
1533_LIBCPP_INLINE_VISIBILITY constexpr
1534optional<_Tp> make_optional(_Args&&... __args)
1535{
1536 return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1537}
1538
1539template <class _Tp, class _Up, class... _Args>
1540_LIBCPP_INLINE_VISIBILITY constexpr
1541optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args)
1542{
1543 return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1544}
1545
1546template <class _Tp>
Eric Fiselier698a97b2017-01-21 00:02:12 +00001547struct _LIBCPP_TEMPLATE_VIS hash<
1548 __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1549>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001550{
Arthur O'Dwyerf5486c82021-05-25 14:34:18 -04001551#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
1552 _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type;
1553 _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type;
1554#endif
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001555
1556 _LIBCPP_INLINE_VISIBILITY
Arthur O'Dwyerf5486c82021-05-25 14:34:18 -04001557 size_t operator()(const optional<_Tp>& __opt) const
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001558 {
Eric Fiselier698a97b2017-01-21 00:02:12 +00001559 return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001560 }
1561};
1562
1563_LIBCPP_END_NAMESPACE_STD
1564
Louis Dionne2b1ceaa2021-04-20 12:03:32 -04001565#endif // _LIBCPP_STD_VER > 14
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001566
Louis Dionne2b1ceaa2021-04-20 12:03:32 -04001567#endif // _LIBCPP_OPTIONAL