1 // <optional> -*- C++ -*-
3 // Copyright (C) 2013-2017 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file include/optional
26 * This is a Standard C++ Library header.
29 #ifndef _GLIBCXX_OPTIONAL
30 #define _GLIBCXX_OPTIONAL 1
32 #if __cplusplus <= 201402L
33 # include <bits/c++17_warning.h>
37 #include <type_traits>
40 #include <initializer_list>
41 #include <bits/functexcept.h>
42 #include <bits/functional_hash.h>
43 #include <bits/enable_special_members.h>
45 namespace std _GLIBCXX_VISIBILITY(default)
47 _GLIBCXX_BEGIN_NAMESPACE_VERSION
50 * @addtogroup utilities
54 template<typename _Tp>
57 /// Tag type to disengage optional objects.
60 // Do not user-declare default constructor at all for
61 // optional_value = {} syntax to work.
62 // nullopt_t() = delete;
64 // Used for constructing nullopt.
65 enum class _Construct { _Token };
67 // Must be constexpr for nullopt_t to be literal.
68 explicit constexpr nullopt_t(_Construct) { }
71 /// Tag to disengage optional objects.
72 constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
75 * @brief Exception class thrown when a disengaged optional object is
79 class bad_optional_access : public exception
82 bad_optional_access() { }
83 virtual const char* what() const noexcept override
84 {return "bad optional access";}
86 virtual ~bad_optional_access() noexcept = default;
90 __throw_bad_optional_access()
91 __attribute__((__noreturn__));
93 // XXX Does not belong here.
95 __throw_bad_optional_access()
96 { _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); }
99 * @brief Class template that holds the necessary state for @ref optional
100 * and that has the responsibility for construction and the special members.
102 * Such a separate base class template is necessary in order to
103 * conditionally enable the special members (e.g. copy/move constructors).
104 * Note that this means that @ref _Optional_base implements the
105 * functionality for copy and move assignment, but not for converting
108 * @see optional, _Enable_special_members
110 template<typename _Tp, bool _ShouldProvideDestructor =
111 !is_trivially_destructible<_Tp>::value>
115 // Remove const to avoid prohibition of reusing object storage for
116 // const-qualified types in [3.8/9]. This is strictly internal
117 // and even optional itself is oblivious to it.
118 using _Stored_type = remove_const_t<_Tp>;
122 // Constructors for disengaged optionals.
123 constexpr _Optional_base() noexcept
126 constexpr _Optional_base(nullopt_t) noexcept
127 : _Optional_base{} { }
129 // Constructors for engaged optionals.
130 template<typename... _Args,
131 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
132 constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
133 : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
135 template<typename _Up, typename... _Args,
136 enable_if_t<is_constructible_v<_Tp,
137 initializer_list<_Up>&,
138 _Args&&...>, bool> = false>
139 constexpr explicit _Optional_base(in_place_t,
140 initializer_list<_Up> __il,
142 : _M_payload(__il, std::forward<_Args>(__args)...),
145 // Copy and move constructors.
146 _Optional_base(const _Optional_base& __other)
148 if (__other._M_engaged)
149 this->_M_construct(__other._M_get());
152 _Optional_base(_Optional_base&& __other)
153 noexcept(is_nothrow_move_constructible<_Tp>())
155 if (__other._M_engaged)
156 this->_M_construct(std::move(__other._M_get()));
159 // Assignment operators.
161 operator=(const _Optional_base& __other)
163 if (this->_M_engaged && __other._M_engaged)
164 this->_M_get() = __other._M_get();
167 if (__other._M_engaged)
168 this->_M_construct(__other._M_get());
177 operator=(_Optional_base&& __other)
178 noexcept(__and_<is_nothrow_move_constructible<_Tp>,
179 is_nothrow_move_assignable<_Tp>>())
181 if (this->_M_engaged && __other._M_engaged)
182 this->_M_get() = std::move(__other._M_get());
185 if (__other._M_engaged)
186 this->_M_construct(std::move(__other._M_get()));
196 if (this->_M_engaged)
197 this->_M_payload.~_Stored_type();
200 // The following functionality is also needed by optional, hence the
201 // protected accessibility.
203 constexpr bool _M_is_engaged() const noexcept
204 { return this->_M_engaged; }
206 // The _M_get operations have _M_engaged as a precondition.
209 { return _M_payload; }
212 _M_get() const noexcept
213 { return _M_payload; }
215 // The _M_construct operation has !_M_engaged as a precondition
216 // while _M_destruct has _M_engaged as a precondition.
217 template<typename... _Args>
219 _M_construct(_Args&&... __args)
220 noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
222 ::new (std::__addressof(this->_M_payload))
223 _Stored_type(std::forward<_Args>(__args)...);
224 this->_M_engaged = true;
230 this->_M_engaged = false;
231 this->_M_payload.~_Stored_type();
234 // _M_reset is a 'safe' operation with no precondition.
238 if (this->_M_engaged)
243 struct _Empty_byte { };
245 _Empty_byte _M_empty;
246 _Stored_type _M_payload;
248 bool _M_engaged = false;
251 /// Partial specialization that is exactly identical to the primary template
252 /// save for not providing a destructor, to fulfill triviality requirements.
253 template<typename _Tp>
254 class _Optional_base<_Tp, false>
257 using _Stored_type = remove_const_t<_Tp>;
260 constexpr _Optional_base() noexcept
263 constexpr _Optional_base(nullopt_t) noexcept
264 : _Optional_base{} { }
266 template<typename... _Args,
267 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
268 constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
269 : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
271 template<typename _Up, typename... _Args,
272 enable_if_t<is_constructible_v<_Tp,
273 initializer_list<_Up>&,
274 _Args&&...>, bool> = false>
275 constexpr explicit _Optional_base(in_place_t,
276 initializer_list<_Up> __il,
278 : _M_payload(__il, std::forward<_Args>(__args)...),
281 _Optional_base(const _Optional_base& __other)
283 if (__other._M_engaged)
284 this->_M_construct(__other._M_get());
287 _Optional_base(_Optional_base&& __other)
288 noexcept(is_nothrow_move_constructible<_Tp>())
290 if (__other._M_engaged)
291 this->_M_construct(std::move(__other._M_get()));
295 operator=(const _Optional_base& __other)
297 if (this->_M_engaged && __other._M_engaged)
298 this->_M_get() = __other._M_get();
301 if (__other._M_engaged)
302 this->_M_construct(__other._M_get());
310 operator=(_Optional_base&& __other)
311 noexcept(__and_<is_nothrow_move_constructible<_Tp>,
312 is_nothrow_move_assignable<_Tp>>())
314 if (this->_M_engaged && __other._M_engaged)
315 this->_M_get() = std::move(__other._M_get());
318 if (__other._M_engaged)
319 this->_M_construct(std::move(__other._M_get()));
327 // ~_Optional_base() noexcept = default;
330 constexpr bool _M_is_engaged() const noexcept
331 { return this->_M_engaged; }
335 { return _M_payload; }
338 _M_get() const noexcept
339 { return _M_payload; }
341 template<typename... _Args>
343 _M_construct(_Args&&... __args)
344 noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
346 ::new (std::__addressof(this->_M_payload))
347 _Stored_type(std::forward<_Args>(__args)...);
348 this->_M_engaged = true;
354 this->_M_engaged = false;
355 this->_M_payload.~_Stored_type();
361 if (this->_M_engaged)
366 struct _Empty_byte { };
369 _Empty_byte _M_empty;
370 _Stored_type _M_payload;
372 bool _M_engaged = false;
375 template<typename _Tp>
378 template<typename _Tp, typename _Up>
379 using __converts_from_optional =
380 __or_<is_constructible<_Tp, const optional<_Up>&>,
381 is_constructible<_Tp, optional<_Up>&>,
382 is_constructible<_Tp, const optional<_Up>&&>,
383 is_constructible<_Tp, optional<_Up>&&>,
384 is_convertible<const optional<_Up>&, _Tp>,
385 is_convertible<optional<_Up>&, _Tp>,
386 is_convertible<const optional<_Up>&&, _Tp>,
387 is_convertible<optional<_Up>&&, _Tp>>;
389 template<typename _Tp, typename _Up>
390 using __assigns_from_optional =
391 __or_<is_assignable<_Tp&, const optional<_Up>&>,
392 is_assignable<_Tp&, optional<_Up>&>,
393 is_assignable<_Tp&, const optional<_Up>&&>,
394 is_assignable<_Tp&, optional<_Up>&&>>;
397 * @brief Class template for optional values.
399 template<typename _Tp>
401 : private _Optional_base<_Tp>,
402 private _Enable_copy_move<
404 is_copy_constructible<_Tp>::value,
406 __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value,
408 is_move_constructible<_Tp>::value,
410 __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value,
414 static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>, nullopt_t>>,
415 __not_<is_same<remove_cv_t<_Tp>, in_place_t>>,
416 __not_<is_reference<_Tp>>>(),
417 "Invalid instantiation of optional<T>");
420 using _Base = _Optional_base<_Tp>;
423 using value_type = _Tp;
425 constexpr optional() = default;
427 constexpr optional(nullopt_t) noexcept
430 // Converting constructors for engaged optionals.
431 template <typename _Up = _Tp,
433 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
434 __not_<is_same<in_place_t, decay_t<_Up>>>,
435 is_constructible<_Tp, _Up&&>,
436 is_convertible<_Up&&, _Tp>
437 >::value, bool> = true>
438 constexpr optional(_Up&& __t)
439 : _Base(std::in_place, std::forward<_Up>(__t)) { }
441 template <typename _Up = _Tp,
443 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
444 __not_<is_same<in_place_t, decay_t<_Up>>>,
445 is_constructible<_Tp, _Up&&>,
446 __not_<is_convertible<_Up&&, _Tp>>
447 >::value, bool> = false>
448 explicit constexpr optional(_Up&& __t)
449 : _Base(std::in_place, std::forward<_Up>(__t)) { }
451 template <typename _Up,
453 __not_<is_same<_Tp, _Up>>,
454 is_constructible<_Tp, const _Up&>,
455 is_convertible<const _Up&, _Tp>,
456 __not_<__converts_from_optional<_Tp, _Up>>
457 >::value, bool> = true>
458 constexpr optional(const optional<_Up>& __t)
464 template <typename _Up,
466 __not_<is_same<_Tp, _Up>>,
467 is_constructible<_Tp, const _Up&>,
468 __not_<is_convertible<const _Up&, _Tp>>,
469 __not_<__converts_from_optional<_Tp, _Up>>
470 >::value, bool> = false>
471 explicit constexpr optional(const optional<_Up>& __t)
477 template <typename _Up,
479 __not_<is_same<_Tp, _Up>>,
480 is_constructible<_Tp, _Up&&>,
481 is_convertible<_Up&&, _Tp>,
482 __not_<__converts_from_optional<_Tp, _Up>>
483 >::value, bool> = true>
484 constexpr optional(optional<_Up>&& __t)
487 emplace(std::move(*__t));
490 template <typename _Up,
492 __not_<is_same<_Tp, _Up>>,
493 is_constructible<_Tp, _Up&&>,
494 __not_<is_convertible<_Up&&, _Tp>>,
495 __not_<__converts_from_optional<_Tp, _Up>>
496 >::value, bool> = false>
497 explicit constexpr optional(optional<_Up>&& __t)
500 emplace(std::move(*__t));
503 template<typename... _Args,
504 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
505 explicit constexpr optional(in_place_t, _Args&&... __args)
506 : _Base(std::in_place, std::forward<_Args>(__args)...) { }
508 template<typename _Up, typename... _Args,
509 enable_if_t<is_constructible_v<_Tp,
510 initializer_list<_Up>&,
511 _Args&&...>, bool> = false>
512 explicit constexpr optional(in_place_t,
513 initializer_list<_Up> __il,
515 : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { }
517 // Assignment operators.
519 operator=(nullopt_t) noexcept
525 template<typename _Up = _Tp>
527 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
528 is_constructible<_Tp, _Up>,
529 __not_<__and_<is_scalar<_Tp>,
530 is_same<_Tp, decay_t<_Up>>>>,
531 is_assignable<_Tp&, _Up>>::value,
535 if (this->_M_is_engaged())
536 this->_M_get() = std::forward<_Up>(__u);
538 this->_M_construct(std::forward<_Up>(__u));
543 template<typename _Up>
545 __not_<is_same<_Tp, _Up>>,
546 is_constructible<_Tp, const _Up&>,
547 is_assignable<_Tp&, _Up>,
548 __not_<__converts_from_optional<_Tp, _Up>>,
549 __not_<__assigns_from_optional<_Tp, _Up>>
552 operator=(const optional<_Up>& __u)
556 if (this->_M_is_engaged())
557 this->_M_get() = *__u;
559 this->_M_construct(*__u);
568 template<typename _Up>
570 __not_<is_same<_Tp, _Up>>,
571 is_constructible<_Tp, _Up>,
572 is_assignable<_Tp&, _Up>,
573 __not_<__converts_from_optional<_Tp, _Up>>,
574 __not_<__assigns_from_optional<_Tp, _Up>>
577 operator=(optional<_Up>&& __u)
581 if (this->_M_is_engaged())
582 this->_M_get() = std::move(*__u);
584 this->_M_construct(std::move(*__u));
594 template<typename... _Args>
595 enable_if_t<is_constructible<_Tp, _Args&&...>::value, _Tp&>
596 emplace(_Args&&... __args)
599 this->_M_construct(std::forward<_Args>(__args)...);
600 return this->_M_get();
603 template<typename _Up, typename... _Args>
604 enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
605 _Args&&...>::value, _Tp&>
606 emplace(initializer_list<_Up> __il, _Args&&... __args)
609 this->_M_construct(__il, std::forward<_Args>(__args)...);
610 return this->_M_get();
613 // Destructor is implicit, implemented in _Optional_base.
617 swap(optional& __other)
618 noexcept(is_nothrow_move_constructible<_Tp>()
619 && is_nothrow_swappable_v<_Tp>)
623 if (this->_M_is_engaged() && __other._M_is_engaged())
624 swap(this->_M_get(), __other._M_get());
625 else if (this->_M_is_engaged())
627 __other._M_construct(std::move(this->_M_get()));
630 else if (__other._M_is_engaged())
632 this->_M_construct(std::move(__other._M_get()));
633 __other._M_destruct();
640 { return std::__addressof(this->_M_get()); }
644 { return std::__addressof(this->_M_get()); }
648 { return this->_M_get(); }
652 { return this->_M_get(); }
656 { return std::move(this->_M_get()); }
658 constexpr const _Tp&&
660 { return std::move(this->_M_get()); }
662 constexpr explicit operator bool() const noexcept
663 { return this->_M_is_engaged(); }
665 constexpr bool has_value() const noexcept
666 { return this->_M_is_engaged(); }
671 return this->_M_is_engaged()
673 : (__throw_bad_optional_access(),
680 return this->_M_is_engaged()
682 : (__throw_bad_optional_access(),
689 return this->_M_is_engaged()
690 ? std::move(this->_M_get())
691 : (__throw_bad_optional_access(),
692 std::move(this->_M_get()));
695 constexpr const _Tp&&
698 return this->_M_is_engaged()
699 ? std::move(this->_M_get())
700 : (__throw_bad_optional_access(),
701 std::move(this->_M_get()));
704 template<typename _Up>
706 value_or(_Up&& __u) const&
708 static_assert(__and_<is_copy_constructible<_Tp>,
709 is_convertible<_Up&&, _Tp>>(),
710 "Cannot return value");
712 return this->_M_is_engaged()
714 : static_cast<_Tp>(std::forward<_Up>(__u));
717 template<typename _Up>
719 value_or(_Up&& __u) &&
721 static_assert(__and_<is_move_constructible<_Tp>,
722 is_convertible<_Up&&, _Tp>>(),
723 "Cannot return value" );
725 return this->_M_is_engaged()
726 ? std::move(this->_M_get())
727 : static_cast<_Tp>(std::forward<_Up>(__u));
729 void reset() noexcept { this->_M_reset(); }
732 template<typename _Tp>
733 using __optional_relop_t =
734 enable_if_t<is_convertible<_Tp, bool>::value, bool>;
736 // Comparisons between optional values.
737 template<typename _Tp, typename _Up>
739 operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
740 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())>
742 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
743 && (!__lhs || *__lhs == *__rhs);
746 template<typename _Tp, typename _Up>
748 operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
749 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())>
751 return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
752 || (static_cast<bool>(__lhs) && *__lhs != *__rhs);
755 template<typename _Tp, typename _Up>
757 operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
758 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())>
760 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
763 template<typename _Tp, typename _Up>
765 operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
766 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())>
768 return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
771 template<typename _Tp, typename _Up>
773 operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
774 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())>
776 return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
779 template<typename _Tp, typename _Up>
781 operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
782 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())>
784 return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
787 // Comparisons with nullopt.
788 template<typename _Tp>
790 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
793 template<typename _Tp>
795 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
798 template<typename _Tp>
800 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
801 { return static_cast<bool>(__lhs); }
803 template<typename _Tp>
805 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
806 { return static_cast<bool>(__rhs); }
808 template<typename _Tp>
810 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
813 template<typename _Tp>
815 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
816 { return static_cast<bool>(__rhs); }
818 template<typename _Tp>
820 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
821 { return static_cast<bool>(__lhs); }
823 template<typename _Tp>
825 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
828 template<typename _Tp>
830 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
833 template<typename _Tp>
835 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
838 template<typename _Tp>
840 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
843 template<typename _Tp>
845 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
848 // Comparisons with value type.
849 template<typename _Tp, typename _Up>
851 operator==(const optional<_Tp>& __lhs, const _Up& __rhs)
852 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())>
853 { return __lhs && *__lhs == __rhs; }
855 template<typename _Tp, typename _Up>
857 operator==(const _Up& __lhs, const optional<_Tp>& __rhs)
858 -> __optional_relop_t<decltype(declval<_Up>() == declval<_Tp>())>
859 { return __rhs && __lhs == *__rhs; }
861 template<typename _Tp, typename _Up>
863 operator!=(const optional<_Tp>& __lhs, const _Up& __rhs)
864 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())>
865 { return !__lhs || *__lhs != __rhs; }
867 template<typename _Tp, typename _Up>
869 operator!=(const _Up& __lhs, const optional<_Tp>& __rhs)
870 -> __optional_relop_t<decltype(declval<_Up>() != declval<_Tp>())>
871 { return !__rhs || __lhs != *__rhs; }
873 template<typename _Tp, typename _Up>
875 operator<(const optional<_Tp>& __lhs, const _Up& __rhs)
876 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())>
877 { return !__lhs || *__lhs < __rhs; }
879 template<typename _Tp, typename _Up>
881 operator<(const _Up& __lhs, const optional<_Tp>& __rhs)
882 -> __optional_relop_t<decltype(declval<_Up>() < declval<_Tp>())>
883 { return __rhs && __lhs < *__rhs; }
885 template<typename _Tp, typename _Up>
887 operator>(const optional<_Tp>& __lhs, const _Up& __rhs)
888 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())>
889 { return __lhs && *__lhs > __rhs; }
891 template<typename _Tp, typename _Up>
893 operator>(const _Up& __lhs, const optional<_Tp>& __rhs)
894 -> __optional_relop_t<decltype(declval<_Up>() > declval<_Tp>())>
895 { return !__rhs || __lhs > *__rhs; }
897 template<typename _Tp, typename _Up>
899 operator<=(const optional<_Tp>& __lhs, const _Up& __rhs)
900 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())>
901 { return !__lhs || *__lhs <= __rhs; }
903 template<typename _Tp, typename _Up>
905 operator<=(const _Up& __lhs, const optional<_Tp>& __rhs)
906 -> __optional_relop_t<decltype(declval<_Up>() <= declval<_Tp>())>
907 { return __rhs && __lhs <= *__rhs; }
909 template<typename _Tp, typename _Up>
911 operator>=(const optional<_Tp>& __lhs, const _Up& __rhs)
912 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())>
913 { return __lhs && *__lhs >= __rhs; }
915 template<typename _Tp, typename _Up>
917 operator>=(const _Up& __lhs, const optional<_Tp>& __rhs)
918 -> __optional_relop_t<decltype(declval<_Up>() >= declval<_Tp>())>
919 { return !__rhs || __lhs >= *__rhs; }
921 // Swap and creation functions.
923 // _GLIBCXX_RESOLVE_LIB_DEFECTS
924 // 2748. swappable traits for optionals
925 template<typename _Tp>
926 inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>>
927 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
928 noexcept(noexcept(__lhs.swap(__rhs)))
929 { __lhs.swap(__rhs); }
931 template<typename _Tp>
932 enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)>
933 swap(optional<_Tp>&, optional<_Tp>&) = delete;
935 template<typename _Tp>
936 constexpr optional<decay_t<_Tp>>
937 make_optional(_Tp&& __t)
938 { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
940 template<typename _Tp, typename ..._Args>
941 constexpr optional<_Tp>
942 make_optional(_Args&&... __args)
943 { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; }
945 template<typename _Tp, typename _Up, typename ..._Args>
946 constexpr optional<_Tp>
947 make_optional(initializer_list<_Up> __il, _Args&&... __args)
948 { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; }
952 template<typename _Tp, bool
953 = __poison_hash<remove_const_t<_Tp>>::__enable_hash_call>
954 struct __optional_hash_call_base
957 operator()(const optional<_Tp>& __t) const
958 noexcept(noexcept(hash<_Tp> {}(*__t)))
960 // We pick an arbitrary hash for disengaged optionals which hopefully
961 // usual values of _Tp won't typically hash to.
962 constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
963 return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash;
967 template<typename _Tp>
968 struct __optional_hash_call_base<_Tp, false> {};
970 template<typename _Tp>
971 struct hash<optional<_Tp>>
972 : private __poison_hash<remove_const_t<_Tp>>,
973 public __optional_hash_call_base<_Tp>
975 using result_type = size_t;
976 using argument_type = optional<_Tp>;
981 template <typename _Tp> optional(_Tp) -> optional<_Tp>;
983 _GLIBCXX_END_NAMESPACE_VERSION
988 #endif // _GLIBCXX_OPTIONAL