blob: 118db66a4abc9e990f323bd543d8120f9c035588 [file] [log] [blame]
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001// -*- C++ -*-
2//===-------------------------- optional ----------------------------------===//
3//
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
Casey Carter84b8a402017-04-17 20:15:16 +0000135 // 23.6.3.6, modifiers
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000136 void reset() noexcept; // constexpr in C++20
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000137
138 private:
139 T *val; // exposition only
140 };
Marshall Clowe3c71ae2018-05-25 02:08:49 +0000141
142template<class T>
143 optional(T) -> optional<T>;
144
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000145} // namespace std
146
147*/
148
Louis Dionne73912b22020-11-04 15:01:25 -0500149#include <__availability>
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400150#include <__config>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000151#include <__debug>
152#include <__functional_base>
Arthur O'Dwyer7deec122021-03-24 18:19:12 -0400153#include <compare>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000154#include <functional>
155#include <initializer_list>
156#include <new>
157#include <stdexcept>
158#include <type_traits>
159#include <utility>
Marshall Clow0a1e7502018-09-12 19:41:40 +0000160#include <version>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000161
162#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
163#pragma GCC system_header
164#endif
165
Eric Fiselierf4433a32017-05-31 22:07:49 +0000166_LIBCPP_PUSH_MACROS
167#include <__undef_macros>
168
169
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000170namespace std // purposefully not using versioning namespace
171{
172
Louis Dionnecef92e62018-11-19 15:37:04 +0000173class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
Marshall Clowa627d4a2017-02-05 20:06:38 +0000174 : public exception
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000175{
176public:
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000177 // Get the key function ~bad_optional_access() into the dylib
Marshall Clow53fc0372017-02-05 20:52:32 +0000178 virtual ~bad_optional_access() _NOEXCEPT;
Marshall Clowa627d4a2017-02-05 20:06:38 +0000179 virtual const char* what() const _NOEXCEPT;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000180};
181
182} // std
183
184#if _LIBCPP_STD_VER > 14
185
186_LIBCPP_BEGIN_NAMESPACE_STD
187
188_LIBCPP_NORETURN
189inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000190_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000191void __throw_bad_optional_access() {
192#ifndef _LIBCPP_NO_EXCEPTIONS
193 throw bad_optional_access();
194#else
195 _VSTD::abort();
196#endif
197}
198
199struct nullopt_t
200{
201 struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
202 _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
203};
204
Marshall Clowf1bf62f2018-01-02 17:17:01 +0000205_LIBCPP_INLINE_VAR constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000206
207template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
208struct __optional_destruct_base;
209
210template <class _Tp>
211struct __optional_destruct_base<_Tp, false>
212{
213 typedef _Tp value_type;
214 static_assert(is_object_v<value_type>,
215 "instantiation of optional with a non-object type is undefined behavior");
216 union
217 {
218 char __null_state_;
219 value_type __val_;
220 };
221 bool __engaged_;
222
223 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000224 _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__optional_destruct_base()
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000225 {
226 if (__engaged_)
227 __val_.~value_type();
228 }
229
230 _LIBCPP_INLINE_VISIBILITY
231 constexpr __optional_destruct_base() noexcept
232 : __null_state_(),
233 __engaged_(false) {}
234
235 template <class... _Args>
236 _LIBCPP_INLINE_VISIBILITY
237 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
238 : __val_(_VSTD::forward<_Args>(__args)...),
239 __engaged_(true) {}
240
241 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000242 _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000243 {
244 if (__engaged_)
245 {
246 __val_.~value_type();
247 __engaged_ = false;
248 }
249 }
250};
251
252template <class _Tp>
253struct __optional_destruct_base<_Tp, true>
254{
255 typedef _Tp value_type;
256 static_assert(is_object_v<value_type>,
257 "instantiation of optional with a non-object type is undefined behavior");
258 union
259 {
260 char __null_state_;
261 value_type __val_;
262 };
263 bool __engaged_;
264
265 _LIBCPP_INLINE_VISIBILITY
266 constexpr __optional_destruct_base() noexcept
267 : __null_state_(),
268 __engaged_(false) {}
269
270 template <class... _Args>
271 _LIBCPP_INLINE_VISIBILITY
272 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
273 : __val_(_VSTD::forward<_Args>(__args)...),
274 __engaged_(true) {}
275
276 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000277 _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000278 {
279 if (__engaged_)
280 {
281 __engaged_ = false;
282 }
283 }
284};
285
286template <class _Tp, bool = is_reference<_Tp>::value>
287struct __optional_storage_base : __optional_destruct_base<_Tp>
288{
289 using __base = __optional_destruct_base<_Tp>;
290 using value_type = _Tp;
291 using __base::__base;
292
293 _LIBCPP_INLINE_VISIBILITY
294 constexpr bool has_value() const noexcept
295 {
296 return this->__engaged_;
297 }
298
299 _LIBCPP_INLINE_VISIBILITY
300 constexpr value_type& __get() & noexcept
301 {
302 return this->__val_;
303 }
304 _LIBCPP_INLINE_VISIBILITY
305 constexpr const value_type& __get() const& noexcept
306 {
307 return this->__val_;
308 }
309 _LIBCPP_INLINE_VISIBILITY
310 constexpr value_type&& __get() && noexcept
311 {
312 return _VSTD::move(this->__val_);
313 }
314 _LIBCPP_INLINE_VISIBILITY
315 constexpr const value_type&& __get() const&& noexcept
316 {
317 return _VSTD::move(this->__val_);
318 }
319
320 template <class... _Args>
321 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000322 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_Args&&... __args)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000323 {
324 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000325#if _LIBCPP_STD_VER > 17
326 _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...);
327#else
Arthur O'Dwyer0c4472a2020-12-11 20:30:28 -0500328 ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000329#endif
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000330 this->__engaged_ = true;
331 }
332
333 template <class _That>
334 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000335 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000336 {
337 if (__opt.has_value())
338 __construct(_VSTD::forward<_That>(__opt).__get());
339 }
340
341 template <class _That>
342 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000343 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000344 {
345 if (this->__engaged_ == __opt.has_value())
346 {
347 if (this->__engaged_)
348 this->__val_ = _VSTD::forward<_That>(__opt).__get();
349 }
350 else
351 {
352 if (this->__engaged_)
353 this->reset();
354 else
355 __construct(_VSTD::forward<_That>(__opt).__get());
356 }
357 }
358};
359
360// optional<T&> is currently required ill-formed, however it may to be in the
361// future. For this reason it has already been implemented to ensure we can
362// make the change in an ABI compatible manner.
363template <class _Tp>
364struct __optional_storage_base<_Tp, true>
365{
366 using value_type = _Tp;
367 using __raw_type = remove_reference_t<_Tp>;
368 __raw_type* __value_;
369
370 template <class _Up>
371 static constexpr bool __can_bind_reference() {
372 using _RawUp = typename remove_reference<_Up>::type;
373 using _UpPtr = _RawUp*;
374 using _RawTp = typename remove_reference<_Tp>::type;
375 using _TpPtr = _RawTp*;
376 using _CheckLValueArg = integral_constant<bool,
377 (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
378 || is_same<_RawUp, reference_wrapper<_RawTp>>::value
379 || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
380 >;
381 return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
382 || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
383 is_convertible<_UpPtr, _TpPtr>::value);
384 }
385
386 _LIBCPP_INLINE_VISIBILITY
387 constexpr __optional_storage_base() noexcept
388 : __value_(nullptr) {}
389
390 template <class _UArg>
391 _LIBCPP_INLINE_VISIBILITY
392 constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
393 : __value_(_VSTD::addressof(__uarg))
394 {
395 static_assert(__can_bind_reference<_UArg>(),
396 "Attempted to construct a reference element in tuple from a "
397 "possible temporary");
398 }
399
400 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000401 _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept { __value_ = nullptr; }
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000402
403 _LIBCPP_INLINE_VISIBILITY
404 constexpr bool has_value() const noexcept
405 { return __value_ != nullptr; }
406
407 _LIBCPP_INLINE_VISIBILITY
408 constexpr value_type& __get() const& noexcept
409 { return *__value_; }
410
411 _LIBCPP_INLINE_VISIBILITY
412 constexpr value_type&& __get() const&& noexcept
413 { return _VSTD::forward<value_type>(*__value_); }
414
415 template <class _UArg>
416 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000417 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_UArg&& __val)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000418 {
419 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
420 static_assert(__can_bind_reference<_UArg>(),
421 "Attempted to construct a reference element in tuple from a "
422 "possible temporary");
423 __value_ = _VSTD::addressof(__val);
424 }
425
426 template <class _That>
427 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000428 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000429 {
430 if (__opt.has_value())
431 __construct(_VSTD::forward<_That>(__opt).__get());
432 }
433
434 template <class _That>
435 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000436 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000437 {
438 if (has_value() == __opt.has_value())
439 {
440 if (has_value())
441 *__value_ = _VSTD::forward<_That>(__opt).__get();
442 }
443 else
444 {
445 if (has_value())
446 reset();
447 else
448 __construct(_VSTD::forward<_That>(__opt).__get());
449 }
450 }
451};
452
Casey Carterc189f7f2017-07-09 17:15:49 +0000453template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
454struct __optional_copy_base : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000455{
456 using __optional_storage_base<_Tp>::__optional_storage_base;
457};
458
459template <class _Tp>
Casey Carterc189f7f2017-07-09 17:15:49 +0000460struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000461{
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000462 using __optional_storage_base<_Tp>::__optional_storage_base;
463
464 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000465 __optional_copy_base() = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000466
467 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000468 _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_base(const __optional_copy_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000469 {
470 this->__construct_from(__opt);
471 }
472
473 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000474 __optional_copy_base(__optional_copy_base&&) = default;
475 _LIBCPP_INLINE_VISIBILITY
476 __optional_copy_base& operator=(const __optional_copy_base&) = default;
477 _LIBCPP_INLINE_VISIBILITY
478 __optional_copy_base& operator=(__optional_copy_base&&) = default;
479};
480
481template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
482struct __optional_move_base : __optional_copy_base<_Tp>
483{
484 using __optional_copy_base<_Tp>::__optional_copy_base;
485};
486
487template <class _Tp>
488struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
489{
490 using value_type = _Tp;
491 using __optional_copy_base<_Tp>::__optional_copy_base;
492
493 _LIBCPP_INLINE_VISIBILITY
494 __optional_move_base() = default;
495 _LIBCPP_INLINE_VISIBILITY
496 __optional_move_base(const __optional_move_base&) = default;
497
498 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000499 _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_base(__optional_move_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000500 noexcept(is_nothrow_move_constructible_v<value_type>)
501 {
502 this->__construct_from(_VSTD::move(__opt));
503 }
504
505 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000506 __optional_move_base& operator=(const __optional_move_base&) = default;
507 _LIBCPP_INLINE_VISIBILITY
508 __optional_move_base& operator=(__optional_move_base&&) = default;
509};
510
511template <class _Tp, bool =
512 is_trivially_destructible<_Tp>::value &&
513 is_trivially_copy_constructible<_Tp>::value &&
514 is_trivially_copy_assignable<_Tp>::value>
515struct __optional_copy_assign_base : __optional_move_base<_Tp>
516{
517 using __optional_move_base<_Tp>::__optional_move_base;
518};
519
520template <class _Tp>
521struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
522{
523 using __optional_move_base<_Tp>::__optional_move_base;
524
525 _LIBCPP_INLINE_VISIBILITY
526 __optional_copy_assign_base() = default;
527 _LIBCPP_INLINE_VISIBILITY
528 __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
529 _LIBCPP_INLINE_VISIBILITY
530 __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
531
532 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000533 _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000534 {
535 this->__assign_from(__opt);
536 return *this;
537 }
538
539 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000540 __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
541};
542
543template <class _Tp, bool =
544 is_trivially_destructible<_Tp>::value &&
545 is_trivially_move_constructible<_Tp>::value &&
546 is_trivially_move_assignable<_Tp>::value>
547struct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
548{
549 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
550};
551
552template <class _Tp>
553struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
554{
555 using value_type = _Tp;
556 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
557
558 _LIBCPP_INLINE_VISIBILITY
559 __optional_move_assign_base() = default;
560 _LIBCPP_INLINE_VISIBILITY
561 __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
562 _LIBCPP_INLINE_VISIBILITY
563 __optional_move_assign_base(__optional_move_assign_base&&) = default;
564 _LIBCPP_INLINE_VISIBILITY
565 __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
566
567 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000568 _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000569 noexcept(is_nothrow_move_assignable_v<value_type> &&
570 is_nothrow_move_constructible_v<value_type>)
571 {
572 this->__assign_from(_VSTD::move(__opt));
573 return *this;
574 }
575};
576
577template <class _Tp>
578using __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
579 is_copy_constructible<_Tp>::value,
580 is_move_constructible<_Tp>::value
581>;
582
583template <class _Tp>
584using __optional_sfinae_assign_base_t = __sfinae_assign_base<
585 (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
586 (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
587>;
588
589template <class _Tp>
590class optional
Casey Carterc189f7f2017-07-09 17:15:49 +0000591 : private __optional_move_assign_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000592 , private __optional_sfinae_ctor_base_t<_Tp>
593 , private __optional_sfinae_assign_base_t<_Tp>
594{
Casey Carterc189f7f2017-07-09 17:15:49 +0000595 using __base = __optional_move_assign_base<_Tp>;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000596public:
597 using value_type = _Tp;
598
599private:
600 // Disable the reference extension using this static assert.
Marshall Clowfa6a3342019-03-25 16:35:59 +0000601 static_assert(!is_same_v<__uncvref_t<value_type>, in_place_t>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000602 "instantiation of optional with in_place_t is ill-formed");
603 static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
604 "instantiation of optional with nullopt_t is ill-formed");
605 static_assert(!is_reference_v<value_type>,
606 "instantiation of optional with a reference type is ill-formed");
607 static_assert(is_destructible_v<value_type>,
608 "instantiation of optional with a non-destructible type is ill-formed");
Marshall Clowfa6a3342019-03-25 16:35:59 +0000609 static_assert(!is_array_v<value_type>,
610 "instantiation of optional with an array type is ill-formed");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000611
612 // LWG2756: conditionally explicit conversion from _Up
613 struct _CheckOptionalArgsConstructor {
614 template <class _Up>
615 static constexpr bool __enable_implicit() {
616 return is_constructible_v<_Tp, _Up&&> &&
617 is_convertible_v<_Up&&, _Tp>;
618 }
619
620 template <class _Up>
621 static constexpr bool __enable_explicit() {
622 return is_constructible_v<_Tp, _Up&&> &&
623 !is_convertible_v<_Up&&, _Tp>;
624 }
625 };
626 template <class _Up>
Eric Fiselier3906a132019-06-23 20:28:29 +0000627 using _CheckOptionalArgsCtor = _If<
628 _IsNotSame<__uncvref_t<_Up>, in_place_t>::value &&
629 _IsNotSame<__uncvref_t<_Up>, optional>::value,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000630 _CheckOptionalArgsConstructor,
631 __check_tuple_constructor_fail
632 >;
633 template <class _QualUp>
634 struct _CheckOptionalLikeConstructor {
635 template <class _Up, class _Opt = optional<_Up>>
Eric Fiselier3906a132019-06-23 20:28:29 +0000636 using __check_constructible_from_opt = _Or<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000637 is_constructible<_Tp, _Opt&>,
638 is_constructible<_Tp, _Opt const&>,
639 is_constructible<_Tp, _Opt&&>,
640 is_constructible<_Tp, _Opt const&&>,
641 is_convertible<_Opt&, _Tp>,
642 is_convertible<_Opt const&, _Tp>,
643 is_convertible<_Opt&&, _Tp>,
644 is_convertible<_Opt const&&, _Tp>
645 >;
646 template <class _Up, class _Opt = optional<_Up>>
Eric Fiselier3906a132019-06-23 20:28:29 +0000647 using __check_assignable_from_opt = _Or<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000648 is_assignable<_Tp&, _Opt&>,
649 is_assignable<_Tp&, _Opt const&>,
650 is_assignable<_Tp&, _Opt&&>,
651 is_assignable<_Tp&, _Opt const&&>
652 >;
653 template <class _Up, class _QUp = _QualUp>
654 static constexpr bool __enable_implicit() {
655 return is_convertible<_QUp, _Tp>::value &&
656 !__check_constructible_from_opt<_Up>::value;
657 }
658 template <class _Up, class _QUp = _QualUp>
659 static constexpr bool __enable_explicit() {
660 return !is_convertible<_QUp, _Tp>::value &&
661 !__check_constructible_from_opt<_Up>::value;
662 }
663 template <class _Up, class _QUp = _QualUp>
664 static constexpr bool __enable_assign() {
Arthur O'Dwyerdf5df562020-12-12 11:57:32 -0500665 // Construction and assignability of _QUp to _Tp has already been
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000666 // checked.
667 return !__check_constructible_from_opt<_Up>::value &&
668 !__check_assignable_from_opt<_Up>::value;
669 }
670 };
671
672 template <class _Up, class _QualUp>
Eric Fiselier3906a132019-06-23 20:28:29 +0000673 using _CheckOptionalLikeCtor = _If<
674 _And<
675 _IsNotSame<_Up, _Tp>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000676 is_constructible<_Tp, _QualUp>
677 >::value,
678 _CheckOptionalLikeConstructor<_QualUp>,
679 __check_tuple_constructor_fail
680 >;
681 template <class _Up, class _QualUp>
Eric Fiselier3906a132019-06-23 20:28:29 +0000682 using _CheckOptionalLikeAssign = _If<
683 _And<
684 _IsNotSame<_Up, _Tp>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000685 is_constructible<_Tp, _QualUp>,
686 is_assignable<_Tp&, _QualUp>
687 >::value,
688 _CheckOptionalLikeConstructor<_QualUp>,
689 __check_tuple_constructor_fail
690 >;
691public:
692
693 _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
Marshall Clowd44e2e32017-05-17 15:30:01 +0000694 _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
695 _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000696 _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
697
Eric Fiselier3906a132019-06-23 20:28:29 +0000698 template <class _InPlaceT, class... _Args, class = _EnableIf<
699 _And<
700 _IsSame<_InPlaceT, in_place_t>,
701 is_constructible<value_type, _Args...>
Eric Fiselier82103932019-03-11 22:55:21 +0000702 >::value
703 >
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000704 >
705 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier82103932019-03-11 22:55:21 +0000706 constexpr explicit optional(_InPlaceT, _Args&&... __args)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000707 : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
708
Eric Fiselier3906a132019-06-23 20:28:29 +0000709 template <class _Up, class... _Args, class = _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000710 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
711 >
712 _LIBCPP_INLINE_VISIBILITY
713 constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
714 : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
715
Eric Fiselier3906a132019-06-23 20:28:29 +0000716 template <class _Up = value_type, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000717 _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
718 , int> = 0>
719 _LIBCPP_INLINE_VISIBILITY
720 constexpr optional(_Up&& __v)
721 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
722
Eric Fiselier3906a132019-06-23 20:28:29 +0000723 template <class _Up, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000724 _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
725 , int> = 0>
726 _LIBCPP_INLINE_VISIBILITY
727 constexpr explicit optional(_Up&& __v)
728 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
729
730 // LWG2756: conditionally explicit conversion from const optional<_Up>&
Eric Fiselier3906a132019-06-23 20:28:29 +0000731 template <class _Up, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000732 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
733 , int> = 0>
734 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000735 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(const optional<_Up>& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000736 {
737 this->__construct_from(__v);
738 }
Eric Fiselier3906a132019-06-23 20:28:29 +0000739 template <class _Up, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000740 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
741 , int> = 0>
742 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000743 _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(const optional<_Up>& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000744 {
745 this->__construct_from(__v);
746 }
747
748 // LWG2756: conditionally explicit conversion from optional<_Up>&&
Eric Fiselier3906a132019-06-23 20:28:29 +0000749 template <class _Up, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000750 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
751 , int> = 0>
752 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000753 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(optional<_Up>&& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000754 {
755 this->__construct_from(_VSTD::move(__v));
756 }
Eric Fiselier3906a132019-06-23 20:28:29 +0000757 template <class _Up, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000758 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
759 , int> = 0>
760 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000761 _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(optional<_Up>&& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000762 {
763 this->__construct_from(_VSTD::move(__v));
764 }
765
766 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000767 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& operator=(nullopt_t) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000768 {
769 reset();
770 return *this;
771 }
772
773 _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
774 _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
775
776 // LWG2756
777 template <class _Up = value_type,
Eric Fiselier3906a132019-06-23 20:28:29 +0000778 class = _EnableIf<
779 _And<
780 _IsNotSame<__uncvref_t<_Up>, optional>,
781 _Or<
Marshall Clow99315112019-06-27 18:40:55 +0000782 _IsNotSame<__uncvref_t<_Up>, value_type>,
Eric Fiselier3906a132019-06-23 20:28:29 +0000783 _Not<is_scalar<value_type>>
Eric Fiselierb9014262016-10-16 03:21:35 +0000784 >,
785 is_constructible<value_type, _Up>,
786 is_assignable<value_type&, _Up>
787 >::value>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000788 >
789 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000790 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000791 operator=(_Up&& __v)
792 {
793 if (this->has_value())
794 this->__get() = _VSTD::forward<_Up>(__v);
795 else
796 this->__construct(_VSTD::forward<_Up>(__v));
797 return *this;
798 }
799
800 // LWG2756
Eric Fiselier3906a132019-06-23 20:28:29 +0000801 template <class _Up, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000802 _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
803 , int> = 0>
804 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000805 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000806 operator=(const optional<_Up>& __v)
807 {
808 this->__assign_from(__v);
809 return *this;
810 }
811
812 // LWG2756
Eric Fiselier3906a132019-06-23 20:28:29 +0000813 template <class _Up, _EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000814 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
815 , int> = 0>
816 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000817 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000818 operator=(optional<_Up>&& __v)
819 {
820 this->__assign_from(_VSTD::move(__v));
821 return *this;
822 }
823
824 template <class... _Args,
Eric Fiselier3906a132019-06-23 20:28:29 +0000825 class = _EnableIf
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000826 <
827 is_constructible_v<value_type, _Args...>
828 >
829 >
830 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000831 _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000832 emplace(_Args&&... __args)
833 {
834 reset();
835 this->__construct(_VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000836 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000837 }
838
839 template <class _Up, class... _Args,
Eric Fiselier3906a132019-06-23 20:28:29 +0000840 class = _EnableIf
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000841 <
842 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
843 >
844 >
845 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000846 _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000847 emplace(initializer_list<_Up> __il, _Args&&... __args)
848 {
849 reset();
850 this->__construct(__il, _VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000851 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000852 }
853
854 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000855 _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(optional& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000856 noexcept(is_nothrow_move_constructible_v<value_type> &&
857 is_nothrow_swappable_v<value_type>)
858 {
859 if (this->has_value() == __opt.has_value())
860 {
861 using _VSTD::swap;
862 if (this->has_value())
863 swap(this->__get(), __opt.__get());
864 }
865 else
866 {
867 if (this->has_value())
868 {
869 __opt.__construct(_VSTD::move(this->__get()));
870 reset();
871 }
872 else
873 {
874 this->__construct(_VSTD::move(__opt.__get()));
875 __opt.reset();
876 }
877 }
878 }
879
880 _LIBCPP_INLINE_VISIBILITY
881 constexpr
882 add_pointer_t<value_type const>
883 operator->() const
884 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200885 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000886#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
887 return _VSTD::addressof(this->__get());
888#else
889 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
890#endif
891 }
892
893 _LIBCPP_INLINE_VISIBILITY
894 constexpr
895 add_pointer_t<value_type>
896 operator->()
897 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200898 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000899#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
900 return _VSTD::addressof(this->__get());
901#else
902 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
903#endif
904 }
905
906 _LIBCPP_INLINE_VISIBILITY
907 constexpr
908 const value_type&
zoecarver73efa752021-07-01 10:18:27 -0700909 operator*() const& noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000910 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200911 _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000912 return this->__get();
913 }
914
915 _LIBCPP_INLINE_VISIBILITY
916 constexpr
917 value_type&
zoecarver73efa752021-07-01 10:18:27 -0700918 operator*() & noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000919 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200920 _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000921 return this->__get();
922 }
923
924 _LIBCPP_INLINE_VISIBILITY
925 constexpr
926 value_type&&
zoecarver73efa752021-07-01 10:18:27 -0700927 operator*() && noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000928 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200929 _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000930 return _VSTD::move(this->__get());
931 }
932
933 _LIBCPP_INLINE_VISIBILITY
934 constexpr
935 const value_type&&
zoecarver73efa752021-07-01 10:18:27 -0700936 operator*() const&& noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000937 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200938 _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000939 return _VSTD::move(this->__get());
940 }
941
942 _LIBCPP_INLINE_VISIBILITY
943 constexpr explicit operator bool() const noexcept { return has_value(); }
944
945 using __base::has_value;
946 using __base::__get;
947
948 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000949 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000950 constexpr value_type const& value() const&
951 {
952 if (!this->has_value())
953 __throw_bad_optional_access();
954 return this->__get();
955 }
956
957 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000958 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000959 constexpr value_type& value() &
960 {
961 if (!this->has_value())
962 __throw_bad_optional_access();
963 return this->__get();
964 }
965
966 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000967 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000968 constexpr value_type&& value() &&
969 {
970 if (!this->has_value())
971 __throw_bad_optional_access();
972 return _VSTD::move(this->__get());
973 }
974
975 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000976 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000977 constexpr value_type const&& value() const&&
978 {
979 if (!this->has_value())
980 __throw_bad_optional_access();
981 return _VSTD::move(this->__get());
982 }
983
984 template <class _Up>
985 _LIBCPP_INLINE_VISIBILITY
986 constexpr value_type value_or(_Up&& __v) const&
987 {
988 static_assert(is_copy_constructible_v<value_type>,
989 "optional<T>::value_or: T must be copy constructible");
990 static_assert(is_convertible_v<_Up, value_type>,
991 "optional<T>::value_or: U must be convertible to T");
992 return this->has_value() ? this->__get() :
993 static_cast<value_type>(_VSTD::forward<_Up>(__v));
994 }
995
996 template <class _Up>
997 _LIBCPP_INLINE_VISIBILITY
Casey Cartercb05fae2017-06-06 18:47:26 +0000998 constexpr value_type value_or(_Up&& __v) &&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000999 {
1000 static_assert(is_move_constructible_v<value_type>,
1001 "optional<T>::value_or: T must be move constructible");
1002 static_assert(is_convertible_v<_Up, value_type>,
1003 "optional<T>::value_or: U must be convertible to T");
1004 return this->has_value() ? _VSTD::move(this->__get()) :
1005 static_cast<value_type>(_VSTD::forward<_Up>(__v));
1006 }
1007
1008 using __base::reset;
1009
1010private:
1011 template <class _Up>
1012 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +00001013 static _LIBCPP_CONSTEXPR_AFTER_CXX17 _Up*
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001014 __operator_arrow(true_type, _Up& __x)
1015 {
1016 return _VSTD::addressof(__x);
1017 }
1018
1019 template <class _Up>
1020 _LIBCPP_INLINE_VISIBILITY
1021 static constexpr _Up*
1022 __operator_arrow(false_type, _Up& __x)
1023 {
1024 return &__x;
1025 }
1026};
1027
Marshall Clowe3c71ae2018-05-25 02:08:49 +00001028#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
1029template<class T>
1030 optional(T) -> optional<T>;
1031#endif
1032
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001033// Comparisons between optionals
Eric Fiselier8af90142017-03-30 20:06:52 +00001034template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001035_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001036_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001037 is_convertible_v<decltype(declval<const _Tp&>() ==
1038 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001039 bool
1040>
Eric Fiselier8af90142017-03-30 20:06:52 +00001041operator==(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001042{
1043 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1044 return false;
1045 if (!static_cast<bool>(__x))
1046 return true;
1047 return *__x == *__y;
1048}
1049
Eric Fiselier8af90142017-03-30 20:06:52 +00001050template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001051_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001052_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001053 is_convertible_v<decltype(declval<const _Tp&>() !=
1054 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001055 bool
1056>
Eric Fiselier8af90142017-03-30 20:06:52 +00001057operator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001058{
1059 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1060 return true;
1061 if (!static_cast<bool>(__x))
1062 return false;
1063 return *__x != *__y;
1064}
1065
Eric Fiselier8af90142017-03-30 20:06:52 +00001066template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001067_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001068_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001069 is_convertible_v<decltype(declval<const _Tp&>() <
1070 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001071 bool
1072>
Eric Fiselier8af90142017-03-30 20:06:52 +00001073operator<(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001074{
1075 if (!static_cast<bool>(__y))
1076 return false;
1077 if (!static_cast<bool>(__x))
1078 return true;
1079 return *__x < *__y;
1080}
1081
Eric Fiselier8af90142017-03-30 20:06:52 +00001082template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001083_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001084_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001085 is_convertible_v<decltype(declval<const _Tp&>() >
1086 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001087 bool
1088>
Eric Fiselier8af90142017-03-30 20:06:52 +00001089operator>(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001090{
1091 if (!static_cast<bool>(__x))
1092 return false;
1093 if (!static_cast<bool>(__y))
1094 return true;
1095 return *__x > *__y;
1096}
1097
Eric Fiselier8af90142017-03-30 20:06:52 +00001098template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001099_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001100_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001101 is_convertible_v<decltype(declval<const _Tp&>() <=
1102 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001103 bool
1104>
Eric Fiselier8af90142017-03-30 20:06:52 +00001105operator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001106{
1107 if (!static_cast<bool>(__x))
1108 return true;
1109 if (!static_cast<bool>(__y))
1110 return false;
1111 return *__x <= *__y;
1112}
1113
Eric Fiselier8af90142017-03-30 20:06:52 +00001114template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001115_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001116_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001117 is_convertible_v<decltype(declval<const _Tp&>() >=
1118 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001119 bool
1120>
Eric Fiselier8af90142017-03-30 20:06:52 +00001121operator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001122{
1123 if (!static_cast<bool>(__y))
1124 return true;
1125 if (!static_cast<bool>(__x))
1126 return false;
1127 return *__x >= *__y;
1128}
1129
1130// Comparisons with nullopt
1131template <class _Tp>
1132_LIBCPP_INLINE_VISIBILITY constexpr
1133bool
1134operator==(const optional<_Tp>& __x, nullopt_t) noexcept
1135{
1136 return !static_cast<bool>(__x);
1137}
1138
1139template <class _Tp>
1140_LIBCPP_INLINE_VISIBILITY constexpr
1141bool
1142operator==(nullopt_t, const optional<_Tp>& __x) noexcept
1143{
1144 return !static_cast<bool>(__x);
1145}
1146
1147template <class _Tp>
1148_LIBCPP_INLINE_VISIBILITY constexpr
1149bool
1150operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
1151{
1152 return static_cast<bool>(__x);
1153}
1154
1155template <class _Tp>
1156_LIBCPP_INLINE_VISIBILITY constexpr
1157bool
1158operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
1159{
1160 return static_cast<bool>(__x);
1161}
1162
1163template <class _Tp>
1164_LIBCPP_INLINE_VISIBILITY constexpr
1165bool
1166operator<(const optional<_Tp>&, nullopt_t) noexcept
1167{
1168 return false;
1169}
1170
1171template <class _Tp>
1172_LIBCPP_INLINE_VISIBILITY constexpr
1173bool
1174operator<(nullopt_t, const optional<_Tp>& __x) noexcept
1175{
1176 return static_cast<bool>(__x);
1177}
1178
1179template <class _Tp>
1180_LIBCPP_INLINE_VISIBILITY constexpr
1181bool
1182operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
1183{
1184 return !static_cast<bool>(__x);
1185}
1186
1187template <class _Tp>
1188_LIBCPP_INLINE_VISIBILITY constexpr
1189bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001190operator<=(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001191{
1192 return true;
1193}
1194
1195template <class _Tp>
1196_LIBCPP_INLINE_VISIBILITY constexpr
1197bool
1198operator>(const optional<_Tp>& __x, nullopt_t) noexcept
1199{
1200 return static_cast<bool>(__x);
1201}
1202
1203template <class _Tp>
1204_LIBCPP_INLINE_VISIBILITY constexpr
1205bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001206operator>(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001207{
1208 return false;
1209}
1210
1211template <class _Tp>
1212_LIBCPP_INLINE_VISIBILITY constexpr
1213bool
1214operator>=(const optional<_Tp>&, nullopt_t) noexcept
1215{
1216 return true;
1217}
1218
1219template <class _Tp>
1220_LIBCPP_INLINE_VISIBILITY constexpr
1221bool
1222operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1223{
1224 return !static_cast<bool>(__x);
1225}
1226
1227// Comparisons with T
Eric Fiselier8af90142017-03-30 20:06:52 +00001228template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001229_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001230_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001231 is_convertible_v<decltype(declval<const _Tp&>() ==
1232 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001233 bool
1234>
Eric Fiselier8af90142017-03-30 20:06:52 +00001235operator==(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001236{
1237 return static_cast<bool>(__x) ? *__x == __v : false;
1238}
1239
Eric Fiselier8af90142017-03-30 20:06:52 +00001240template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001241_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001242_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001243 is_convertible_v<decltype(declval<const _Tp&>() ==
1244 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001245 bool
1246>
Eric Fiselier8af90142017-03-30 20:06:52 +00001247operator==(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001248{
1249 return static_cast<bool>(__x) ? __v == *__x : false;
1250}
1251
Eric Fiselier8af90142017-03-30 20:06:52 +00001252template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001253_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001254_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001255 is_convertible_v<decltype(declval<const _Tp&>() !=
1256 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001257 bool
1258>
Eric Fiselier8af90142017-03-30 20:06:52 +00001259operator!=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001260{
1261 return static_cast<bool>(__x) ? *__x != __v : true;
1262}
1263
Eric Fiselier8af90142017-03-30 20:06:52 +00001264template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001265_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001266_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001267 is_convertible_v<decltype(declval<const _Tp&>() !=
1268 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001269 bool
1270>
Eric Fiselier8af90142017-03-30 20:06:52 +00001271operator!=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001272{
1273 return static_cast<bool>(__x) ? __v != *__x : true;
1274}
1275
Eric Fiselier8af90142017-03-30 20:06:52 +00001276template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001277_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001278_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001279 is_convertible_v<decltype(declval<const _Tp&>() <
1280 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001281 bool
1282>
Eric Fiselier8af90142017-03-30 20:06:52 +00001283operator<(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001284{
1285 return static_cast<bool>(__x) ? *__x < __v : true;
1286}
1287
Eric Fiselier8af90142017-03-30 20:06:52 +00001288template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001289_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001290_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001291 is_convertible_v<decltype(declval<const _Tp&>() <
1292 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001293 bool
1294>
Eric Fiselier8af90142017-03-30 20:06:52 +00001295operator<(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001296{
1297 return static_cast<bool>(__x) ? __v < *__x : false;
1298}
1299
Eric Fiselier8af90142017-03-30 20:06:52 +00001300template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001301_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001302_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001303 is_convertible_v<decltype(declval<const _Tp&>() <=
1304 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001305 bool
1306>
Eric Fiselier8af90142017-03-30 20:06:52 +00001307operator<=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001308{
1309 return static_cast<bool>(__x) ? *__x <= __v : true;
1310}
1311
Eric Fiselier8af90142017-03-30 20:06:52 +00001312template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001313_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001314_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001315 is_convertible_v<decltype(declval<const _Tp&>() <=
1316 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001317 bool
1318>
Eric Fiselier8af90142017-03-30 20:06:52 +00001319operator<=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001320{
1321 return static_cast<bool>(__x) ? __v <= *__x : false;
1322}
1323
Eric Fiselier8af90142017-03-30 20:06:52 +00001324template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001325_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001326_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001327 is_convertible_v<decltype(declval<const _Tp&>() >
1328 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001329 bool
1330>
Eric Fiselier8af90142017-03-30 20:06:52 +00001331operator>(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001332{
1333 return static_cast<bool>(__x) ? *__x > __v : false;
1334}
1335
Eric Fiselier8af90142017-03-30 20:06:52 +00001336template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001337_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001338_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001339 is_convertible_v<decltype(declval<const _Tp&>() >
1340 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001341 bool
1342>
Eric Fiselier8af90142017-03-30 20:06:52 +00001343operator>(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001344{
1345 return static_cast<bool>(__x) ? __v > *__x : true;
1346}
1347
Eric Fiselier8af90142017-03-30 20:06:52 +00001348template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001349_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001350_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001351 is_convertible_v<decltype(declval<const _Tp&>() >=
1352 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001353 bool
1354>
Eric Fiselier8af90142017-03-30 20:06:52 +00001355operator>=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001356{
1357 return static_cast<bool>(__x) ? *__x >= __v : false;
1358}
1359
Eric Fiselier8af90142017-03-30 20:06:52 +00001360template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001361_LIBCPP_INLINE_VISIBILITY constexpr
Eric Fiselier3906a132019-06-23 20:28:29 +00001362_EnableIf<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001363 is_convertible_v<decltype(declval<const _Tp&>() >=
1364 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001365 bool
1366>
Eric Fiselier8af90142017-03-30 20:06:52 +00001367operator>=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001368{
1369 return static_cast<bool>(__x) ? __v >= *__x : true;
1370}
1371
1372
1373template <class _Tp>
Christopher Di Bella80e8f642021-05-09 01:30:32 +00001374inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Eric Fiselier3906a132019-06-23 20:28:29 +00001375_EnableIf<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001376 is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1377 void
1378>
1379swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1380{
1381 __x.swap(__y);
1382}
1383
1384template <class _Tp>
1385_LIBCPP_INLINE_VISIBILITY constexpr
1386optional<decay_t<_Tp>> make_optional(_Tp&& __v)
1387{
1388 return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1389}
1390
1391template <class _Tp, class... _Args>
1392_LIBCPP_INLINE_VISIBILITY constexpr
1393optional<_Tp> make_optional(_Args&&... __args)
1394{
1395 return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1396}
1397
1398template <class _Tp, class _Up, class... _Args>
1399_LIBCPP_INLINE_VISIBILITY constexpr
1400optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args)
1401{
1402 return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1403}
1404
1405template <class _Tp>
Eric Fiselier698a97b2017-01-21 00:02:12 +00001406struct _LIBCPP_TEMPLATE_VIS hash<
1407 __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1408>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001409{
Arthur O'Dwyerf5486c82021-05-25 14:34:18 -04001410#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
1411 _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type;
1412 _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type;
1413#endif
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001414
1415 _LIBCPP_INLINE_VISIBILITY
Arthur O'Dwyerf5486c82021-05-25 14:34:18 -04001416 size_t operator()(const optional<_Tp>& __opt) const
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001417 {
Eric Fiselier698a97b2017-01-21 00:02:12 +00001418 return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001419 }
1420};
1421
1422_LIBCPP_END_NAMESPACE_STD
1423
Louis Dionne2b1ceaa2021-04-20 12:03:32 -04001424#endif // _LIBCPP_STD_VER > 14
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001425
Eric Fiselierf4433a32017-05-31 22:07:49 +00001426_LIBCPP_POP_MACROS
1427
Louis Dionne2b1ceaa2021-04-20 12:03:32 -04001428#endif // _LIBCPP_OPTIONAL