blob: b9ac71b04e2c5e8e16c5f5bcc76c9a217a4a6c8f [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
166namespace std // purposefully not using versioning namespace
167{
168
Louis Dionnecef92e62018-11-19 15:37:04 +0000169class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
Marshall Clowa627d4a2017-02-05 20:06:38 +0000170 : public exception
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000171{
172public:
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000173 // Get the key function ~bad_optional_access() into the dylib
Marshall Clow53fc0372017-02-05 20:52:32 +0000174 virtual ~bad_optional_access() _NOEXCEPT;
Marshall Clowa627d4a2017-02-05 20:06:38 +0000175 virtual const char* what() const _NOEXCEPT;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000176};
177
178} // std
179
180#if _LIBCPP_STD_VER > 14
181
182_LIBCPP_BEGIN_NAMESPACE_STD
183
184_LIBCPP_NORETURN
185inline _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000186_LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000187void __throw_bad_optional_access() {
188#ifndef _LIBCPP_NO_EXCEPTIONS
189 throw bad_optional_access();
190#else
191 _VSTD::abort();
192#endif
193}
194
195struct nullopt_t
196{
197 struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
198 _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
199};
200
Louis Dionne559be102021-09-22 09:35:32 -0400201inline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000202
203template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
204struct __optional_destruct_base;
205
206template <class _Tp>
207struct __optional_destruct_base<_Tp, false>
208{
209 typedef _Tp value_type;
210 static_assert(is_object_v<value_type>,
211 "instantiation of optional with a non-object type is undefined behavior");
212 union
213 {
214 char __null_state_;
215 value_type __val_;
216 };
217 bool __engaged_;
218
219 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000220 _LIBCPP_CONSTEXPR_AFTER_CXX17 ~__optional_destruct_base()
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000221 {
222 if (__engaged_)
223 __val_.~value_type();
224 }
225
226 _LIBCPP_INLINE_VISIBILITY
227 constexpr __optional_destruct_base() noexcept
228 : __null_state_(),
229 __engaged_(false) {}
230
231 template <class... _Args>
232 _LIBCPP_INLINE_VISIBILITY
233 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
234 : __val_(_VSTD::forward<_Args>(__args)...),
235 __engaged_(true) {}
236
237 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000238 _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000239 {
240 if (__engaged_)
241 {
242 __val_.~value_type();
243 __engaged_ = false;
244 }
245 }
246};
247
248template <class _Tp>
249struct __optional_destruct_base<_Tp, true>
250{
251 typedef _Tp value_type;
252 static_assert(is_object_v<value_type>,
253 "instantiation of optional with a non-object type is undefined behavior");
254 union
255 {
256 char __null_state_;
257 value_type __val_;
258 };
259 bool __engaged_;
260
261 _LIBCPP_INLINE_VISIBILITY
262 constexpr __optional_destruct_base() noexcept
263 : __null_state_(),
264 __engaged_(false) {}
265
266 template <class... _Args>
267 _LIBCPP_INLINE_VISIBILITY
268 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
269 : __val_(_VSTD::forward<_Args>(__args)...),
270 __engaged_(true) {}
271
272 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000273 _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000274 {
275 if (__engaged_)
276 {
277 __engaged_ = false;
278 }
279 }
280};
281
282template <class _Tp, bool = is_reference<_Tp>::value>
283struct __optional_storage_base : __optional_destruct_base<_Tp>
284{
285 using __base = __optional_destruct_base<_Tp>;
286 using value_type = _Tp;
287 using __base::__base;
288
289 _LIBCPP_INLINE_VISIBILITY
290 constexpr bool has_value() const noexcept
291 {
292 return this->__engaged_;
293 }
294
295 _LIBCPP_INLINE_VISIBILITY
296 constexpr value_type& __get() & noexcept
297 {
298 return this->__val_;
299 }
300 _LIBCPP_INLINE_VISIBILITY
301 constexpr const value_type& __get() const& noexcept
302 {
303 return this->__val_;
304 }
305 _LIBCPP_INLINE_VISIBILITY
306 constexpr value_type&& __get() && noexcept
307 {
308 return _VSTD::move(this->__val_);
309 }
310 _LIBCPP_INLINE_VISIBILITY
311 constexpr const value_type&& __get() const&& noexcept
312 {
313 return _VSTD::move(this->__val_);
314 }
315
316 template <class... _Args>
317 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000318 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_Args&&... __args)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000319 {
320 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000321#if _LIBCPP_STD_VER > 17
322 _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...);
323#else
Arthur O'Dwyer0c4472a2020-12-11 20:30:28 -0500324 ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000325#endif
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000326 this->__engaged_ = true;
327 }
328
329 template <class _That>
330 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000331 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000332 {
333 if (__opt.has_value())
334 __construct(_VSTD::forward<_That>(__opt).__get());
335 }
336
337 template <class _That>
338 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000339 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000340 {
341 if (this->__engaged_ == __opt.has_value())
342 {
343 if (this->__engaged_)
344 this->__val_ = _VSTD::forward<_That>(__opt).__get();
345 }
346 else
347 {
348 if (this->__engaged_)
349 this->reset();
350 else
351 __construct(_VSTD::forward<_That>(__opt).__get());
352 }
353 }
354};
355
356// optional<T&> is currently required ill-formed, however it may to be in the
357// future. For this reason it has already been implemented to ensure we can
358// make the change in an ABI compatible manner.
359template <class _Tp>
360struct __optional_storage_base<_Tp, true>
361{
362 using value_type = _Tp;
363 using __raw_type = remove_reference_t<_Tp>;
364 __raw_type* __value_;
365
366 template <class _Up>
367 static constexpr bool __can_bind_reference() {
368 using _RawUp = typename remove_reference<_Up>::type;
369 using _UpPtr = _RawUp*;
370 using _RawTp = typename remove_reference<_Tp>::type;
371 using _TpPtr = _RawTp*;
372 using _CheckLValueArg = integral_constant<bool,
373 (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
374 || is_same<_RawUp, reference_wrapper<_RawTp>>::value
375 || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
376 >;
377 return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
378 || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
379 is_convertible<_UpPtr, _TpPtr>::value);
380 }
381
382 _LIBCPP_INLINE_VISIBILITY
383 constexpr __optional_storage_base() noexcept
384 : __value_(nullptr) {}
385
386 template <class _UArg>
387 _LIBCPP_INLINE_VISIBILITY
388 constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
389 : __value_(_VSTD::addressof(__uarg))
390 {
391 static_assert(__can_bind_reference<_UArg>(),
392 "Attempted to construct a reference element in tuple from a "
393 "possible temporary");
394 }
395
396 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000397 _LIBCPP_CONSTEXPR_AFTER_CXX17 void reset() noexcept { __value_ = nullptr; }
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000398
399 _LIBCPP_INLINE_VISIBILITY
400 constexpr bool has_value() const noexcept
401 { return __value_ != nullptr; }
402
403 _LIBCPP_INLINE_VISIBILITY
404 constexpr value_type& __get() const& noexcept
405 { return *__value_; }
406
407 _LIBCPP_INLINE_VISIBILITY
408 constexpr value_type&& __get() const&& noexcept
409 { return _VSTD::forward<value_type>(*__value_); }
410
411 template <class _UArg>
412 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000413 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct(_UArg&& __val)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000414 {
415 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
416 static_assert(__can_bind_reference<_UArg>(),
417 "Attempted to construct a reference element in tuple from a "
418 "possible temporary");
419 __value_ = _VSTD::addressof(__val);
420 }
421
422 template <class _That>
423 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000424 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __construct_from(_That&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000425 {
426 if (__opt.has_value())
427 __construct(_VSTD::forward<_That>(__opt).__get());
428 }
429
430 template <class _That>
431 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000432 _LIBCPP_CONSTEXPR_AFTER_CXX17 void __assign_from(_That&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000433 {
434 if (has_value() == __opt.has_value())
435 {
436 if (has_value())
437 *__value_ = _VSTD::forward<_That>(__opt).__get();
438 }
439 else
440 {
441 if (has_value())
442 reset();
443 else
444 __construct(_VSTD::forward<_That>(__opt).__get());
445 }
446 }
447};
448
Casey Carterc189f7f2017-07-09 17:15:49 +0000449template <class _Tp, bool = is_trivially_copy_constructible<_Tp>::value>
450struct __optional_copy_base : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000451{
452 using __optional_storage_base<_Tp>::__optional_storage_base;
453};
454
455template <class _Tp>
Casey Carterc189f7f2017-07-09 17:15:49 +0000456struct __optional_copy_base<_Tp, false> : __optional_storage_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000457{
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000458 using __optional_storage_base<_Tp>::__optional_storage_base;
459
460 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000461 __optional_copy_base() = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000462
463 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000464 _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_base(const __optional_copy_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000465 {
466 this->__construct_from(__opt);
467 }
468
469 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000470 __optional_copy_base(__optional_copy_base&&) = default;
471 _LIBCPP_INLINE_VISIBILITY
472 __optional_copy_base& operator=(const __optional_copy_base&) = default;
473 _LIBCPP_INLINE_VISIBILITY
474 __optional_copy_base& operator=(__optional_copy_base&&) = default;
475};
476
477template <class _Tp, bool = is_trivially_move_constructible<_Tp>::value>
478struct __optional_move_base : __optional_copy_base<_Tp>
479{
480 using __optional_copy_base<_Tp>::__optional_copy_base;
481};
482
483template <class _Tp>
484struct __optional_move_base<_Tp, false> : __optional_copy_base<_Tp>
485{
486 using value_type = _Tp;
487 using __optional_copy_base<_Tp>::__optional_copy_base;
488
489 _LIBCPP_INLINE_VISIBILITY
490 __optional_move_base() = default;
491 _LIBCPP_INLINE_VISIBILITY
492 __optional_move_base(const __optional_move_base&) = default;
493
494 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000495 _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_base(__optional_move_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000496 noexcept(is_nothrow_move_constructible_v<value_type>)
497 {
498 this->__construct_from(_VSTD::move(__opt));
499 }
500
501 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000502 __optional_move_base& operator=(const __optional_move_base&) = default;
503 _LIBCPP_INLINE_VISIBILITY
504 __optional_move_base& operator=(__optional_move_base&&) = default;
505};
506
507template <class _Tp, bool =
508 is_trivially_destructible<_Tp>::value &&
509 is_trivially_copy_constructible<_Tp>::value &&
510 is_trivially_copy_assignable<_Tp>::value>
511struct __optional_copy_assign_base : __optional_move_base<_Tp>
512{
513 using __optional_move_base<_Tp>::__optional_move_base;
514};
515
516template <class _Tp>
517struct __optional_copy_assign_base<_Tp, false> : __optional_move_base<_Tp>
518{
519 using __optional_move_base<_Tp>::__optional_move_base;
520
521 _LIBCPP_INLINE_VISIBILITY
522 __optional_copy_assign_base() = default;
523 _LIBCPP_INLINE_VISIBILITY
524 __optional_copy_assign_base(const __optional_copy_assign_base&) = default;
525 _LIBCPP_INLINE_VISIBILITY
526 __optional_copy_assign_base(__optional_copy_assign_base&&) = default;
527
528 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000529 _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000530 {
531 this->__assign_from(__opt);
532 return *this;
533 }
534
535 _LIBCPP_INLINE_VISIBILITY
Casey Carterc189f7f2017-07-09 17:15:49 +0000536 __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default;
537};
538
539template <class _Tp, bool =
540 is_trivially_destructible<_Tp>::value &&
541 is_trivially_move_constructible<_Tp>::value &&
542 is_trivially_move_assignable<_Tp>::value>
543struct __optional_move_assign_base : __optional_copy_assign_base<_Tp>
544{
545 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
546};
547
548template <class _Tp>
549struct __optional_move_assign_base<_Tp, false> : __optional_copy_assign_base<_Tp>
550{
551 using value_type = _Tp;
552 using __optional_copy_assign_base<_Tp>::__optional_copy_assign_base;
553
554 _LIBCPP_INLINE_VISIBILITY
555 __optional_move_assign_base() = default;
556 _LIBCPP_INLINE_VISIBILITY
557 __optional_move_assign_base(const __optional_move_assign_base& __opt) = default;
558 _LIBCPP_INLINE_VISIBILITY
559 __optional_move_assign_base(__optional_move_assign_base&&) = default;
560 _LIBCPP_INLINE_VISIBILITY
561 __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default;
562
563 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000564 _LIBCPP_CONSTEXPR_AFTER_CXX17 __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000565 noexcept(is_nothrow_move_assignable_v<value_type> &&
566 is_nothrow_move_constructible_v<value_type>)
567 {
568 this->__assign_from(_VSTD::move(__opt));
569 return *this;
570 }
571};
572
573template <class _Tp>
574using __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
575 is_copy_constructible<_Tp>::value,
576 is_move_constructible<_Tp>::value
577>;
578
579template <class _Tp>
580using __optional_sfinae_assign_base_t = __sfinae_assign_base<
581 (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
582 (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
583>;
584
585template <class _Tp>
586class optional
Casey Carterc189f7f2017-07-09 17:15:49 +0000587 : private __optional_move_assign_base<_Tp>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000588 , private __optional_sfinae_ctor_base_t<_Tp>
589 , private __optional_sfinae_assign_base_t<_Tp>
590{
Casey Carterc189f7f2017-07-09 17:15:49 +0000591 using __base = __optional_move_assign_base<_Tp>;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000592public:
593 using value_type = _Tp;
594
595private:
596 // Disable the reference extension using this static assert.
Marshall Clowfa6a3342019-03-25 16:35:59 +0000597 static_assert(!is_same_v<__uncvref_t<value_type>, in_place_t>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000598 "instantiation of optional with in_place_t is ill-formed");
599 static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
600 "instantiation of optional with nullopt_t is ill-formed");
601 static_assert(!is_reference_v<value_type>,
602 "instantiation of optional with a reference type is ill-formed");
603 static_assert(is_destructible_v<value_type>,
604 "instantiation of optional with a non-destructible type is ill-formed");
Marshall Clowfa6a3342019-03-25 16:35:59 +0000605 static_assert(!is_array_v<value_type>,
606 "instantiation of optional with an array type is ill-formed");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000607
608 // LWG2756: conditionally explicit conversion from _Up
609 struct _CheckOptionalArgsConstructor {
610 template <class _Up>
611 static constexpr bool __enable_implicit() {
612 return is_constructible_v<_Tp, _Up&&> &&
613 is_convertible_v<_Up&&, _Tp>;
614 }
615
616 template <class _Up>
617 static constexpr bool __enable_explicit() {
618 return is_constructible_v<_Tp, _Up&&> &&
619 !is_convertible_v<_Up&&, _Tp>;
620 }
621 };
622 template <class _Up>
Eric Fiselier3906a132019-06-23 20:28:29 +0000623 using _CheckOptionalArgsCtor = _If<
624 _IsNotSame<__uncvref_t<_Up>, in_place_t>::value &&
625 _IsNotSame<__uncvref_t<_Up>, optional>::value,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000626 _CheckOptionalArgsConstructor,
627 __check_tuple_constructor_fail
628 >;
629 template <class _QualUp>
630 struct _CheckOptionalLikeConstructor {
631 template <class _Up, class _Opt = optional<_Up>>
Eric Fiselier3906a132019-06-23 20:28:29 +0000632 using __check_constructible_from_opt = _Or<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000633 is_constructible<_Tp, _Opt&>,
634 is_constructible<_Tp, _Opt const&>,
635 is_constructible<_Tp, _Opt&&>,
636 is_constructible<_Tp, _Opt const&&>,
637 is_convertible<_Opt&, _Tp>,
638 is_convertible<_Opt const&, _Tp>,
639 is_convertible<_Opt&&, _Tp>,
640 is_convertible<_Opt const&&, _Tp>
641 >;
642 template <class _Up, class _Opt = optional<_Up>>
Eric Fiselier3906a132019-06-23 20:28:29 +0000643 using __check_assignable_from_opt = _Or<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000644 is_assignable<_Tp&, _Opt&>,
645 is_assignable<_Tp&, _Opt const&>,
646 is_assignable<_Tp&, _Opt&&>,
647 is_assignable<_Tp&, _Opt const&&>
648 >;
649 template <class _Up, class _QUp = _QualUp>
650 static constexpr bool __enable_implicit() {
651 return is_convertible<_QUp, _Tp>::value &&
652 !__check_constructible_from_opt<_Up>::value;
653 }
654 template <class _Up, class _QUp = _QualUp>
655 static constexpr bool __enable_explicit() {
656 return !is_convertible<_QUp, _Tp>::value &&
657 !__check_constructible_from_opt<_Up>::value;
658 }
659 template <class _Up, class _QUp = _QualUp>
660 static constexpr bool __enable_assign() {
Arthur O'Dwyerdf5df562020-12-12 11:57:32 -0500661 // Construction and assignability of _QUp to _Tp has already been
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000662 // checked.
663 return !__check_constructible_from_opt<_Up>::value &&
664 !__check_assignable_from_opt<_Up>::value;
665 }
666 };
667
668 template <class _Up, class _QualUp>
Eric Fiselier3906a132019-06-23 20:28:29 +0000669 using _CheckOptionalLikeCtor = _If<
670 _And<
671 _IsNotSame<_Up, _Tp>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000672 is_constructible<_Tp, _QualUp>
673 >::value,
674 _CheckOptionalLikeConstructor<_QualUp>,
675 __check_tuple_constructor_fail
676 >;
677 template <class _Up, class _QualUp>
Eric Fiselier3906a132019-06-23 20:28:29 +0000678 using _CheckOptionalLikeAssign = _If<
679 _And<
680 _IsNotSame<_Up, _Tp>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000681 is_constructible<_Tp, _QualUp>,
682 is_assignable<_Tp&, _QualUp>
683 >::value,
684 _CheckOptionalLikeConstructor<_QualUp>,
685 __check_tuple_constructor_fail
686 >;
687public:
688
689 _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
Marshall Clowd44e2e32017-05-17 15:30:01 +0000690 _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
691 _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000692 _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
693
Louis Dionne25547162021-08-17 12:26:09 -0400694 template <class _InPlaceT, class... _Args, class = enable_if_t<
Eric Fiselier3906a132019-06-23 20:28:29 +0000695 _And<
696 _IsSame<_InPlaceT, in_place_t>,
697 is_constructible<value_type, _Args...>
Eric Fiselier82103932019-03-11 22:55:21 +0000698 >::value
699 >
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000700 >
701 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier82103932019-03-11 22:55:21 +0000702 constexpr explicit optional(_InPlaceT, _Args&&... __args)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000703 : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
704
Louis Dionne25547162021-08-17 12:26:09 -0400705 template <class _Up, class... _Args, class = enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000706 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
707 >
708 _LIBCPP_INLINE_VISIBILITY
709 constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
710 : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
711
Louis Dionne25547162021-08-17 12:26:09 -0400712 template <class _Up = value_type, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000713 _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
714 , int> = 0>
715 _LIBCPP_INLINE_VISIBILITY
716 constexpr optional(_Up&& __v)
717 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
718
Louis Dionne25547162021-08-17 12:26:09 -0400719 template <class _Up, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000720 _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
721 , int> = 0>
722 _LIBCPP_INLINE_VISIBILITY
723 constexpr explicit optional(_Up&& __v)
724 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
725
726 // LWG2756: conditionally explicit conversion from const optional<_Up>&
Louis Dionne25547162021-08-17 12:26:09 -0400727 template <class _Up, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000728 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
729 , int> = 0>
730 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000731 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(const optional<_Up>& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000732 {
733 this->__construct_from(__v);
734 }
Louis Dionne25547162021-08-17 12:26:09 -0400735 template <class _Up, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000736 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
737 , int> = 0>
738 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000739 _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(const optional<_Up>& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000740 {
741 this->__construct_from(__v);
742 }
743
744 // LWG2756: conditionally explicit conversion from optional<_Up>&&
Louis Dionne25547162021-08-17 12:26:09 -0400745 template <class _Up, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000746 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
747 , int> = 0>
748 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000749 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional(optional<_Up>&& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000750 {
751 this->__construct_from(_VSTD::move(__v));
752 }
Louis Dionne25547162021-08-17 12:26:09 -0400753 template <class _Up, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000754 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
755 , int> = 0>
756 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000757 _LIBCPP_CONSTEXPR_AFTER_CXX17 explicit optional(optional<_Up>&& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000758 {
759 this->__construct_from(_VSTD::move(__v));
760 }
761
762 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000763 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional& operator=(nullopt_t) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000764 {
765 reset();
766 return *this;
767 }
768
769 _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
770 _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
771
772 // LWG2756
773 template <class _Up = value_type,
Louis Dionne25547162021-08-17 12:26:09 -0400774 class = enable_if_t<
Eric Fiselier3906a132019-06-23 20:28:29 +0000775 _And<
776 _IsNotSame<__uncvref_t<_Up>, optional>,
777 _Or<
Marshall Clow99315112019-06-27 18:40:55 +0000778 _IsNotSame<__uncvref_t<_Up>, value_type>,
Eric Fiselier3906a132019-06-23 20:28:29 +0000779 _Not<is_scalar<value_type>>
Eric Fiselierb9014262016-10-16 03:21:35 +0000780 >,
781 is_constructible<value_type, _Up>,
782 is_assignable<value_type&, _Up>
783 >::value>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000784 >
785 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000786 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000787 operator=(_Up&& __v)
788 {
789 if (this->has_value())
790 this->__get() = _VSTD::forward<_Up>(__v);
791 else
792 this->__construct(_VSTD::forward<_Up>(__v));
793 return *this;
794 }
795
796 // LWG2756
Louis Dionne25547162021-08-17 12:26:09 -0400797 template <class _Up, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000798 _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
799 , int> = 0>
800 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000801 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000802 operator=(const optional<_Up>& __v)
803 {
804 this->__assign_from(__v);
805 return *this;
806 }
807
808 // LWG2756
Louis Dionne25547162021-08-17 12:26:09 -0400809 template <class _Up, enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000810 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
811 , int> = 0>
812 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000813 _LIBCPP_CONSTEXPR_AFTER_CXX17 optional&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000814 operator=(optional<_Up>&& __v)
815 {
816 this->__assign_from(_VSTD::move(__v));
817 return *this;
818 }
819
820 template <class... _Args,
Louis Dionne25547162021-08-17 12:26:09 -0400821 class = enable_if_t
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000822 <
823 is_constructible_v<value_type, _Args...>
824 >
825 >
826 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000827 _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000828 emplace(_Args&&... __args)
829 {
830 reset();
831 this->__construct(_VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000832 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000833 }
834
835 template <class _Up, class... _Args,
Louis Dionne25547162021-08-17 12:26:09 -0400836 class = enable_if_t
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000837 <
838 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
839 >
840 >
841 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000842 _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000843 emplace(initializer_list<_Up> __il, _Args&&... __args)
844 {
845 reset();
846 this->__construct(__il, _VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000847 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000848 }
849
850 _LIBCPP_INLINE_VISIBILITY
Christopher Di Bella80e8f642021-05-09 01:30:32 +0000851 _LIBCPP_CONSTEXPR_AFTER_CXX17 void swap(optional& __opt)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000852 noexcept(is_nothrow_move_constructible_v<value_type> &&
853 is_nothrow_swappable_v<value_type>)
854 {
855 if (this->has_value() == __opt.has_value())
856 {
857 using _VSTD::swap;
858 if (this->has_value())
859 swap(this->__get(), __opt.__get());
860 }
861 else
862 {
863 if (this->has_value())
864 {
865 __opt.__construct(_VSTD::move(this->__get()));
866 reset();
867 }
868 else
869 {
870 this->__construct(_VSTD::move(__opt.__get()));
871 __opt.reset();
872 }
873 }
874 }
875
876 _LIBCPP_INLINE_VISIBILITY
877 constexpr
878 add_pointer_t<value_type const>
879 operator->() const
880 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200881 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000882 return _VSTD::addressof(this->__get());
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000883 }
884
885 _LIBCPP_INLINE_VISIBILITY
886 constexpr
887 add_pointer_t<value_type>
888 operator->()
889 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200890 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000891 return _VSTD::addressof(this->__get());
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000892 }
893
894 _LIBCPP_INLINE_VISIBILITY
895 constexpr
896 const value_type&
zoecarver73efa752021-07-01 10:18:27 -0700897 operator*() const& noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000898 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200899 _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000900 return this->__get();
901 }
902
903 _LIBCPP_INLINE_VISIBILITY
904 constexpr
905 value_type&
zoecarver73efa752021-07-01 10:18:27 -0700906 operator*() & noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000907 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200908 _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000909 return this->__get();
910 }
911
912 _LIBCPP_INLINE_VISIBILITY
913 constexpr
914 value_type&&
zoecarver73efa752021-07-01 10:18:27 -0700915 operator*() && noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000916 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200917 _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000918 return _VSTD::move(this->__get());
919 }
920
921 _LIBCPP_INLINE_VISIBILITY
922 constexpr
923 const value_type&&
zoecarver73efa752021-07-01 10:18:27 -0700924 operator*() const&& noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000925 {
Kristina Bessonovaaeeaa7e2021-05-09 19:29:56 +0200926 _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value");
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000927 return _VSTD::move(this->__get());
928 }
929
930 _LIBCPP_INLINE_VISIBILITY
931 constexpr explicit operator bool() const noexcept { return has_value(); }
932
933 using __base::has_value;
934 using __base::__get;
935
936 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000937 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000938 constexpr value_type const& value() const&
939 {
940 if (!this->has_value())
941 __throw_bad_optional_access();
942 return this->__get();
943 }
944
945 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000946 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000947 constexpr value_type& value() &
948 {
949 if (!this->has_value())
950 __throw_bad_optional_access();
951 return this->__get();
952 }
953
954 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000955 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000956 constexpr value_type&& value() &&
957 {
958 if (!this->has_value())
959 __throw_bad_optional_access();
960 return _VSTD::move(this->__get());
961 }
962
963 _LIBCPP_INLINE_VISIBILITY
Louis Dionnecef92e62018-11-19 15:37:04 +0000964 _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000965 constexpr value_type const&& value() const&&
966 {
967 if (!this->has_value())
968 __throw_bad_optional_access();
969 return _VSTD::move(this->__get());
970 }
971
972 template <class _Up>
973 _LIBCPP_INLINE_VISIBILITY
974 constexpr value_type value_or(_Up&& __v) const&
975 {
976 static_assert(is_copy_constructible_v<value_type>,
977 "optional<T>::value_or: T must be copy constructible");
978 static_assert(is_convertible_v<_Up, value_type>,
979 "optional<T>::value_or: U must be convertible to T");
980 return this->has_value() ? this->__get() :
981 static_cast<value_type>(_VSTD::forward<_Up>(__v));
982 }
983
984 template <class _Up>
985 _LIBCPP_INLINE_VISIBILITY
Casey Cartercb05fae2017-06-06 18:47:26 +0000986 constexpr value_type value_or(_Up&& __v) &&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000987 {
988 static_assert(is_move_constructible_v<value_type>,
989 "optional<T>::value_or: T must be move 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() ? _VSTD::move(this->__get()) :
993 static_cast<value_type>(_VSTD::forward<_Up>(__v));
994 }
995
996 using __base::reset;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000997};
998
Louis Dionned59f8a52021-08-17 11:59:07 -0400999#if _LIBCPP_STD_VER >= 17
Marshall Clowe3c71ae2018-05-25 02:08:49 +00001000template<class T>
1001 optional(T) -> optional<T>;
1002#endif
1003
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001004// Comparisons between optionals
Eric Fiselier8af90142017-03-30 20:06:52 +00001005template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001006_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001007enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001008 is_convertible_v<decltype(declval<const _Tp&>() ==
1009 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001010 bool
1011>
Eric Fiselier8af90142017-03-30 20:06:52 +00001012operator==(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001013{
1014 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1015 return false;
1016 if (!static_cast<bool>(__x))
1017 return true;
1018 return *__x == *__y;
1019}
1020
Eric Fiselier8af90142017-03-30 20:06:52 +00001021template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001022_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001023enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001024 is_convertible_v<decltype(declval<const _Tp&>() !=
1025 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001026 bool
1027>
Eric Fiselier8af90142017-03-30 20:06:52 +00001028operator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001029{
1030 if (static_cast<bool>(__x) != static_cast<bool>(__y))
1031 return true;
1032 if (!static_cast<bool>(__x))
1033 return false;
1034 return *__x != *__y;
1035}
1036
Eric Fiselier8af90142017-03-30 20:06:52 +00001037template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001038_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001039enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001040 is_convertible_v<decltype(declval<const _Tp&>() <
1041 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001042 bool
1043>
Eric Fiselier8af90142017-03-30 20:06:52 +00001044operator<(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001045{
1046 if (!static_cast<bool>(__y))
1047 return false;
1048 if (!static_cast<bool>(__x))
1049 return true;
1050 return *__x < *__y;
1051}
1052
Eric Fiselier8af90142017-03-30 20:06:52 +00001053template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001054_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001055enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001056 is_convertible_v<decltype(declval<const _Tp&>() >
1057 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001058 bool
1059>
Eric Fiselier8af90142017-03-30 20:06:52 +00001060operator>(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001061{
1062 if (!static_cast<bool>(__x))
1063 return false;
1064 if (!static_cast<bool>(__y))
1065 return true;
1066 return *__x > *__y;
1067}
1068
Eric Fiselier8af90142017-03-30 20:06:52 +00001069template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001070_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001071enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001072 is_convertible_v<decltype(declval<const _Tp&>() <=
1073 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001074 bool
1075>
Eric Fiselier8af90142017-03-30 20:06:52 +00001076operator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001077{
1078 if (!static_cast<bool>(__x))
1079 return true;
1080 if (!static_cast<bool>(__y))
1081 return false;
1082 return *__x <= *__y;
1083}
1084
Eric Fiselier8af90142017-03-30 20:06:52 +00001085template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001086_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001087enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001088 is_convertible_v<decltype(declval<const _Tp&>() >=
1089 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001090 bool
1091>
Eric Fiselier8af90142017-03-30 20:06:52 +00001092operator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001093{
1094 if (!static_cast<bool>(__y))
1095 return true;
1096 if (!static_cast<bool>(__x))
1097 return false;
1098 return *__x >= *__y;
1099}
1100
1101// Comparisons with nullopt
1102template <class _Tp>
1103_LIBCPP_INLINE_VISIBILITY constexpr
1104bool
1105operator==(const optional<_Tp>& __x, nullopt_t) noexcept
1106{
1107 return !static_cast<bool>(__x);
1108}
1109
1110template <class _Tp>
1111_LIBCPP_INLINE_VISIBILITY constexpr
1112bool
1113operator==(nullopt_t, const optional<_Tp>& __x) noexcept
1114{
1115 return !static_cast<bool>(__x);
1116}
1117
1118template <class _Tp>
1119_LIBCPP_INLINE_VISIBILITY constexpr
1120bool
1121operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
1122{
1123 return static_cast<bool>(__x);
1124}
1125
1126template <class _Tp>
1127_LIBCPP_INLINE_VISIBILITY constexpr
1128bool
1129operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
1130{
1131 return static_cast<bool>(__x);
1132}
1133
1134template <class _Tp>
1135_LIBCPP_INLINE_VISIBILITY constexpr
1136bool
1137operator<(const optional<_Tp>&, nullopt_t) noexcept
1138{
1139 return false;
1140}
1141
1142template <class _Tp>
1143_LIBCPP_INLINE_VISIBILITY constexpr
1144bool
1145operator<(nullopt_t, const optional<_Tp>& __x) noexcept
1146{
1147 return static_cast<bool>(__x);
1148}
1149
1150template <class _Tp>
1151_LIBCPP_INLINE_VISIBILITY constexpr
1152bool
1153operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
1154{
1155 return !static_cast<bool>(__x);
1156}
1157
1158template <class _Tp>
1159_LIBCPP_INLINE_VISIBILITY constexpr
1160bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001161operator<=(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001162{
1163 return true;
1164}
1165
1166template <class _Tp>
1167_LIBCPP_INLINE_VISIBILITY constexpr
1168bool
1169operator>(const optional<_Tp>& __x, nullopt_t) noexcept
1170{
1171 return static_cast<bool>(__x);
1172}
1173
1174template <class _Tp>
1175_LIBCPP_INLINE_VISIBILITY constexpr
1176bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001177operator>(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001178{
1179 return false;
1180}
1181
1182template <class _Tp>
1183_LIBCPP_INLINE_VISIBILITY constexpr
1184bool
1185operator>=(const optional<_Tp>&, nullopt_t) noexcept
1186{
1187 return true;
1188}
1189
1190template <class _Tp>
1191_LIBCPP_INLINE_VISIBILITY constexpr
1192bool
1193operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1194{
1195 return !static_cast<bool>(__x);
1196}
1197
1198// Comparisons with T
Eric Fiselier8af90142017-03-30 20:06:52 +00001199template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001200_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001201enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001202 is_convertible_v<decltype(declval<const _Tp&>() ==
1203 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001204 bool
1205>
Eric Fiselier8af90142017-03-30 20:06:52 +00001206operator==(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001207{
1208 return static_cast<bool>(__x) ? *__x == __v : false;
1209}
1210
Eric Fiselier8af90142017-03-30 20:06:52 +00001211template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001212_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001213enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001214 is_convertible_v<decltype(declval<const _Tp&>() ==
1215 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001216 bool
1217>
Eric Fiselier8af90142017-03-30 20:06:52 +00001218operator==(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001219{
1220 return static_cast<bool>(__x) ? __v == *__x : false;
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 _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001231{
1232 return static_cast<bool>(__x) ? *__x != __v : true;
1233}
1234
Eric Fiselier8af90142017-03-30 20:06:52 +00001235template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001236_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001237enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001238 is_convertible_v<decltype(declval<const _Tp&>() !=
1239 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001240 bool
1241>
Eric Fiselier8af90142017-03-30 20:06:52 +00001242operator!=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001243{
1244 return static_cast<bool>(__x) ? __v != *__x : true;
1245}
1246
Eric Fiselier8af90142017-03-30 20:06:52 +00001247template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001248_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001249enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001250 is_convertible_v<decltype(declval<const _Tp&>() <
1251 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001252 bool
1253>
Eric Fiselier8af90142017-03-30 20:06:52 +00001254operator<(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001255{
1256 return static_cast<bool>(__x) ? *__x < __v : true;
1257}
1258
Eric Fiselier8af90142017-03-30 20:06:52 +00001259template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001260_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001261enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001262 is_convertible_v<decltype(declval<const _Tp&>() <
1263 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001264 bool
1265>
Eric Fiselier8af90142017-03-30 20:06:52 +00001266operator<(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001267{
1268 return static_cast<bool>(__x) ? __v < *__x : false;
1269}
1270
Eric Fiselier8af90142017-03-30 20:06:52 +00001271template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001272_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001273enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001274 is_convertible_v<decltype(declval<const _Tp&>() <=
1275 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001276 bool
1277>
Eric Fiselier8af90142017-03-30 20:06:52 +00001278operator<=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001279{
1280 return static_cast<bool>(__x) ? *__x <= __v : true;
1281}
1282
Eric Fiselier8af90142017-03-30 20:06:52 +00001283template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001284_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001285enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001286 is_convertible_v<decltype(declval<const _Tp&>() <=
1287 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001288 bool
1289>
Eric Fiselier8af90142017-03-30 20:06:52 +00001290operator<=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001291{
1292 return static_cast<bool>(__x) ? __v <= *__x : false;
1293}
1294
Eric Fiselier8af90142017-03-30 20:06:52 +00001295template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001296_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001297enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001298 is_convertible_v<decltype(declval<const _Tp&>() >
1299 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001300 bool
1301>
Eric Fiselier8af90142017-03-30 20:06:52 +00001302operator>(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001303{
1304 return static_cast<bool>(__x) ? *__x > __v : false;
1305}
1306
Eric Fiselier8af90142017-03-30 20:06:52 +00001307template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001308_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001309enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001310 is_convertible_v<decltype(declval<const _Tp&>() >
1311 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001312 bool
1313>
Eric Fiselier8af90142017-03-30 20:06:52 +00001314operator>(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001315{
1316 return static_cast<bool>(__x) ? __v > *__x : true;
1317}
1318
Eric Fiselier8af90142017-03-30 20:06:52 +00001319template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001320_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001321enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001322 is_convertible_v<decltype(declval<const _Tp&>() >=
1323 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001324 bool
1325>
Eric Fiselier8af90142017-03-30 20:06:52 +00001326operator>=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001327{
1328 return static_cast<bool>(__x) ? *__x >= __v : false;
1329}
1330
Eric Fiselier8af90142017-03-30 20:06:52 +00001331template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001332_LIBCPP_INLINE_VISIBILITY constexpr
Louis Dionne25547162021-08-17 12:26:09 -04001333enable_if_t<
Arthur O'Dwyer3285c342021-05-10 13:04:16 -04001334 is_convertible_v<decltype(declval<const _Tp&>() >=
1335 declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001336 bool
1337>
Eric Fiselier8af90142017-03-30 20:06:52 +00001338operator>=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001339{
1340 return static_cast<bool>(__x) ? __v >= *__x : true;
1341}
1342
1343
1344template <class _Tp>
Christopher Di Bella80e8f642021-05-09 01:30:32 +00001345inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Louis Dionne25547162021-08-17 12:26:09 -04001346enable_if_t<
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001347 is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1348 void
1349>
1350swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1351{
1352 __x.swap(__y);
1353}
1354
1355template <class _Tp>
1356_LIBCPP_INLINE_VISIBILITY constexpr
1357optional<decay_t<_Tp>> make_optional(_Tp&& __v)
1358{
1359 return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1360}
1361
1362template <class _Tp, class... _Args>
1363_LIBCPP_INLINE_VISIBILITY constexpr
1364optional<_Tp> make_optional(_Args&&... __args)
1365{
1366 return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1367}
1368
1369template <class _Tp, class _Up, class... _Args>
1370_LIBCPP_INLINE_VISIBILITY constexpr
1371optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args)
1372{
1373 return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1374}
1375
1376template <class _Tp>
Eric Fiselier698a97b2017-01-21 00:02:12 +00001377struct _LIBCPP_TEMPLATE_VIS hash<
1378 __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1379>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001380{
Arthur O'Dwyerf5486c82021-05-25 14:34:18 -04001381#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
1382 _LIBCPP_DEPRECATED_IN_CXX17 typedef optional<_Tp> argument_type;
1383 _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type;
1384#endif
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001385
1386 _LIBCPP_INLINE_VISIBILITY
Arthur O'Dwyerf5486c82021-05-25 14:34:18 -04001387 size_t operator()(const optional<_Tp>& __opt) const
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001388 {
Eric Fiselier698a97b2017-01-21 00:02:12 +00001389 return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001390 }
1391};
1392
1393_LIBCPP_END_NAMESPACE_STD
1394
Louis Dionne2b1ceaa2021-04-20 12:03:32 -04001395#endif // _LIBCPP_STD_VER > 14
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001396
Louis Dionne2b1ceaa2021-04-20 12:03:32 -04001397#endif // _LIBCPP_OPTIONAL