blob: 118d71782882786725b334a484faa4ef21d7fcd2 [file] [log] [blame]
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001// -*- C++ -*-
2//===-------------------------- optional ----------------------------------===//
3//
4// The LLVM Compiler Infrastructure
5//
6// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_OPTIONAL
12#define _LIBCPP_OPTIONAL
13
14/*
15 optional synopsis
16
17// C++1z
18
19namespace std {
20 // 20.6.3, optional for object types
21 template <class T> class optional;
22
23 // 20.6.4, no-value state indicator
24 struct nullopt_t{see below };
25 constexpr nullopt_t nullopt(unspecified );
26
27 // 20.6.5, class bad_optional_access
28 class bad_optional_access;
29
30 // 20.6.6, relational operators
31 template <class T>
32 constexpr bool operator==(const optional<T>&, const optional<T>&);
33 template <class T>
34 constexpr bool operator!=(const optional<T>&, const optional<T>&);
35 template <class T>
36 constexpr bool operator<(const optional<T>&, const optional<T>&);
37 template <class T>
38 constexpr bool operator>(const optional<T>&, const optional<T>&);
39 template <class T>
40 constexpr bool operator<=(const optional<T>&, const optional<T>&);
41 template <class T>
42 constexpr bool operator>=(const optional<T>&, const optional<T>&);
43 template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
44 template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
45 template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
46 template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
47 template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
48 template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
49 template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
50 template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
51 template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
52 template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
53 template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
54 template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;
55
56 // 20.6.8, comparison with T
57 template <class T> constexpr bool operator==(const optional<T>&, const T&);
58 template <class T> constexpr bool operator==(const T&, const optional<T>&);
59 template <class T> constexpr bool operator!=(const optional<T>&, const T&);
60 template <class T> constexpr bool operator!=(const T&, const optional<T>&);
61 template <class T> constexpr bool operator<(const optional<T>&, const T&);
62 template <class T> constexpr bool operator<(const T&, const optional<T>&);
63 template <class T> constexpr bool operator<=(const optional<T>&, const T&);
64 template <class T> constexpr bool operator<=(const T&, const optional<T>&);
65 template <class T> constexpr bool operator>(const optional<T>&, const T&);
66 template <class T> constexpr bool operator>(const T&, const optional<T>&);
67 template <class T> constexpr bool operator>=(const optional<T>&, const T&);
68 template <class T> constexpr bool operator>=(const T&, const optional<T>&);
69
70 // 20.6.9, specialized algorithms
71 template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below );
72 template <class T> constexpr optional<see below > make_optional(T&&);
73 template <class T, class... Args>
74 constexpr optional<T> make_optional(Args&&... args);
75 template <class T, class U, class... Args>
76 constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
77
78 // 20.6.10, hash support
79 template <class T> struct hash;
80 template <class T> struct hash<optional<T>>;
81
82 template <class T> class optional {
83 public:
84 using value_type = T;
85
86 // 20.6.3.1, constructors
87 constexpr optional() noexcept;
88 constexpr optional(nullopt_t) noexcept;
89 optional(const optional &);
Marshall Clow45ff9822017-04-12 22:51:27 +000090 optional(optional &&) noexcept(see below);
Eric Fiselierd4ec6352016-10-12 07:46:20 +000091 template <class... Args> constexpr explicit optional(in_place_t, Args &&...);
92 template <class U, class... Args>
93 constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...);
94 template <class U = T>
95 constexpr EXPLICIT optional(U &&);
96 template <class U>
97 constexpr EXPLICIT optional(const optional<U> &);
98 template <class U>
99 constexpr EXPLICIT optional(optional<U> &&);
100
101 // 20.6.3.2, destructor
102 ~optional();
103
104 // 20.6.3.3, assignment
105 optional &operator=(nullopt_t) noexcept;
106 optional &operator=(const optional &);
107 optional &operator=(optional &&) noexcept(see below );
108 template <class U = T> optional &operator=(U &&);
109 template <class U> optional &operator=(const optional<U> &);
110 template <class U> optional &operator=(optional<U> &&);
Marshall Clow45ff9822017-04-12 22:51:27 +0000111 template <class... Args> T& emplace(Args &&...);
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000112 template <class U, class... Args>
Marshall Clow45ff9822017-04-12 22:51:27 +0000113 T& emplace(initializer_list<U>, Args &&...);
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000114
115 // 20.6.3.4, swap
116 void swap(optional &) noexcept(see below );
117
118 // 20.6.3.5, observers
119 constexpr T const *operator->() const;
120 constexpr T *operator->();
121 constexpr T const &operator*() const &;
122 constexpr T &operator*() &;
123 constexpr T &&operator*() &&;
124 constexpr const T &&operator*() const &&;
125 constexpr explicit operator bool() const noexcept;
126 constexpr bool has_value() const noexcept;
127 constexpr T const &value() const &;
128 constexpr T &value() &;
129 constexpr T &&value() &&;
130 constexpr const T &&value() const &&;
131 template <class U> constexpr T value_or(U &&) const &;
132 template <class U> constexpr T value_or(U &&) &&;
133
134 // 20.6.3.6, modifiers
135 void reset() noexcept;
136
137 private:
138 T *val; // exposition only
139 };
140} // namespace std
141
142*/
143
144#include <__config>
145#include <__debug>
146#include <__functional_base>
147#include <__undef_min_max>
148#include <functional>
149#include <initializer_list>
150#include <new>
151#include <stdexcept>
152#include <type_traits>
153#include <utility>
154
155#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
156#pragma GCC system_header
157#endif
158
159namespace std // purposefully not using versioning namespace
160{
161
162class _LIBCPP_EXCEPTION_ABI bad_optional_access
Marshall Clowa627d4a2017-02-05 20:06:38 +0000163 : public exception
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000164{
165public:
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000166 // Get the key function ~bad_optional_access() into the dylib
Marshall Clow53fc0372017-02-05 20:52:32 +0000167 virtual ~bad_optional_access() _NOEXCEPT;
Marshall Clowa627d4a2017-02-05 20:06:38 +0000168 virtual const char* what() const _NOEXCEPT;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000169};
170
171} // std
172
173#if _LIBCPP_STD_VER > 14
174
175_LIBCPP_BEGIN_NAMESPACE_STD
176
177_LIBCPP_NORETURN
178inline _LIBCPP_INLINE_VISIBILITY
179void __throw_bad_optional_access() {
180#ifndef _LIBCPP_NO_EXCEPTIONS
181 throw bad_optional_access();
182#else
183 _VSTD::abort();
184#endif
185}
186
187struct nullopt_t
188{
189 struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
190 _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
191};
192
193/* inline */ constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
194
195template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
196struct __optional_destruct_base;
197
198template <class _Tp>
199struct __optional_destruct_base<_Tp, false>
200{
201 typedef _Tp value_type;
202 static_assert(is_object_v<value_type>,
203 "instantiation of optional with a non-object type is undefined behavior");
204 union
205 {
206 char __null_state_;
207 value_type __val_;
208 };
209 bool __engaged_;
210
211 _LIBCPP_INLINE_VISIBILITY
212 ~__optional_destruct_base()
213 {
214 if (__engaged_)
215 __val_.~value_type();
216 }
217
218 _LIBCPP_INLINE_VISIBILITY
219 constexpr __optional_destruct_base() noexcept
220 : __null_state_(),
221 __engaged_(false) {}
222
223 template <class... _Args>
224 _LIBCPP_INLINE_VISIBILITY
225 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
226 : __val_(_VSTD::forward<_Args>(__args)...),
227 __engaged_(true) {}
228
229 _LIBCPP_INLINE_VISIBILITY
230 void reset() noexcept
231 {
232 if (__engaged_)
233 {
234 __val_.~value_type();
235 __engaged_ = false;
236 }
237 }
238};
239
240template <class _Tp>
241struct __optional_destruct_base<_Tp, true>
242{
243 typedef _Tp value_type;
244 static_assert(is_object_v<value_type>,
245 "instantiation of optional with a non-object type is undefined behavior");
246 union
247 {
248 char __null_state_;
249 value_type __val_;
250 };
251 bool __engaged_;
252
253 _LIBCPP_INLINE_VISIBILITY
254 constexpr __optional_destruct_base() noexcept
255 : __null_state_(),
256 __engaged_(false) {}
257
258 template <class... _Args>
259 _LIBCPP_INLINE_VISIBILITY
260 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
261 : __val_(_VSTD::forward<_Args>(__args)...),
262 __engaged_(true) {}
263
264 _LIBCPP_INLINE_VISIBILITY
265 void reset() noexcept
266 {
267 if (__engaged_)
268 {
269 __engaged_ = false;
270 }
271 }
272};
273
274template <class _Tp, bool = is_reference<_Tp>::value>
275struct __optional_storage_base : __optional_destruct_base<_Tp>
276{
277 using __base = __optional_destruct_base<_Tp>;
278 using value_type = _Tp;
279 using __base::__base;
280
281 _LIBCPP_INLINE_VISIBILITY
282 constexpr bool has_value() const noexcept
283 {
284 return this->__engaged_;
285 }
286
287 _LIBCPP_INLINE_VISIBILITY
288 constexpr value_type& __get() & noexcept
289 {
290 return this->__val_;
291 }
292 _LIBCPP_INLINE_VISIBILITY
293 constexpr const value_type& __get() const& noexcept
294 {
295 return this->__val_;
296 }
297 _LIBCPP_INLINE_VISIBILITY
298 constexpr value_type&& __get() && noexcept
299 {
300 return _VSTD::move(this->__val_);
301 }
302 _LIBCPP_INLINE_VISIBILITY
303 constexpr const value_type&& __get() const&& noexcept
304 {
305 return _VSTD::move(this->__val_);
306 }
307
308 template <class... _Args>
309 _LIBCPP_INLINE_VISIBILITY
310 void __construct(_Args&&... __args)
311 {
312 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
313 ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
314 this->__engaged_ = true;
315 }
316
317 template <class _That>
318 _LIBCPP_INLINE_VISIBILITY
319 void __construct_from(_That&& __opt)
320 {
321 if (__opt.has_value())
322 __construct(_VSTD::forward<_That>(__opt).__get());
323 }
324
325 template <class _That>
326 _LIBCPP_INLINE_VISIBILITY
327 void __assign_from(_That&& __opt)
328 {
329 if (this->__engaged_ == __opt.has_value())
330 {
331 if (this->__engaged_)
332 this->__val_ = _VSTD::forward<_That>(__opt).__get();
333 }
334 else
335 {
336 if (this->__engaged_)
337 this->reset();
338 else
339 __construct(_VSTD::forward<_That>(__opt).__get());
340 }
341 }
342};
343
344// optional<T&> is currently required ill-formed, however it may to be in the
345// future. For this reason it has already been implemented to ensure we can
346// make the change in an ABI compatible manner.
347template <class _Tp>
348struct __optional_storage_base<_Tp, true>
349{
350 using value_type = _Tp;
351 using __raw_type = remove_reference_t<_Tp>;
352 __raw_type* __value_;
353
354 template <class _Up>
355 static constexpr bool __can_bind_reference() {
356 using _RawUp = typename remove_reference<_Up>::type;
357 using _UpPtr = _RawUp*;
358 using _RawTp = typename remove_reference<_Tp>::type;
359 using _TpPtr = _RawTp*;
360 using _CheckLValueArg = integral_constant<bool,
361 (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
362 || is_same<_RawUp, reference_wrapper<_RawTp>>::value
363 || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
364 >;
365 return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
366 || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
367 is_convertible<_UpPtr, _TpPtr>::value);
368 }
369
370 _LIBCPP_INLINE_VISIBILITY
371 constexpr __optional_storage_base() noexcept
372 : __value_(nullptr) {}
373
374 template <class _UArg>
375 _LIBCPP_INLINE_VISIBILITY
376 constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
377 : __value_(_VSTD::addressof(__uarg))
378 {
379 static_assert(__can_bind_reference<_UArg>(),
380 "Attempted to construct a reference element in tuple from a "
381 "possible temporary");
382 }
383
384 _LIBCPP_INLINE_VISIBILITY
385 void reset() noexcept { __value_ = nullptr; }
386
387 _LIBCPP_INLINE_VISIBILITY
388 constexpr bool has_value() const noexcept
389 { return __value_ != nullptr; }
390
391 _LIBCPP_INLINE_VISIBILITY
392 constexpr value_type& __get() const& noexcept
393 { return *__value_; }
394
395 _LIBCPP_INLINE_VISIBILITY
396 constexpr value_type&& __get() const&& noexcept
397 { return _VSTD::forward<value_type>(*__value_); }
398
399 template <class _UArg>
400 _LIBCPP_INLINE_VISIBILITY
401 void __construct(_UArg&& __val)
402 {
403 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
404 static_assert(__can_bind_reference<_UArg>(),
405 "Attempted to construct a reference element in tuple from a "
406 "possible temporary");
407 __value_ = _VSTD::addressof(__val);
408 }
409
410 template <class _That>
411 _LIBCPP_INLINE_VISIBILITY
412 void __construct_from(_That&& __opt)
413 {
414 if (__opt.has_value())
415 __construct(_VSTD::forward<_That>(__opt).__get());
416 }
417
418 template <class _That>
419 _LIBCPP_INLINE_VISIBILITY
420 void __assign_from(_That&& __opt)
421 {
422 if (has_value() == __opt.has_value())
423 {
424 if (has_value())
425 *__value_ = _VSTD::forward<_That>(__opt).__get();
426 }
427 else
428 {
429 if (has_value())
430 reset();
431 else
432 __construct(_VSTD::forward<_That>(__opt).__get());
433 }
434 }
435};
436
437template <class _Tp, bool = is_trivially_copyable<_Tp>::value>
438struct __optional_storage;
439
440template <class _Tp>
441struct __optional_storage<_Tp, true> : __optional_storage_base<_Tp>
442{
443 using __optional_storage_base<_Tp>::__optional_storage_base;
444};
445
446template <class _Tp>
447struct __optional_storage<_Tp, false> : __optional_storage_base<_Tp>
448{
449 using value_type = _Tp;
450 using __optional_storage_base<_Tp>::__optional_storage_base;
451
452 _LIBCPP_INLINE_VISIBILITY
453 __optional_storage() = default;
454
455 _LIBCPP_INLINE_VISIBILITY
456 __optional_storage(const __optional_storage& __opt)
457 {
458 this->__construct_from(__opt);
459 }
460
461 _LIBCPP_INLINE_VISIBILITY
462 __optional_storage(__optional_storage&& __opt)
463 noexcept(is_nothrow_move_constructible_v<value_type>)
464 {
465 this->__construct_from(_VSTD::move(__opt));
466 }
467
468 _LIBCPP_INLINE_VISIBILITY
469 __optional_storage& operator=(const __optional_storage& __opt)
470 {
471 this->__assign_from(__opt);
472 return *this;
473 }
474
475 _LIBCPP_INLINE_VISIBILITY
476 __optional_storage& operator=(__optional_storage&& __opt)
477 noexcept(is_nothrow_move_assignable_v<value_type> &&
478 is_nothrow_move_constructible_v<value_type>)
479 {
480 this->__assign_from(_VSTD::move(__opt));
481 return *this;
482 }
483};
484
485template <class _Tp>
486using __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
487 is_copy_constructible<_Tp>::value,
488 is_move_constructible<_Tp>::value
489>;
490
491template <class _Tp>
492using __optional_sfinae_assign_base_t = __sfinae_assign_base<
493 (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
494 (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
495>;
496
497template <class _Tp>
498class optional
499 : private __optional_storage<_Tp>
500 , private __optional_sfinae_ctor_base_t<_Tp>
501 , private __optional_sfinae_assign_base_t<_Tp>
502{
503 using __base = __optional_storage<_Tp>;
504public:
505 using value_type = _Tp;
506
507private:
508 // Disable the reference extension using this static assert.
509 static_assert(!is_same_v<value_type, in_place_t>,
510 "instantiation of optional with in_place_t is ill-formed");
511 static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
512 "instantiation of optional with nullopt_t is ill-formed");
513 static_assert(!is_reference_v<value_type>,
514 "instantiation of optional with a reference type is ill-formed");
515 static_assert(is_destructible_v<value_type>,
516 "instantiation of optional with a non-destructible type is ill-formed");
517
518 // LWG2756: conditionally explicit conversion from _Up
519 struct _CheckOptionalArgsConstructor {
520 template <class _Up>
521 static constexpr bool __enable_implicit() {
522 return is_constructible_v<_Tp, _Up&&> &&
523 is_convertible_v<_Up&&, _Tp>;
524 }
525
526 template <class _Up>
527 static constexpr bool __enable_explicit() {
528 return is_constructible_v<_Tp, _Up&&> &&
529 !is_convertible_v<_Up&&, _Tp>;
530 }
531 };
532 template <class _Up>
533 using _CheckOptionalArgsCtor = conditional_t<
Eric Fiselierf7b1d302017-03-30 19:43:50 +0000534 !is_same_v<decay_t<_Up>, in_place_t> &&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000535 !is_same_v<decay_t<_Up>, optional>,
536 _CheckOptionalArgsConstructor,
537 __check_tuple_constructor_fail
538 >;
539 template <class _QualUp>
540 struct _CheckOptionalLikeConstructor {
541 template <class _Up, class _Opt = optional<_Up>>
542 using __check_constructible_from_opt = __lazy_or<
543 is_constructible<_Tp, _Opt&>,
544 is_constructible<_Tp, _Opt const&>,
545 is_constructible<_Tp, _Opt&&>,
546 is_constructible<_Tp, _Opt const&&>,
547 is_convertible<_Opt&, _Tp>,
548 is_convertible<_Opt const&, _Tp>,
549 is_convertible<_Opt&&, _Tp>,
550 is_convertible<_Opt const&&, _Tp>
551 >;
552 template <class _Up, class _Opt = optional<_Up>>
553 using __check_assignable_from_opt = __lazy_or<
554 is_assignable<_Tp&, _Opt&>,
555 is_assignable<_Tp&, _Opt const&>,
556 is_assignable<_Tp&, _Opt&&>,
557 is_assignable<_Tp&, _Opt const&&>
558 >;
559 template <class _Up, class _QUp = _QualUp>
560 static constexpr bool __enable_implicit() {
561 return is_convertible<_QUp, _Tp>::value &&
562 !__check_constructible_from_opt<_Up>::value;
563 }
564 template <class _Up, class _QUp = _QualUp>
565 static constexpr bool __enable_explicit() {
566 return !is_convertible<_QUp, _Tp>::value &&
567 !__check_constructible_from_opt<_Up>::value;
568 }
569 template <class _Up, class _QUp = _QualUp>
570 static constexpr bool __enable_assign() {
571 // Construction and assignability of _Qup to _Tp has already been
572 // checked.
573 return !__check_constructible_from_opt<_Up>::value &&
574 !__check_assignable_from_opt<_Up>::value;
575 }
576 };
577
578 template <class _Up, class _QualUp>
579 using _CheckOptionalLikeCtor = conditional_t<
580 __lazy_and<
581 __lazy_not<is_same<_Up, _Tp>>,
582 is_constructible<_Tp, _QualUp>
583 >::value,
584 _CheckOptionalLikeConstructor<_QualUp>,
585 __check_tuple_constructor_fail
586 >;
587 template <class _Up, class _QualUp>
588 using _CheckOptionalLikeAssign = conditional_t<
589 __lazy_and<
590 __lazy_not<is_same<_Up, _Tp>>,
591 is_constructible<_Tp, _QualUp>,
592 is_assignable<_Tp&, _QualUp>
593 >::value,
594 _CheckOptionalLikeConstructor<_QualUp>,
595 __check_tuple_constructor_fail
596 >;
597public:
598
599 _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
600 _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default;
601 _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default;
602 _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
603
604 template <class... _Args, class = enable_if_t<
605 is_constructible_v<value_type, _Args...>>
606 >
607 _LIBCPP_INLINE_VISIBILITY
608 constexpr explicit optional(in_place_t, _Args&&... __args)
609 : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
610
611 template <class _Up, class... _Args, class = enable_if_t<
612 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
613 >
614 _LIBCPP_INLINE_VISIBILITY
615 constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
616 : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
617
618 template <class _Up = value_type, enable_if_t<
619 _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
620 , int> = 0>
621 _LIBCPP_INLINE_VISIBILITY
622 constexpr optional(_Up&& __v)
623 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
624
625 template <class _Up, enable_if_t<
626 _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
627 , int> = 0>
628 _LIBCPP_INLINE_VISIBILITY
629 constexpr explicit optional(_Up&& __v)
630 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
631
632 // LWG2756: conditionally explicit conversion from const optional<_Up>&
633 template <class _Up, enable_if_t<
634 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
635 , int> = 0>
636 _LIBCPP_INLINE_VISIBILITY
637 optional(const optional<_Up>& __v)
638 {
639 this->__construct_from(__v);
640 }
641 template <class _Up, enable_if_t<
642 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
643 , int> = 0>
644 _LIBCPP_INLINE_VISIBILITY
645 explicit optional(const optional<_Up>& __v)
646 {
647 this->__construct_from(__v);
648 }
649
650 // LWG2756: conditionally explicit conversion from optional<_Up>&&
651 template <class _Up, enable_if_t<
652 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
653 , int> = 0>
654 _LIBCPP_INLINE_VISIBILITY
655 optional(optional<_Up>&& __v)
656 {
657 this->__construct_from(_VSTD::move(__v));
658 }
659 template <class _Up, enable_if_t<
660 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
661 , int> = 0>
662 _LIBCPP_INLINE_VISIBILITY
663 explicit optional(optional<_Up>&& __v)
664 {
665 this->__construct_from(_VSTD::move(__v));
666 }
667
668 _LIBCPP_INLINE_VISIBILITY
669 optional& operator=(nullopt_t) noexcept
670 {
671 reset();
672 return *this;
673 }
674
675 _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
676 _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
677
678 // LWG2756
679 template <class _Up = value_type,
680 class = enable_if_t
Eric Fiselierb9014262016-10-16 03:21:35 +0000681 <__lazy_and<
682 integral_constant<bool,
683 !is_same_v<decay_t<_Up>, optional> &&
684 !(is_same_v<_Up, value_type> && is_scalar_v<value_type>)
685 >,
686 is_constructible<value_type, _Up>,
687 is_assignable<value_type&, _Up>
688 >::value>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000689 >
690 _LIBCPP_INLINE_VISIBILITY
691 optional&
692 operator=(_Up&& __v)
693 {
694 if (this->has_value())
695 this->__get() = _VSTD::forward<_Up>(__v);
696 else
697 this->__construct(_VSTD::forward<_Up>(__v));
698 return *this;
699 }
700
701 // LWG2756
702 template <class _Up, enable_if_t<
703 _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
704 , int> = 0>
705 _LIBCPP_INLINE_VISIBILITY
706 optional&
707 operator=(const optional<_Up>& __v)
708 {
709 this->__assign_from(__v);
710 return *this;
711 }
712
713 // LWG2756
714 template <class _Up, enable_if_t<
715 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
716 , int> = 0>
717 _LIBCPP_INLINE_VISIBILITY
718 optional&
719 operator=(optional<_Up>&& __v)
720 {
721 this->__assign_from(_VSTD::move(__v));
722 return *this;
723 }
724
725 template <class... _Args,
726 class = enable_if_t
727 <
728 is_constructible_v<value_type, _Args...>
729 >
730 >
731 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000732 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000733 emplace(_Args&&... __args)
734 {
735 reset();
736 this->__construct(_VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000737 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000738 }
739
740 template <class _Up, class... _Args,
741 class = enable_if_t
742 <
743 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
744 >
745 >
746 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000747 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000748 emplace(initializer_list<_Up> __il, _Args&&... __args)
749 {
750 reset();
751 this->__construct(__il, _VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000752 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000753 }
754
755 _LIBCPP_INLINE_VISIBILITY
756 void swap(optional& __opt)
757 noexcept(is_nothrow_move_constructible_v<value_type> &&
758 is_nothrow_swappable_v<value_type>)
759 {
760 if (this->has_value() == __opt.has_value())
761 {
762 using _VSTD::swap;
763 if (this->has_value())
764 swap(this->__get(), __opt.__get());
765 }
766 else
767 {
768 if (this->has_value())
769 {
770 __opt.__construct(_VSTD::move(this->__get()));
771 reset();
772 }
773 else
774 {
775 this->__construct(_VSTD::move(__opt.__get()));
776 __opt.reset();
777 }
778 }
779 }
780
781 _LIBCPP_INLINE_VISIBILITY
782 constexpr
783 add_pointer_t<value_type const>
784 operator->() const
785 {
786 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
787#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
788 return _VSTD::addressof(this->__get());
789#else
790 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
791#endif
792 }
793
794 _LIBCPP_INLINE_VISIBILITY
795 constexpr
796 add_pointer_t<value_type>
797 operator->()
798 {
799 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
800#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
801 return _VSTD::addressof(this->__get());
802#else
803 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
804#endif
805 }
806
807 _LIBCPP_INLINE_VISIBILITY
808 constexpr
809 const value_type&
810 operator*() const&
811 {
812 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
813 return this->__get();
814 }
815
816 _LIBCPP_INLINE_VISIBILITY
817 constexpr
818 value_type&
819 operator*() &
820 {
821 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
822 return this->__get();
823 }
824
825 _LIBCPP_INLINE_VISIBILITY
826 constexpr
827 value_type&&
828 operator*() &&
829 {
830 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
831 return _VSTD::move(this->__get());
832 }
833
834 _LIBCPP_INLINE_VISIBILITY
835 constexpr
836 const value_type&&
837 operator*() const&&
838 {
839 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
840 return _VSTD::move(this->__get());
841 }
842
843 _LIBCPP_INLINE_VISIBILITY
844 constexpr explicit operator bool() const noexcept { return has_value(); }
845
846 using __base::has_value;
847 using __base::__get;
848
849 _LIBCPP_INLINE_VISIBILITY
850 constexpr value_type const& value() const&
851 {
852 if (!this->has_value())
853 __throw_bad_optional_access();
854 return this->__get();
855 }
856
857 _LIBCPP_INLINE_VISIBILITY
858 constexpr value_type& value() &
859 {
860 if (!this->has_value())
861 __throw_bad_optional_access();
862 return this->__get();
863 }
864
865 _LIBCPP_INLINE_VISIBILITY
866 constexpr value_type&& value() &&
867 {
868 if (!this->has_value())
869 __throw_bad_optional_access();
870 return _VSTD::move(this->__get());
871 }
872
873 _LIBCPP_INLINE_VISIBILITY
874 constexpr value_type const&& value() const&&
875 {
876 if (!this->has_value())
877 __throw_bad_optional_access();
878 return _VSTD::move(this->__get());
879 }
880
881 template <class _Up>
882 _LIBCPP_INLINE_VISIBILITY
883 constexpr value_type value_or(_Up&& __v) const&
884 {
885 static_assert(is_copy_constructible_v<value_type>,
886 "optional<T>::value_or: T must be copy constructible");
887 static_assert(is_convertible_v<_Up, value_type>,
888 "optional<T>::value_or: U must be convertible to T");
889 return this->has_value() ? this->__get() :
890 static_cast<value_type>(_VSTD::forward<_Up>(__v));
891 }
892
893 template <class _Up>
894 _LIBCPP_INLINE_VISIBILITY
895 value_type value_or(_Up&& __v) &&
896 {
897 static_assert(is_move_constructible_v<value_type>,
898 "optional<T>::value_or: T must be move constructible");
899 static_assert(is_convertible_v<_Up, value_type>,
900 "optional<T>::value_or: U must be convertible to T");
901 return this->has_value() ? _VSTD::move(this->__get()) :
902 static_cast<value_type>(_VSTD::forward<_Up>(__v));
903 }
904
905 using __base::reset;
906
907private:
908 template <class _Up>
909 _LIBCPP_INLINE_VISIBILITY
910 static _Up*
911 __operator_arrow(true_type, _Up& __x)
912 {
913 return _VSTD::addressof(__x);
914 }
915
916 template <class _Up>
917 _LIBCPP_INLINE_VISIBILITY
918 static constexpr _Up*
919 __operator_arrow(false_type, _Up& __x)
920 {
921 return &__x;
922 }
923};
924
925// Comparisons between optionals
Eric Fiselier8af90142017-03-30 20:06:52 +0000926template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000927_LIBCPP_INLINE_VISIBILITY constexpr
928enable_if_t<
929 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +0000930 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000931 bool
932>
Eric Fiselier8af90142017-03-30 20:06:52 +0000933operator==(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000934{
935 if (static_cast<bool>(__x) != static_cast<bool>(__y))
936 return false;
937 if (!static_cast<bool>(__x))
938 return true;
939 return *__x == *__y;
940}
941
Eric Fiselier8af90142017-03-30 20:06:52 +0000942template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000943_LIBCPP_INLINE_VISIBILITY constexpr
944enable_if_t<
945 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +0000946 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000947 bool
948>
Eric Fiselier8af90142017-03-30 20:06:52 +0000949operator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000950{
951 if (static_cast<bool>(__x) != static_cast<bool>(__y))
952 return true;
953 if (!static_cast<bool>(__x))
954 return false;
955 return *__x != *__y;
956}
957
Eric Fiselier8af90142017-03-30 20:06:52 +0000958template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000959_LIBCPP_INLINE_VISIBILITY constexpr
960enable_if_t<
961 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +0000962 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000963 bool
964>
Eric Fiselier8af90142017-03-30 20:06:52 +0000965operator<(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000966{
967 if (!static_cast<bool>(__y))
968 return false;
969 if (!static_cast<bool>(__x))
970 return true;
971 return *__x < *__y;
972}
973
Eric Fiselier8af90142017-03-30 20:06:52 +0000974template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000975_LIBCPP_INLINE_VISIBILITY constexpr
976enable_if_t<
977 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +0000978 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000979 bool
980>
Eric Fiselier8af90142017-03-30 20:06:52 +0000981operator>(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000982{
983 if (!static_cast<bool>(__x))
984 return false;
985 if (!static_cast<bool>(__y))
986 return true;
987 return *__x > *__y;
988}
989
Eric Fiselier8af90142017-03-30 20:06:52 +0000990template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000991_LIBCPP_INLINE_VISIBILITY constexpr
992enable_if_t<
993 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +0000994 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000995 bool
996>
Eric Fiselier8af90142017-03-30 20:06:52 +0000997operator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000998{
999 if (!static_cast<bool>(__x))
1000 return true;
1001 if (!static_cast<bool>(__y))
1002 return false;
1003 return *__x <= *__y;
1004}
1005
Eric Fiselier8af90142017-03-30 20:06:52 +00001006template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001007_LIBCPP_INLINE_VISIBILITY constexpr
1008enable_if_t<
1009 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001010 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001011 bool
1012>
Eric Fiselier8af90142017-03-30 20:06:52 +00001013operator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001014{
1015 if (!static_cast<bool>(__y))
1016 return true;
1017 if (!static_cast<bool>(__x))
1018 return false;
1019 return *__x >= *__y;
1020}
1021
1022// Comparisons with nullopt
1023template <class _Tp>
1024_LIBCPP_INLINE_VISIBILITY constexpr
1025bool
1026operator==(const optional<_Tp>& __x, nullopt_t) noexcept
1027{
1028 return !static_cast<bool>(__x);
1029}
1030
1031template <class _Tp>
1032_LIBCPP_INLINE_VISIBILITY constexpr
1033bool
1034operator==(nullopt_t, const optional<_Tp>& __x) noexcept
1035{
1036 return !static_cast<bool>(__x);
1037}
1038
1039template <class _Tp>
1040_LIBCPP_INLINE_VISIBILITY constexpr
1041bool
1042operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
1043{
1044 return static_cast<bool>(__x);
1045}
1046
1047template <class _Tp>
1048_LIBCPP_INLINE_VISIBILITY constexpr
1049bool
1050operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
1051{
1052 return static_cast<bool>(__x);
1053}
1054
1055template <class _Tp>
1056_LIBCPP_INLINE_VISIBILITY constexpr
1057bool
1058operator<(const optional<_Tp>&, nullopt_t) noexcept
1059{
1060 return false;
1061}
1062
1063template <class _Tp>
1064_LIBCPP_INLINE_VISIBILITY constexpr
1065bool
1066operator<(nullopt_t, const optional<_Tp>& __x) noexcept
1067{
1068 return static_cast<bool>(__x);
1069}
1070
1071template <class _Tp>
1072_LIBCPP_INLINE_VISIBILITY constexpr
1073bool
1074operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
1075{
1076 return !static_cast<bool>(__x);
1077}
1078
1079template <class _Tp>
1080_LIBCPP_INLINE_VISIBILITY constexpr
1081bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001082operator<=(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001083{
1084 return true;
1085}
1086
1087template <class _Tp>
1088_LIBCPP_INLINE_VISIBILITY constexpr
1089bool
1090operator>(const optional<_Tp>& __x, nullopt_t) noexcept
1091{
1092 return static_cast<bool>(__x);
1093}
1094
1095template <class _Tp>
1096_LIBCPP_INLINE_VISIBILITY constexpr
1097bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001098operator>(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001099{
1100 return false;
1101}
1102
1103template <class _Tp>
1104_LIBCPP_INLINE_VISIBILITY constexpr
1105bool
1106operator>=(const optional<_Tp>&, nullopt_t) noexcept
1107{
1108 return true;
1109}
1110
1111template <class _Tp>
1112_LIBCPP_INLINE_VISIBILITY constexpr
1113bool
1114operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1115{
1116 return !static_cast<bool>(__x);
1117}
1118
1119// Comparisons with T
Eric Fiselier8af90142017-03-30 20:06:52 +00001120template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001121_LIBCPP_INLINE_VISIBILITY constexpr
1122enable_if_t<
1123 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001124 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001125 bool
1126>
Eric Fiselier8af90142017-03-30 20:06:52 +00001127operator==(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001128{
1129 return static_cast<bool>(__x) ? *__x == __v : false;
1130}
1131
Eric Fiselier8af90142017-03-30 20:06:52 +00001132template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001133_LIBCPP_INLINE_VISIBILITY constexpr
1134enable_if_t<
1135 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001136 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001137 bool
1138>
Eric Fiselier8af90142017-03-30 20:06:52 +00001139operator==(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001140{
1141 return static_cast<bool>(__x) ? __v == *__x : false;
1142}
1143
Eric Fiselier8af90142017-03-30 20:06:52 +00001144template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001145_LIBCPP_INLINE_VISIBILITY constexpr
1146enable_if_t<
1147 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001148 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001149 bool
1150>
Eric Fiselier8af90142017-03-30 20:06:52 +00001151operator!=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001152{
1153 return static_cast<bool>(__x) ? *__x != __v : true;
1154}
1155
Eric Fiselier8af90142017-03-30 20:06:52 +00001156template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001157_LIBCPP_INLINE_VISIBILITY constexpr
1158enable_if_t<
1159 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001160 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001161 bool
1162>
Eric Fiselier8af90142017-03-30 20:06:52 +00001163operator!=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001164{
1165 return static_cast<bool>(__x) ? __v != *__x : true;
1166}
1167
Eric Fiselier8af90142017-03-30 20:06:52 +00001168template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001169_LIBCPP_INLINE_VISIBILITY constexpr
1170enable_if_t<
1171 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001172 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001173 bool
1174>
Eric Fiselier8af90142017-03-30 20:06:52 +00001175operator<(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001176{
1177 return static_cast<bool>(__x) ? *__x < __v : true;
1178}
1179
Eric Fiselier8af90142017-03-30 20:06:52 +00001180template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001181_LIBCPP_INLINE_VISIBILITY constexpr
1182enable_if_t<
1183 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001184 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001185 bool
1186>
Eric Fiselier8af90142017-03-30 20:06:52 +00001187operator<(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001188{
1189 return static_cast<bool>(__x) ? __v < *__x : false;
1190}
1191
Eric Fiselier8af90142017-03-30 20:06:52 +00001192template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001193_LIBCPP_INLINE_VISIBILITY constexpr
1194enable_if_t<
1195 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001196 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001197 bool
1198>
Eric Fiselier8af90142017-03-30 20:06:52 +00001199operator<=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001200{
1201 return static_cast<bool>(__x) ? *__x <= __v : true;
1202}
1203
Eric Fiselier8af90142017-03-30 20:06:52 +00001204template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001205_LIBCPP_INLINE_VISIBILITY constexpr
1206enable_if_t<
1207 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001208 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001209 bool
1210>
Eric Fiselier8af90142017-03-30 20:06:52 +00001211operator<=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001212{
1213 return static_cast<bool>(__x) ? __v <= *__x : false;
1214}
1215
Eric Fiselier8af90142017-03-30 20:06:52 +00001216template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001217_LIBCPP_INLINE_VISIBILITY constexpr
1218enable_if_t<
1219 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001220 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001221 bool
1222>
Eric Fiselier8af90142017-03-30 20:06:52 +00001223operator>(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001224{
1225 return static_cast<bool>(__x) ? *__x > __v : false;
1226}
1227
Eric Fiselier8af90142017-03-30 20:06:52 +00001228template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001229_LIBCPP_INLINE_VISIBILITY constexpr
1230enable_if_t<
1231 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001232 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001233 bool
1234>
Eric Fiselier8af90142017-03-30 20:06:52 +00001235operator>(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001236{
1237 return static_cast<bool>(__x) ? __v > *__x : true;
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
1242enable_if_t<
1243 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001244 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001245 bool
1246>
Eric Fiselier8af90142017-03-30 20:06:52 +00001247operator>=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001248{
1249 return static_cast<bool>(__x) ? *__x >= __v : 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
1254enable_if_t<
1255 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001256 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001257 bool
1258>
Eric Fiselier8af90142017-03-30 20:06:52 +00001259operator>=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001260{
1261 return static_cast<bool>(__x) ? __v >= *__x : true;
1262}
1263
1264
1265template <class _Tp>
1266inline _LIBCPP_INLINE_VISIBILITY
1267enable_if_t<
1268 is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1269 void
1270>
1271swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1272{
1273 __x.swap(__y);
1274}
1275
1276template <class _Tp>
1277_LIBCPP_INLINE_VISIBILITY constexpr
1278optional<decay_t<_Tp>> make_optional(_Tp&& __v)
1279{
1280 return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1281}
1282
1283template <class _Tp, class... _Args>
1284_LIBCPP_INLINE_VISIBILITY constexpr
1285optional<_Tp> make_optional(_Args&&... __args)
1286{
1287 return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1288}
1289
1290template <class _Tp, class _Up, class... _Args>
1291_LIBCPP_INLINE_VISIBILITY constexpr
1292optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args)
1293{
1294 return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1295}
1296
1297template <class _Tp>
Eric Fiselier698a97b2017-01-21 00:02:12 +00001298struct _LIBCPP_TEMPLATE_VIS hash<
1299 __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1300>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001301{
1302 typedef optional<_Tp> argument_type;
1303 typedef size_t result_type;
1304
1305 _LIBCPP_INLINE_VISIBILITY
Marshall Clow49036892017-03-23 02:40:28 +00001306 result_type operator()(const argument_type& __opt) const
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001307 {
Eric Fiselier698a97b2017-01-21 00:02:12 +00001308 return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001309 }
1310};
1311
1312_LIBCPP_END_NAMESPACE_STD
1313
1314#endif // _LIBCPP_STD_VER > 14
1315
1316#endif // _LIBCPP_OPTIONAL