blob: 8c8ee76b1411ea83ab27247d4eac009773a3fe33 [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 {
Casey Carter84b8a402017-04-17 20:15:16 +000020 // 23.6.3, optional for object types
Eric Fiselierd4ec6352016-10-12 07:46:20 +000021 template <class T> class optional;
22
Casey Carter84b8a402017-04-17 20:15:16 +000023 // 23.6.4, no-value state indicator
Eric Fiselierd4ec6352016-10-12 07:46:20 +000024 struct nullopt_t{see below };
25 constexpr nullopt_t nullopt(unspecified );
26
Casey Carter84b8a402017-04-17 20:15:16 +000027 // 23.6.5, class bad_optional_access
Eric Fiselierd4ec6352016-10-12 07:46:20 +000028 class bad_optional_access;
29
Casey Carter84b8a402017-04-17 20:15:16 +000030 // 23.6.6, relational operators
31 template <class T, class U>
32 constexpr bool operator==(const optional<T>&, const optional<U>&);
33 template <class T, class U>
34 constexpr bool operator!=(const optional<T>&, const optional<U>&);
35 template <class T, class U>
36 constexpr bool operator<(const optional<T>&, const optional<U>&);
37 template <class T, class U>
38 constexpr bool operator>(const optional<T>&, const optional<U>&);
39 template <class T, class U>
40 constexpr bool operator<=(const optional<T>&, const optional<U>&);
41 template <class T, class U>
42 constexpr bool operator>=(const optional<T>&, const optional<U>&);
43
44 // 23.6.7 comparison with nullopt
Eric Fiselierd4ec6352016-10-12 07:46:20 +000045 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 template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
56 template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;
57
Casey Carter84b8a402017-04-17 20:15:16 +000058 // 23.6.8, comparison with T
59 template <class T, class U> constexpr bool operator==(const optional<T>&, const U&);
60 template <class T, class U> constexpr bool operator==(const U&, const optional<T>&);
61 template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
62 template <class T, class U> constexpr bool operator!=(const U&, const optional<T>&);
63 template <class T, class U> constexpr bool operator<(const optional<T>&, const U&);
64 template <class T, class U> constexpr bool operator<(const U&, const optional<T>&);
65 template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
66 template <class T, class U> constexpr bool operator<=(const U&, const optional<T>&);
67 template <class T, class U> constexpr bool operator>(const optional<T>&, const U&);
68 template <class T, class U> constexpr bool operator>(const U&, const optional<T>&);
69 template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
70 template <class T, class U> constexpr bool operator>=(const U&, const optional<T>&);
Eric Fiselierd4ec6352016-10-12 07:46:20 +000071
Casey Carter84b8a402017-04-17 20:15:16 +000072 // 23.6.9, specialized algorithms
Eric Fiselierd4ec6352016-10-12 07:46:20 +000073 template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below );
74 template <class T> constexpr optional<see below > make_optional(T&&);
75 template <class T, class... Args>
76 constexpr optional<T> make_optional(Args&&... args);
77 template <class T, class U, class... Args>
78 constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
79
Casey Carter84b8a402017-04-17 20:15:16 +000080 // 23.6.10, hash support
Eric Fiselierd4ec6352016-10-12 07:46:20 +000081 template <class T> struct hash;
82 template <class T> struct hash<optional<T>>;
83
84 template <class T> class optional {
85 public:
86 using value_type = T;
87
Casey Carter84b8a402017-04-17 20:15:16 +000088 // 23.6.3.1, constructors
Eric Fiselierd4ec6352016-10-12 07:46:20 +000089 constexpr optional() noexcept;
90 constexpr optional(nullopt_t) noexcept;
91 optional(const optional &);
Marshall Clow45ff9822017-04-12 22:51:27 +000092 optional(optional &&) noexcept(see below);
Eric Fiselierd4ec6352016-10-12 07:46:20 +000093 template <class... Args> constexpr explicit optional(in_place_t, Args &&...);
94 template <class U, class... Args>
95 constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...);
96 template <class U = T>
97 constexpr EXPLICIT optional(U &&);
98 template <class U>
99 constexpr EXPLICIT optional(const optional<U> &);
100 template <class U>
101 constexpr EXPLICIT optional(optional<U> &&);
102
Casey Carter84b8a402017-04-17 20:15:16 +0000103 // 23.6.3.2, destructor
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000104 ~optional();
105
Casey Carter84b8a402017-04-17 20:15:16 +0000106 // 23.6.3.3, assignment
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000107 optional &operator=(nullopt_t) noexcept;
108 optional &operator=(const optional &);
109 optional &operator=(optional &&) noexcept(see below );
110 template <class U = T> optional &operator=(U &&);
111 template <class U> optional &operator=(const optional<U> &);
112 template <class U> optional &operator=(optional<U> &&);
Marshall Clow45ff9822017-04-12 22:51:27 +0000113 template <class... Args> T& emplace(Args &&...);
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000114 template <class U, class... Args>
Marshall Clow45ff9822017-04-12 22:51:27 +0000115 T& emplace(initializer_list<U>, Args &&...);
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000116
Casey Carter84b8a402017-04-17 20:15:16 +0000117 // 23.6.3.4, swap
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000118 void swap(optional &) noexcept(see below );
119
Casey Carter84b8a402017-04-17 20:15:16 +0000120 // 23.6.3.5, observers
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000121 constexpr T const *operator->() const;
122 constexpr T *operator->();
123 constexpr T const &operator*() const &;
124 constexpr T &operator*() &;
125 constexpr T &&operator*() &&;
126 constexpr const T &&operator*() const &&;
127 constexpr explicit operator bool() const noexcept;
128 constexpr bool has_value() const noexcept;
129 constexpr T const &value() const &;
130 constexpr T &value() &;
131 constexpr T &&value() &&;
132 constexpr const T &&value() const &&;
133 template <class U> constexpr T value_or(U &&) const &;
134 template <class U> constexpr T value_or(U &&) &&;
135
Casey Carter84b8a402017-04-17 20:15:16 +0000136 // 23.6.3.6, modifiers
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000137 void reset() noexcept;
138
139 private:
140 T *val; // exposition only
141 };
142} // namespace std
143
144*/
145
146#include <__config>
147#include <__debug>
148#include <__functional_base>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000149#include <functional>
150#include <initializer_list>
151#include <new>
152#include <stdexcept>
153#include <type_traits>
154#include <utility>
155
156#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
157#pragma GCC system_header
158#endif
159
Eric Fiselierf4433a32017-05-31 22:07:49 +0000160_LIBCPP_PUSH_MACROS
161#include <__undef_macros>
162
163
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000164namespace std // purposefully not using versioning namespace
165{
166
167class _LIBCPP_EXCEPTION_ABI bad_optional_access
Marshall Clowa627d4a2017-02-05 20:06:38 +0000168 : public exception
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000169{
170public:
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000171 // Get the key function ~bad_optional_access() into the dylib
Marshall Clow53fc0372017-02-05 20:52:32 +0000172 virtual ~bad_optional_access() _NOEXCEPT;
Marshall Clowa627d4a2017-02-05 20:06:38 +0000173 virtual const char* what() const _NOEXCEPT;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000174};
175
176} // std
177
178#if _LIBCPP_STD_VER > 14
179
180_LIBCPP_BEGIN_NAMESPACE_STD
181
182_LIBCPP_NORETURN
183inline _LIBCPP_INLINE_VISIBILITY
184void __throw_bad_optional_access() {
185#ifndef _LIBCPP_NO_EXCEPTIONS
186 throw bad_optional_access();
187#else
188 _VSTD::abort();
189#endif
190}
191
192struct nullopt_t
193{
194 struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
195 _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
196};
197
198/* inline */ constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
199
200template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
201struct __optional_destruct_base;
202
203template <class _Tp>
204struct __optional_destruct_base<_Tp, false>
205{
206 typedef _Tp value_type;
207 static_assert(is_object_v<value_type>,
208 "instantiation of optional with a non-object type is undefined behavior");
209 union
210 {
211 char __null_state_;
212 value_type __val_;
213 };
214 bool __engaged_;
215
216 _LIBCPP_INLINE_VISIBILITY
217 ~__optional_destruct_base()
218 {
219 if (__engaged_)
220 __val_.~value_type();
221 }
222
223 _LIBCPP_INLINE_VISIBILITY
224 constexpr __optional_destruct_base() noexcept
225 : __null_state_(),
226 __engaged_(false) {}
227
228 template <class... _Args>
229 _LIBCPP_INLINE_VISIBILITY
230 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
231 : __val_(_VSTD::forward<_Args>(__args)...),
232 __engaged_(true) {}
233
234 _LIBCPP_INLINE_VISIBILITY
235 void reset() noexcept
236 {
237 if (__engaged_)
238 {
239 __val_.~value_type();
240 __engaged_ = false;
241 }
242 }
243};
244
245template <class _Tp>
246struct __optional_destruct_base<_Tp, true>
247{
248 typedef _Tp value_type;
249 static_assert(is_object_v<value_type>,
250 "instantiation of optional with a non-object type is undefined behavior");
251 union
252 {
253 char __null_state_;
254 value_type __val_;
255 };
256 bool __engaged_;
257
258 _LIBCPP_INLINE_VISIBILITY
259 constexpr __optional_destruct_base() noexcept
260 : __null_state_(),
261 __engaged_(false) {}
262
263 template <class... _Args>
264 _LIBCPP_INLINE_VISIBILITY
265 constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
266 : __val_(_VSTD::forward<_Args>(__args)...),
267 __engaged_(true) {}
268
269 _LIBCPP_INLINE_VISIBILITY
270 void reset() noexcept
271 {
272 if (__engaged_)
273 {
274 __engaged_ = false;
275 }
276 }
277};
278
279template <class _Tp, bool = is_reference<_Tp>::value>
280struct __optional_storage_base : __optional_destruct_base<_Tp>
281{
282 using __base = __optional_destruct_base<_Tp>;
283 using value_type = _Tp;
284 using __base::__base;
285
286 _LIBCPP_INLINE_VISIBILITY
287 constexpr bool has_value() const noexcept
288 {
289 return this->__engaged_;
290 }
291
292 _LIBCPP_INLINE_VISIBILITY
293 constexpr value_type& __get() & noexcept
294 {
295 return this->__val_;
296 }
297 _LIBCPP_INLINE_VISIBILITY
298 constexpr const value_type& __get() const& noexcept
299 {
300 return this->__val_;
301 }
302 _LIBCPP_INLINE_VISIBILITY
303 constexpr value_type&& __get() && noexcept
304 {
305 return _VSTD::move(this->__val_);
306 }
307 _LIBCPP_INLINE_VISIBILITY
308 constexpr const value_type&& __get() const&& noexcept
309 {
310 return _VSTD::move(this->__val_);
311 }
312
313 template <class... _Args>
314 _LIBCPP_INLINE_VISIBILITY
315 void __construct(_Args&&... __args)
316 {
317 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
318 ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
319 this->__engaged_ = true;
320 }
321
322 template <class _That>
323 _LIBCPP_INLINE_VISIBILITY
324 void __construct_from(_That&& __opt)
325 {
326 if (__opt.has_value())
327 __construct(_VSTD::forward<_That>(__opt).__get());
328 }
329
330 template <class _That>
331 _LIBCPP_INLINE_VISIBILITY
332 void __assign_from(_That&& __opt)
333 {
334 if (this->__engaged_ == __opt.has_value())
335 {
336 if (this->__engaged_)
337 this->__val_ = _VSTD::forward<_That>(__opt).__get();
338 }
339 else
340 {
341 if (this->__engaged_)
342 this->reset();
343 else
344 __construct(_VSTD::forward<_That>(__opt).__get());
345 }
346 }
347};
348
349// optional<T&> is currently required ill-formed, however it may to be in the
350// future. For this reason it has already been implemented to ensure we can
351// make the change in an ABI compatible manner.
352template <class _Tp>
353struct __optional_storage_base<_Tp, true>
354{
355 using value_type = _Tp;
356 using __raw_type = remove_reference_t<_Tp>;
357 __raw_type* __value_;
358
359 template <class _Up>
360 static constexpr bool __can_bind_reference() {
361 using _RawUp = typename remove_reference<_Up>::type;
362 using _UpPtr = _RawUp*;
363 using _RawTp = typename remove_reference<_Tp>::type;
364 using _TpPtr = _RawTp*;
365 using _CheckLValueArg = integral_constant<bool,
366 (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
367 || is_same<_RawUp, reference_wrapper<_RawTp>>::value
368 || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
369 >;
370 return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
371 || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
372 is_convertible<_UpPtr, _TpPtr>::value);
373 }
374
375 _LIBCPP_INLINE_VISIBILITY
376 constexpr __optional_storage_base() noexcept
377 : __value_(nullptr) {}
378
379 template <class _UArg>
380 _LIBCPP_INLINE_VISIBILITY
381 constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
382 : __value_(_VSTD::addressof(__uarg))
383 {
384 static_assert(__can_bind_reference<_UArg>(),
385 "Attempted to construct a reference element in tuple from a "
386 "possible temporary");
387 }
388
389 _LIBCPP_INLINE_VISIBILITY
390 void reset() noexcept { __value_ = nullptr; }
391
392 _LIBCPP_INLINE_VISIBILITY
393 constexpr bool has_value() const noexcept
394 { return __value_ != nullptr; }
395
396 _LIBCPP_INLINE_VISIBILITY
397 constexpr value_type& __get() const& noexcept
398 { return *__value_; }
399
400 _LIBCPP_INLINE_VISIBILITY
401 constexpr value_type&& __get() const&& noexcept
402 { return _VSTD::forward<value_type>(*__value_); }
403
404 template <class _UArg>
405 _LIBCPP_INLINE_VISIBILITY
406 void __construct(_UArg&& __val)
407 {
408 _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
409 static_assert(__can_bind_reference<_UArg>(),
410 "Attempted to construct a reference element in tuple from a "
411 "possible temporary");
412 __value_ = _VSTD::addressof(__val);
413 }
414
415 template <class _That>
416 _LIBCPP_INLINE_VISIBILITY
417 void __construct_from(_That&& __opt)
418 {
419 if (__opt.has_value())
420 __construct(_VSTD::forward<_That>(__opt).__get());
421 }
422
423 template <class _That>
424 _LIBCPP_INLINE_VISIBILITY
425 void __assign_from(_That&& __opt)
426 {
427 if (has_value() == __opt.has_value())
428 {
429 if (has_value())
430 *__value_ = _VSTD::forward<_That>(__opt).__get();
431 }
432 else
433 {
434 if (has_value())
435 reset();
436 else
437 __construct(_VSTD::forward<_That>(__opt).__get());
438 }
439 }
440};
441
442template <class _Tp, bool = is_trivially_copyable<_Tp>::value>
443struct __optional_storage;
444
445template <class _Tp>
446struct __optional_storage<_Tp, true> : __optional_storage_base<_Tp>
447{
448 using __optional_storage_base<_Tp>::__optional_storage_base;
449};
450
451template <class _Tp>
452struct __optional_storage<_Tp, false> : __optional_storage_base<_Tp>
453{
454 using value_type = _Tp;
455 using __optional_storage_base<_Tp>::__optional_storage_base;
456
457 _LIBCPP_INLINE_VISIBILITY
458 __optional_storage() = default;
459
460 _LIBCPP_INLINE_VISIBILITY
461 __optional_storage(const __optional_storage& __opt)
462 {
463 this->__construct_from(__opt);
464 }
465
466 _LIBCPP_INLINE_VISIBILITY
467 __optional_storage(__optional_storage&& __opt)
468 noexcept(is_nothrow_move_constructible_v<value_type>)
469 {
470 this->__construct_from(_VSTD::move(__opt));
471 }
472
473 _LIBCPP_INLINE_VISIBILITY
474 __optional_storage& operator=(const __optional_storage& __opt)
475 {
476 this->__assign_from(__opt);
477 return *this;
478 }
479
480 _LIBCPP_INLINE_VISIBILITY
481 __optional_storage& operator=(__optional_storage&& __opt)
482 noexcept(is_nothrow_move_assignable_v<value_type> &&
483 is_nothrow_move_constructible_v<value_type>)
484 {
485 this->__assign_from(_VSTD::move(__opt));
486 return *this;
487 }
488};
489
490template <class _Tp>
491using __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
492 is_copy_constructible<_Tp>::value,
493 is_move_constructible<_Tp>::value
494>;
495
496template <class _Tp>
497using __optional_sfinae_assign_base_t = __sfinae_assign_base<
498 (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
499 (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value)
500>;
501
502template <class _Tp>
503class optional
504 : private __optional_storage<_Tp>
505 , private __optional_sfinae_ctor_base_t<_Tp>
506 , private __optional_sfinae_assign_base_t<_Tp>
507{
508 using __base = __optional_storage<_Tp>;
509public:
510 using value_type = _Tp;
511
512private:
513 // Disable the reference extension using this static assert.
514 static_assert(!is_same_v<value_type, in_place_t>,
515 "instantiation of optional with in_place_t is ill-formed");
516 static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
517 "instantiation of optional with nullopt_t is ill-formed");
518 static_assert(!is_reference_v<value_type>,
519 "instantiation of optional with a reference type is ill-formed");
520 static_assert(is_destructible_v<value_type>,
521 "instantiation of optional with a non-destructible type is ill-formed");
522
523 // LWG2756: conditionally explicit conversion from _Up
524 struct _CheckOptionalArgsConstructor {
525 template <class _Up>
526 static constexpr bool __enable_implicit() {
527 return is_constructible_v<_Tp, _Up&&> &&
528 is_convertible_v<_Up&&, _Tp>;
529 }
530
531 template <class _Up>
532 static constexpr bool __enable_explicit() {
533 return is_constructible_v<_Tp, _Up&&> &&
534 !is_convertible_v<_Up&&, _Tp>;
535 }
536 };
537 template <class _Up>
538 using _CheckOptionalArgsCtor = conditional_t<
Eric Fiselierf7b1d302017-03-30 19:43:50 +0000539 !is_same_v<decay_t<_Up>, in_place_t> &&
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000540 !is_same_v<decay_t<_Up>, optional>,
541 _CheckOptionalArgsConstructor,
542 __check_tuple_constructor_fail
543 >;
544 template <class _QualUp>
545 struct _CheckOptionalLikeConstructor {
546 template <class _Up, class _Opt = optional<_Up>>
547 using __check_constructible_from_opt = __lazy_or<
548 is_constructible<_Tp, _Opt&>,
549 is_constructible<_Tp, _Opt const&>,
550 is_constructible<_Tp, _Opt&&>,
551 is_constructible<_Tp, _Opt const&&>,
552 is_convertible<_Opt&, _Tp>,
553 is_convertible<_Opt const&, _Tp>,
554 is_convertible<_Opt&&, _Tp>,
555 is_convertible<_Opt const&&, _Tp>
556 >;
557 template <class _Up, class _Opt = optional<_Up>>
558 using __check_assignable_from_opt = __lazy_or<
559 is_assignable<_Tp&, _Opt&>,
560 is_assignable<_Tp&, _Opt const&>,
561 is_assignable<_Tp&, _Opt&&>,
562 is_assignable<_Tp&, _Opt const&&>
563 >;
564 template <class _Up, class _QUp = _QualUp>
565 static constexpr bool __enable_implicit() {
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_explicit() {
571 return !is_convertible<_QUp, _Tp>::value &&
572 !__check_constructible_from_opt<_Up>::value;
573 }
574 template <class _Up, class _QUp = _QualUp>
575 static constexpr bool __enable_assign() {
576 // Construction and assignability of _Qup to _Tp has already been
577 // checked.
578 return !__check_constructible_from_opt<_Up>::value &&
579 !__check_assignable_from_opt<_Up>::value;
580 }
581 };
582
583 template <class _Up, class _QualUp>
584 using _CheckOptionalLikeCtor = conditional_t<
585 __lazy_and<
586 __lazy_not<is_same<_Up, _Tp>>,
587 is_constructible<_Tp, _QualUp>
588 >::value,
589 _CheckOptionalLikeConstructor<_QualUp>,
590 __check_tuple_constructor_fail
591 >;
592 template <class _Up, class _QualUp>
593 using _CheckOptionalLikeAssign = conditional_t<
594 __lazy_and<
595 __lazy_not<is_same<_Up, _Tp>>,
596 is_constructible<_Tp, _QualUp>,
597 is_assignable<_Tp&, _QualUp>
598 >::value,
599 _CheckOptionalLikeConstructor<_QualUp>,
600 __check_tuple_constructor_fail
601 >;
602public:
603
604 _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
Marshall Clowd44e2e32017-05-17 15:30:01 +0000605 _LIBCPP_INLINE_VISIBILITY constexpr optional(const optional&) = default;
606 _LIBCPP_INLINE_VISIBILITY constexpr optional(optional&&) = default;
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000607 _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
608
609 template <class... _Args, class = enable_if_t<
610 is_constructible_v<value_type, _Args...>>
611 >
612 _LIBCPP_INLINE_VISIBILITY
613 constexpr explicit optional(in_place_t, _Args&&... __args)
614 : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
615
616 template <class _Up, class... _Args, class = enable_if_t<
617 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
618 >
619 _LIBCPP_INLINE_VISIBILITY
620 constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
621 : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
622
623 template <class _Up = value_type, enable_if_t<
624 _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
625 , int> = 0>
626 _LIBCPP_INLINE_VISIBILITY
627 constexpr optional(_Up&& __v)
628 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
629
630 template <class _Up, enable_if_t<
631 _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
632 , int> = 0>
633 _LIBCPP_INLINE_VISIBILITY
634 constexpr explicit optional(_Up&& __v)
635 : __base(in_place, _VSTD::forward<_Up>(__v)) {}
636
637 // LWG2756: conditionally explicit conversion from const optional<_Up>&
638 template <class _Up, enable_if_t<
639 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
640 , int> = 0>
641 _LIBCPP_INLINE_VISIBILITY
642 optional(const optional<_Up>& __v)
643 {
644 this->__construct_from(__v);
645 }
646 template <class _Up, enable_if_t<
647 _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
648 , int> = 0>
649 _LIBCPP_INLINE_VISIBILITY
650 explicit optional(const optional<_Up>& __v)
651 {
652 this->__construct_from(__v);
653 }
654
655 // LWG2756: conditionally explicit conversion from optional<_Up>&&
656 template <class _Up, enable_if_t<
657 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
658 , int> = 0>
659 _LIBCPP_INLINE_VISIBILITY
660 optional(optional<_Up>&& __v)
661 {
662 this->__construct_from(_VSTD::move(__v));
663 }
664 template <class _Up, enable_if_t<
665 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
666 , int> = 0>
667 _LIBCPP_INLINE_VISIBILITY
668 explicit optional(optional<_Up>&& __v)
669 {
670 this->__construct_from(_VSTD::move(__v));
671 }
672
673 _LIBCPP_INLINE_VISIBILITY
674 optional& operator=(nullopt_t) noexcept
675 {
676 reset();
677 return *this;
678 }
679
680 _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
681 _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
682
683 // LWG2756
684 template <class _Up = value_type,
685 class = enable_if_t
Eric Fiselierb9014262016-10-16 03:21:35 +0000686 <__lazy_and<
687 integral_constant<bool,
688 !is_same_v<decay_t<_Up>, optional> &&
689 !(is_same_v<_Up, value_type> && is_scalar_v<value_type>)
690 >,
691 is_constructible<value_type, _Up>,
692 is_assignable<value_type&, _Up>
693 >::value>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000694 >
695 _LIBCPP_INLINE_VISIBILITY
696 optional&
697 operator=(_Up&& __v)
698 {
699 if (this->has_value())
700 this->__get() = _VSTD::forward<_Up>(__v);
701 else
702 this->__construct(_VSTD::forward<_Up>(__v));
703 return *this;
704 }
705
706 // LWG2756
707 template <class _Up, enable_if_t<
708 _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
709 , int> = 0>
710 _LIBCPP_INLINE_VISIBILITY
711 optional&
712 operator=(const optional<_Up>& __v)
713 {
714 this->__assign_from(__v);
715 return *this;
716 }
717
718 // LWG2756
719 template <class _Up, enable_if_t<
720 _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
721 , int> = 0>
722 _LIBCPP_INLINE_VISIBILITY
723 optional&
724 operator=(optional<_Up>&& __v)
725 {
726 this->__assign_from(_VSTD::move(__v));
727 return *this;
728 }
729
730 template <class... _Args,
731 class = enable_if_t
732 <
733 is_constructible_v<value_type, _Args...>
734 >
735 >
736 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000737 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000738 emplace(_Args&&... __args)
739 {
740 reset();
741 this->__construct(_VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000742 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000743 }
744
745 template <class _Up, class... _Args,
746 class = enable_if_t
747 <
748 is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
749 >
750 >
751 _LIBCPP_INLINE_VISIBILITY
Marshall Clow45ff9822017-04-12 22:51:27 +0000752 _Tp &
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000753 emplace(initializer_list<_Up> __il, _Args&&... __args)
754 {
755 reset();
756 this->__construct(__il, _VSTD::forward<_Args>(__args)...);
Marshall Clow45ff9822017-04-12 22:51:27 +0000757 return this->__get();
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000758 }
759
760 _LIBCPP_INLINE_VISIBILITY
761 void swap(optional& __opt)
762 noexcept(is_nothrow_move_constructible_v<value_type> &&
763 is_nothrow_swappable_v<value_type>)
764 {
765 if (this->has_value() == __opt.has_value())
766 {
767 using _VSTD::swap;
768 if (this->has_value())
769 swap(this->__get(), __opt.__get());
770 }
771 else
772 {
773 if (this->has_value())
774 {
775 __opt.__construct(_VSTD::move(this->__get()));
776 reset();
777 }
778 else
779 {
780 this->__construct(_VSTD::move(__opt.__get()));
781 __opt.reset();
782 }
783 }
784 }
785
786 _LIBCPP_INLINE_VISIBILITY
787 constexpr
788 add_pointer_t<value_type const>
789 operator->() const
790 {
791 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
792#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
793 return _VSTD::addressof(this->__get());
794#else
795 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
796#endif
797 }
798
799 _LIBCPP_INLINE_VISIBILITY
800 constexpr
801 add_pointer_t<value_type>
802 operator->()
803 {
804 _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
805#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
806 return _VSTD::addressof(this->__get());
807#else
808 return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
809#endif
810 }
811
812 _LIBCPP_INLINE_VISIBILITY
813 constexpr
814 const value_type&
815 operator*() const&
816 {
817 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
818 return this->__get();
819 }
820
821 _LIBCPP_INLINE_VISIBILITY
822 constexpr
823 value_type&
824 operator*() &
825 {
826 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
827 return this->__get();
828 }
829
830 _LIBCPP_INLINE_VISIBILITY
831 constexpr
832 value_type&&
833 operator*() &&
834 {
835 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
836 return _VSTD::move(this->__get());
837 }
838
839 _LIBCPP_INLINE_VISIBILITY
840 constexpr
841 const value_type&&
842 operator*() const&&
843 {
844 _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
845 return _VSTD::move(this->__get());
846 }
847
848 _LIBCPP_INLINE_VISIBILITY
849 constexpr explicit operator bool() const noexcept { return has_value(); }
850
851 using __base::has_value;
852 using __base::__get;
853
854 _LIBCPP_INLINE_VISIBILITY
855 constexpr value_type const& value() const&
856 {
857 if (!this->has_value())
858 __throw_bad_optional_access();
859 return this->__get();
860 }
861
862 _LIBCPP_INLINE_VISIBILITY
863 constexpr value_type& value() &
864 {
865 if (!this->has_value())
866 __throw_bad_optional_access();
867 return this->__get();
868 }
869
870 _LIBCPP_INLINE_VISIBILITY
871 constexpr value_type&& value() &&
872 {
873 if (!this->has_value())
874 __throw_bad_optional_access();
875 return _VSTD::move(this->__get());
876 }
877
878 _LIBCPP_INLINE_VISIBILITY
879 constexpr value_type const&& value() const&&
880 {
881 if (!this->has_value())
882 __throw_bad_optional_access();
883 return _VSTD::move(this->__get());
884 }
885
886 template <class _Up>
887 _LIBCPP_INLINE_VISIBILITY
888 constexpr value_type value_or(_Up&& __v) const&
889 {
890 static_assert(is_copy_constructible_v<value_type>,
891 "optional<T>::value_or: T must be copy constructible");
892 static_assert(is_convertible_v<_Up, value_type>,
893 "optional<T>::value_or: U must be convertible to T");
894 return this->has_value() ? this->__get() :
895 static_cast<value_type>(_VSTD::forward<_Up>(__v));
896 }
897
898 template <class _Up>
899 _LIBCPP_INLINE_VISIBILITY
900 value_type value_or(_Up&& __v) &&
901 {
902 static_assert(is_move_constructible_v<value_type>,
903 "optional<T>::value_or: T must be move constructible");
904 static_assert(is_convertible_v<_Up, value_type>,
905 "optional<T>::value_or: U must be convertible to T");
906 return this->has_value() ? _VSTD::move(this->__get()) :
907 static_cast<value_type>(_VSTD::forward<_Up>(__v));
908 }
909
910 using __base::reset;
911
912private:
913 template <class _Up>
914 _LIBCPP_INLINE_VISIBILITY
915 static _Up*
916 __operator_arrow(true_type, _Up& __x)
917 {
918 return _VSTD::addressof(__x);
919 }
920
921 template <class _Up>
922 _LIBCPP_INLINE_VISIBILITY
923 static constexpr _Up*
924 __operator_arrow(false_type, _Up& __x)
925 {
926 return &__x;
927 }
928};
929
930// Comparisons between optionals
Eric Fiselier8af90142017-03-30 20:06:52 +0000931template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000932_LIBCPP_INLINE_VISIBILITY constexpr
933enable_if_t<
934 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +0000935 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000936 bool
937>
Eric Fiselier8af90142017-03-30 20:06:52 +0000938operator==(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000939{
940 if (static_cast<bool>(__x) != static_cast<bool>(__y))
941 return false;
942 if (!static_cast<bool>(__x))
943 return true;
944 return *__x == *__y;
945}
946
Eric Fiselier8af90142017-03-30 20:06:52 +0000947template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000948_LIBCPP_INLINE_VISIBILITY constexpr
949enable_if_t<
950 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +0000951 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000952 bool
953>
Eric Fiselier8af90142017-03-30 20:06:52 +0000954operator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000955{
956 if (static_cast<bool>(__x) != static_cast<bool>(__y))
957 return true;
958 if (!static_cast<bool>(__x))
959 return false;
960 return *__x != *__y;
961}
962
Eric Fiselier8af90142017-03-30 20:06:52 +0000963template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000964_LIBCPP_INLINE_VISIBILITY constexpr
965enable_if_t<
966 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +0000967 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000968 bool
969>
Eric Fiselier8af90142017-03-30 20:06:52 +0000970operator<(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000971{
972 if (!static_cast<bool>(__y))
973 return false;
974 if (!static_cast<bool>(__x))
975 return true;
976 return *__x < *__y;
977}
978
Eric Fiselier8af90142017-03-30 20:06:52 +0000979template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000980_LIBCPP_INLINE_VISIBILITY constexpr
981enable_if_t<
982 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +0000983 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000984 bool
985>
Eric Fiselier8af90142017-03-30 20:06:52 +0000986operator>(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000987{
988 if (!static_cast<bool>(__x))
989 return false;
990 if (!static_cast<bool>(__y))
991 return true;
992 return *__x > *__y;
993}
994
Eric Fiselier8af90142017-03-30 20:06:52 +0000995template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +0000996_LIBCPP_INLINE_VISIBILITY constexpr
997enable_if_t<
998 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +0000999 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001000 bool
1001>
Eric Fiselier8af90142017-03-30 20:06:52 +00001002operator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001003{
1004 if (!static_cast<bool>(__x))
1005 return true;
1006 if (!static_cast<bool>(__y))
1007 return false;
1008 return *__x <= *__y;
1009}
1010
Eric Fiselier8af90142017-03-30 20:06:52 +00001011template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001012_LIBCPP_INLINE_VISIBILITY constexpr
1013enable_if_t<
1014 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001015 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001016 bool
1017>
Eric Fiselier8af90142017-03-30 20:06:52 +00001018operator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001019{
1020 if (!static_cast<bool>(__y))
1021 return true;
1022 if (!static_cast<bool>(__x))
1023 return false;
1024 return *__x >= *__y;
1025}
1026
1027// Comparisons with nullopt
1028template <class _Tp>
1029_LIBCPP_INLINE_VISIBILITY constexpr
1030bool
1031operator==(const optional<_Tp>& __x, nullopt_t) noexcept
1032{
1033 return !static_cast<bool>(__x);
1034}
1035
1036template <class _Tp>
1037_LIBCPP_INLINE_VISIBILITY constexpr
1038bool
1039operator==(nullopt_t, const optional<_Tp>& __x) noexcept
1040{
1041 return !static_cast<bool>(__x);
1042}
1043
1044template <class _Tp>
1045_LIBCPP_INLINE_VISIBILITY constexpr
1046bool
1047operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
1048{
1049 return static_cast<bool>(__x);
1050}
1051
1052template <class _Tp>
1053_LIBCPP_INLINE_VISIBILITY constexpr
1054bool
1055operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
1056{
1057 return static_cast<bool>(__x);
1058}
1059
1060template <class _Tp>
1061_LIBCPP_INLINE_VISIBILITY constexpr
1062bool
1063operator<(const optional<_Tp>&, nullopt_t) noexcept
1064{
1065 return false;
1066}
1067
1068template <class _Tp>
1069_LIBCPP_INLINE_VISIBILITY constexpr
1070bool
1071operator<(nullopt_t, const optional<_Tp>& __x) noexcept
1072{
1073 return static_cast<bool>(__x);
1074}
1075
1076template <class _Tp>
1077_LIBCPP_INLINE_VISIBILITY constexpr
1078bool
1079operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
1080{
1081 return !static_cast<bool>(__x);
1082}
1083
1084template <class _Tp>
1085_LIBCPP_INLINE_VISIBILITY constexpr
1086bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001087operator<=(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001088{
1089 return true;
1090}
1091
1092template <class _Tp>
1093_LIBCPP_INLINE_VISIBILITY constexpr
1094bool
1095operator>(const optional<_Tp>& __x, nullopt_t) noexcept
1096{
1097 return static_cast<bool>(__x);
1098}
1099
1100template <class _Tp>
1101_LIBCPP_INLINE_VISIBILITY constexpr
1102bool
Eric Fiselier6003c772016-12-23 23:37:52 +00001103operator>(nullopt_t, const optional<_Tp>&) noexcept
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001104{
1105 return false;
1106}
1107
1108template <class _Tp>
1109_LIBCPP_INLINE_VISIBILITY constexpr
1110bool
1111operator>=(const optional<_Tp>&, nullopt_t) noexcept
1112{
1113 return true;
1114}
1115
1116template <class _Tp>
1117_LIBCPP_INLINE_VISIBILITY constexpr
1118bool
1119operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
1120{
1121 return !static_cast<bool>(__x);
1122}
1123
1124// Comparisons with T
Eric Fiselier8af90142017-03-30 20:06:52 +00001125template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001126_LIBCPP_INLINE_VISIBILITY constexpr
1127enable_if_t<
1128 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001129 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001130 bool
1131>
Eric Fiselier8af90142017-03-30 20:06:52 +00001132operator==(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001133{
1134 return static_cast<bool>(__x) ? *__x == __v : false;
1135}
1136
Eric Fiselier8af90142017-03-30 20:06:52 +00001137template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001138_LIBCPP_INLINE_VISIBILITY constexpr
1139enable_if_t<
1140 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
Eric Fiselier8af90142017-03-30 20:06:52 +00001141 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001142 bool
1143>
Eric Fiselier8af90142017-03-30 20:06:52 +00001144operator==(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001145{
1146 return static_cast<bool>(__x) ? __v == *__x : false;
1147}
1148
Eric Fiselier8af90142017-03-30 20:06:52 +00001149template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001150_LIBCPP_INLINE_VISIBILITY constexpr
1151enable_if_t<
1152 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001153 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001154 bool
1155>
Eric Fiselier8af90142017-03-30 20:06:52 +00001156operator!=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001157{
1158 return static_cast<bool>(__x) ? *__x != __v : true;
1159}
1160
Eric Fiselier8af90142017-03-30 20:06:52 +00001161template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001162_LIBCPP_INLINE_VISIBILITY constexpr
1163enable_if_t<
1164 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
Eric Fiselier8af90142017-03-30 20:06:52 +00001165 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001166 bool
1167>
Eric Fiselier8af90142017-03-30 20:06:52 +00001168operator!=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001169{
1170 return static_cast<bool>(__x) ? __v != *__x : true;
1171}
1172
Eric Fiselier8af90142017-03-30 20:06:52 +00001173template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001174_LIBCPP_INLINE_VISIBILITY constexpr
1175enable_if_t<
1176 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001177 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001178 bool
1179>
Eric Fiselier8af90142017-03-30 20:06:52 +00001180operator<(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001181{
1182 return static_cast<bool>(__x) ? *__x < __v : true;
1183}
1184
Eric Fiselier8af90142017-03-30 20:06:52 +00001185template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001186_LIBCPP_INLINE_VISIBILITY constexpr
1187enable_if_t<
1188 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
Eric Fiselier8af90142017-03-30 20:06:52 +00001189 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001190 bool
1191>
Eric Fiselier8af90142017-03-30 20:06:52 +00001192operator<(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001193{
1194 return static_cast<bool>(__x) ? __v < *__x : false;
1195}
1196
Eric Fiselier8af90142017-03-30 20:06:52 +00001197template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001198_LIBCPP_INLINE_VISIBILITY constexpr
1199enable_if_t<
1200 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001201 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001202 bool
1203>
Eric Fiselier8af90142017-03-30 20:06:52 +00001204operator<=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001205{
1206 return static_cast<bool>(__x) ? *__x <= __v : true;
1207}
1208
Eric Fiselier8af90142017-03-30 20:06:52 +00001209template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001210_LIBCPP_INLINE_VISIBILITY constexpr
1211enable_if_t<
1212 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
Eric Fiselier8af90142017-03-30 20:06:52 +00001213 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001214 bool
1215>
Eric Fiselier8af90142017-03-30 20:06:52 +00001216operator<=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001217{
1218 return static_cast<bool>(__x) ? __v <= *__x : false;
1219}
1220
Eric Fiselier8af90142017-03-30 20:06:52 +00001221template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001222_LIBCPP_INLINE_VISIBILITY constexpr
1223enable_if_t<
1224 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001225 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001226 bool
1227>
Eric Fiselier8af90142017-03-30 20:06:52 +00001228operator>(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001229{
1230 return static_cast<bool>(__x) ? *__x > __v : false;
1231}
1232
Eric Fiselier8af90142017-03-30 20:06:52 +00001233template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001234_LIBCPP_INLINE_VISIBILITY constexpr
1235enable_if_t<
1236 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
Eric Fiselier8af90142017-03-30 20:06:52 +00001237 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001238 bool
1239>
Eric Fiselier8af90142017-03-30 20:06:52 +00001240operator>(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001241{
1242 return static_cast<bool>(__x) ? __v > *__x : true;
1243}
1244
Eric Fiselier8af90142017-03-30 20:06:52 +00001245template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001246_LIBCPP_INLINE_VISIBILITY constexpr
1247enable_if_t<
1248 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001249 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001250 bool
1251>
Eric Fiselier8af90142017-03-30 20:06:52 +00001252operator>=(const optional<_Tp>& __x, const _Up& __v)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001253{
1254 return static_cast<bool>(__x) ? *__x >= __v : false;
1255}
1256
Eric Fiselier8af90142017-03-30 20:06:52 +00001257template <class _Tp, class _Up>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001258_LIBCPP_INLINE_VISIBILITY constexpr
1259enable_if_t<
1260 is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
Eric Fiselier8af90142017-03-30 20:06:52 +00001261 _VSTD::declval<const _Up&>()), bool>,
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001262 bool
1263>
Eric Fiselier8af90142017-03-30 20:06:52 +00001264operator>=(const _Tp& __v, const optional<_Up>& __x)
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001265{
1266 return static_cast<bool>(__x) ? __v >= *__x : true;
1267}
1268
1269
1270template <class _Tp>
1271inline _LIBCPP_INLINE_VISIBILITY
1272enable_if_t<
1273 is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
1274 void
1275>
1276swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
1277{
1278 __x.swap(__y);
1279}
1280
1281template <class _Tp>
1282_LIBCPP_INLINE_VISIBILITY constexpr
1283optional<decay_t<_Tp>> make_optional(_Tp&& __v)
1284{
1285 return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
1286}
1287
1288template <class _Tp, class... _Args>
1289_LIBCPP_INLINE_VISIBILITY constexpr
1290optional<_Tp> make_optional(_Args&&... __args)
1291{
1292 return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
1293}
1294
1295template <class _Tp, class _Up, class... _Args>
1296_LIBCPP_INLINE_VISIBILITY constexpr
1297optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args)
1298{
1299 return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
1300}
1301
1302template <class _Tp>
Eric Fiselier698a97b2017-01-21 00:02:12 +00001303struct _LIBCPP_TEMPLATE_VIS hash<
1304 __enable_hash_helper<optional<_Tp>, remove_const_t<_Tp>>
1305>
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001306{
1307 typedef optional<_Tp> argument_type;
1308 typedef size_t result_type;
1309
1310 _LIBCPP_INLINE_VISIBILITY
Marshall Clow49036892017-03-23 02:40:28 +00001311 result_type operator()(const argument_type& __opt) const
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001312 {
Eric Fiselier698a97b2017-01-21 00:02:12 +00001313 return static_cast<bool>(__opt) ? hash<remove_const_t<_Tp>>()(*__opt) : 0;
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001314 }
1315};
1316
1317_LIBCPP_END_NAMESPACE_STD
1318
1319#endif // _LIBCPP_STD_VER > 14
1320
Eric Fiselierf4433a32017-05-31 22:07:49 +00001321_LIBCPP_POP_MACROS
1322
Eric Fiselierd4ec6352016-10-12 07:46:20 +00001323#endif // _LIBCPP_OPTIONAL