1 // <optional> -*- C++ -*-
3 // Copyright (C) 2013-2016 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 logic_error
81 // XXX See LEWG 72, https://issues.isocpp.org/show_bug.cgi?id=72
83 bad_optional_access() : logic_error("bad optional access") { }
84 // XXX This constructor is non-standard. Should not be inline
85 explicit bad_optional_access(const char* __arg) : logic_error(__arg) { }
87 virtual ~bad_optional_access() noexcept = default;
91 __throw_bad_optional_access(const char*)
92 __attribute__((__noreturn__));
94 // XXX Does not belong here.
96 __throw_bad_optional_access(const char* __s)
97 { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); }
100 * @brief Class template that holds the necessary state for @ref optional
101 * and that has the responsibility for construction and the special members.
103 * Such a separate base class template is necessary in order to
104 * conditionally enable the special members (e.g. copy/move constructors).
105 * Note that this means that @ref _Optional_base implements the
106 * functionality for copy and move assignment, but not for converting
109 * @see optional, _Enable_special_members
111 template<typename _Tp, bool _ShouldProvideDestructor =
112 !is_trivially_destructible<_Tp>::value>
116 // Remove const to avoid prohibition of reusing object storage for
117 // const-qualified types in [3.8/9]. This is strictly internal
118 // and even optional itself is oblivious to it.
119 using _Stored_type = remove_const_t<_Tp>;
123 // Constructors for disengaged optionals.
124 constexpr _Optional_base() noexcept
127 constexpr _Optional_base(nullopt_t) noexcept
128 : _Optional_base{} { }
130 // Constructors for engaged optionals.
131 template<typename... _Args,
132 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
133 constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
134 : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
136 template<typename _Up, typename... _Args,
137 enable_if_t<is_constructible_v<_Tp,
138 initializer_list<_Up>&,
139 _Args&&...>, bool> = false>
140 constexpr explicit _Optional_base(in_place_t,
141 initializer_list<_Up> __il,
143 : _M_payload(__il, std::forward<_Args>(__args)...),
146 // Copy and move constructors.
147 _Optional_base(const _Optional_base& __other)
149 if (__other._M_engaged)
150 this->_M_construct(__other._M_get());
153 _Optional_base(_Optional_base&& __other)
154 noexcept(is_nothrow_move_constructible<_Tp>())
156 if (__other._M_engaged)
157 this->_M_construct(std::move(__other._M_get()));
160 // Assignment operators.
162 operator=(const _Optional_base& __other)
164 if (this->_M_engaged && __other._M_engaged)
165 this->_M_get() = __other._M_get();
168 if (__other._M_engaged)
169 this->_M_construct(__other._M_get());
178 operator=(_Optional_base&& __other)
179 noexcept(__and_<is_nothrow_move_constructible<_Tp>,
180 is_nothrow_move_assignable<_Tp>>())
182 if (this->_M_engaged && __other._M_engaged)
183 this->_M_get() = std::move(__other._M_get());
186 if (__other._M_engaged)
187 this->_M_construct(std::move(__other._M_get()));
197 if (this->_M_engaged)
198 this->_M_payload.~_Stored_type();
201 // The following functionality is also needed by optional, hence the
202 // protected accessibility.
204 constexpr bool _M_is_engaged() const noexcept
205 { return this->_M_engaged; }
207 // The _M_get operations have _M_engaged as a precondition.
210 { return _M_payload; }
213 _M_get() const noexcept
214 { return _M_payload; }
216 // The _M_construct operation has !_M_engaged as a precondition
217 // while _M_destruct has _M_engaged as a precondition.
218 template<typename... _Args>
220 _M_construct(_Args&&... __args)
221 noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
223 ::new (std::__addressof(this->_M_payload))
224 _Stored_type(std::forward<_Args>(__args)...);
225 this->_M_engaged = true;
231 this->_M_engaged = false;
232 this->_M_payload.~_Stored_type();
235 // _M_reset is a 'safe' operation with no precondition.
239 if (this->_M_engaged)
244 struct _Empty_byte { };
246 _Empty_byte _M_empty;
247 _Stored_type _M_payload;
249 bool _M_engaged = false;
252 /// Partial specialization that is exactly identical to the primary template
253 /// save for not providing a destructor, to fulfill triviality requirements.
254 template<typename _Tp>
255 class _Optional_base<_Tp, false>
258 using _Stored_type = remove_const_t<_Tp>;
261 constexpr _Optional_base() noexcept
264 constexpr _Optional_base(nullopt_t) noexcept
265 : _Optional_base{} { }
267 template<typename... _Args,
268 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
269 constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
270 : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
272 template<typename _Up, typename... _Args,
273 enable_if_t<is_constructible_v<_Tp,
274 initializer_list<_Up>&,
275 _Args&&...>, bool> = false>
276 constexpr explicit _Optional_base(in_place_t,
277 initializer_list<_Up> __il,
279 : _M_payload(__il, std::forward<_Args>(__args)...),
282 _Optional_base(const _Optional_base& __other)
284 if (__other._M_engaged)
285 this->_M_construct(__other._M_get());
288 _Optional_base(_Optional_base&& __other)
289 noexcept(is_nothrow_move_constructible<_Tp>())
291 if (__other._M_engaged)
292 this->_M_construct(std::move(__other._M_get()));
296 operator=(const _Optional_base& __other)
298 if (this->_M_engaged && __other._M_engaged)
299 this->_M_get() = __other._M_get();
302 if (__other._M_engaged)
303 this->_M_construct(__other._M_get());
311 operator=(_Optional_base&& __other)
312 noexcept(__and_<is_nothrow_move_constructible<_Tp>,
313 is_nothrow_move_assignable<_Tp>>())
315 if (this->_M_engaged && __other._M_engaged)
316 this->_M_get() = std::move(__other._M_get());
319 if (__other._M_engaged)
320 this->_M_construct(std::move(__other._M_get()));
328 // ~_Optional_base() noexcept = default;
331 constexpr bool _M_is_engaged() const noexcept
332 { return this->_M_engaged; }
336 { return _M_payload; }
339 _M_get() const noexcept
340 { return _M_payload; }
342 template<typename... _Args>
344 _M_construct(_Args&&... __args)
345 noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
347 ::new (std::__addressof(this->_M_payload))
348 _Stored_type(std::forward<_Args>(__args)...);
349 this->_M_engaged = true;
355 this->_M_engaged = false;
356 this->_M_payload.~_Stored_type();
362 if (this->_M_engaged)
367 struct _Empty_byte { };
370 _Empty_byte _M_empty;
371 _Stored_type _M_payload;
373 bool _M_engaged = false;
376 template<typename _Tp>
379 template<typename _Tp, typename _Up>
380 using __converts_from_optional =
381 __or_<is_constructible<_Tp, const optional<_Up>&>,
382 is_constructible<_Tp, optional<_Up>&>,
383 is_constructible<_Tp, const optional<_Up>&&>,
384 is_constructible<_Tp, optional<_Up>&&>,
385 is_convertible<const optional<_Up>&, _Tp>,
386 is_convertible<optional<_Up>&, _Tp>,
387 is_convertible<const optional<_Up>&&, _Tp>,
388 is_convertible<optional<_Up>&&, _Tp>>;
390 template<typename _Tp, typename _Up>
391 using __assigns_from_optional =
392 __or_<is_assignable<_Tp&, const optional<_Up>&>,
393 is_assignable<_Tp&, optional<_Up>&>,
394 is_assignable<_Tp&, const optional<_Up>&&>,
395 is_assignable<_Tp&, optional<_Up>&&>>;
398 * @brief Class template for optional values.
400 template<typename _Tp>
402 : private _Optional_base<_Tp>,
403 private _Enable_copy_move<
405 is_copy_constructible<_Tp>::value,
407 __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value,
409 is_move_constructible<_Tp>::value,
411 __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value,
415 static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>, nullopt_t>>,
416 __not_<is_same<remove_cv_t<_Tp>, in_place_t>>,
417 __not_<is_reference<_Tp>>>(),
418 "Invalid instantiation of optional<T>");
421 using _Base = _Optional_base<_Tp>;
424 using value_type = _Tp;
426 constexpr optional() = default;
428 constexpr optional(nullopt_t) noexcept
431 // Converting constructors for engaged optionals.
432 template <typename _Up = _Tp,
434 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
435 __not_<is_same<in_place_t, decay_t<_Up>>>,
436 is_constructible<_Tp, _Up&&>,
437 is_convertible<_Up&&, _Tp>
438 >::value, bool> = true>
439 constexpr optional(_Up&& __t)
440 : _Base(std::in_place, std::forward<_Up>(__t)) { }
442 template <typename _Up = _Tp,
444 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
445 __not_<is_same<in_place_t, decay_t<_Up>>>,
446 is_constructible<_Tp, _Up&&>,
447 __not_<is_convertible<_Up&&, _Tp>>
448 >::value, bool> = false>
449 explicit constexpr optional(_Up&& __t)
450 : _Base(std::in_place, std::forward<_Up>(__t)) { }
452 template <typename _Up,
454 __not_<is_same<_Tp, _Up>>,
455 is_constructible<_Tp, const _Up&>,
456 is_convertible<const _Up&, _Tp>,
457 __not_<__converts_from_optional<_Tp, _Up>>
458 >::value, bool> = true>
459 constexpr optional(const optional<_Up>& __t)
465 template <typename _Up,
467 __not_<is_same<_Tp, _Up>>,
468 is_constructible<_Tp, const _Up&>,
469 __not_<is_convertible<const _Up&, _Tp>>,
470 __not_<__converts_from_optional<_Tp, _Up>>
471 >::value, bool> = false>
472 explicit constexpr optional(const optional<_Up>& __t)
478 template <typename _Up,
480 __not_<is_same<_Tp, _Up>>,
481 is_constructible<_Tp, _Up&&>,
482 is_convertible<_Up&&, _Tp>,
483 __not_<__converts_from_optional<_Tp, _Up>>
484 >::value, bool> = true>
485 constexpr optional(optional<_Up>&& __t)
488 emplace(std::move(*__t));
491 template <typename _Up,
493 __not_<is_same<_Tp, _Up>>,
494 is_constructible<_Tp, _Up&&>,
495 __not_<is_convertible<_Up&&, _Tp>>,
496 __not_<__converts_from_optional<_Tp, _Up>>
497 >::value, bool> = false>
498 explicit constexpr optional(optional<_Up>&& __t)
501 emplace(std::move(*__t));
504 template<typename... _Args,
505 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false>
506 explicit constexpr optional(in_place_t, _Args&&... __args)
507 : _Base(std::in_place, std::forward<_Args>(__args)...) { }
509 template<typename _Up, typename... _Args,
510 enable_if_t<is_constructible_v<_Tp,
511 initializer_list<_Up>&,
512 _Args&&...>, bool> = false>
513 explicit constexpr optional(in_place_t,
514 initializer_list<_Up> __il,
516 : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { }
518 // Assignment operators.
520 operator=(nullopt_t) noexcept
526 template<typename _Up = _Tp>
528 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
529 is_constructible<_Tp, _Up>,
530 __not_<__and_<is_scalar<_Tp>,
531 is_same<_Tp, decay_t<_Up>>>>,
532 is_assignable<_Tp&, _Up>>::value,
536 if (this->_M_is_engaged())
537 this->_M_get() = std::forward<_Up>(__u);
539 this->_M_construct(std::forward<_Up>(__u));
544 template<typename _Up>
546 __not_<is_same<_Tp, _Up>>,
547 is_constructible<_Tp, const _Up&>,
548 is_assignable<_Tp&, _Up>,
549 __not_<__converts_from_optional<_Tp, _Up>>,
550 __not_<__assigns_from_optional<_Tp, _Up>>
553 operator=(const optional<_Up>& __u)
557 if (this->_M_is_engaged())
558 this->_M_get() = *__u;
560 this->_M_construct(*__u);
569 template<typename _Up>
571 __not_<is_same<_Tp, _Up>>,
572 is_constructible<_Tp, _Up>,
573 is_assignable<_Tp&, _Up>,
574 __not_<__converts_from_optional<_Tp, _Up>>,
575 __not_<__assigns_from_optional<_Tp, _Up>>
578 operator=(optional<_Up>&& __u)
582 if (this->_M_is_engaged())
583 this->_M_get() = std::move(*__u);
585 this->_M_construct(std::move(*__u));
595 template<typename... _Args>
596 enable_if_t<is_constructible<_Tp, _Args&&...>::value>
597 emplace(_Args&&... __args)
600 this->_M_construct(std::forward<_Args>(__args)...);
603 template<typename _Up, typename... _Args>
604 enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
606 emplace(initializer_list<_Up> __il, _Args&&... __args)
609 this->_M_construct(__il, std::forward<_Args>(__args)...);
612 // Destructor is implicit, implemented in _Optional_base.
616 swap(optional& __other)
617 noexcept(is_nothrow_move_constructible<_Tp>()
618 && is_nothrow_swappable_v<_Tp>)
622 if (this->_M_is_engaged() && __other._M_is_engaged())
623 swap(this->_M_get(), __other._M_get());
624 else if (this->_M_is_engaged())
626 __other._M_construct(std::move(this->_M_get()));
629 else if (__other._M_is_engaged())
631 this->_M_construct(std::move(__other._M_get()));
632 __other._M_destruct();
639 { return std::__addressof(this->_M_get()); }
643 { return std::__addressof(this->_M_get()); }
647 { return this->_M_get(); }
651 { return this->_M_get(); }
655 { return std::move(this->_M_get()); }
657 constexpr const _Tp&&
659 { return std::move(this->_M_get()); }
661 constexpr explicit operator bool() const noexcept
662 { return this->_M_is_engaged(); }
664 constexpr bool has_value() const noexcept
665 { return this->_M_is_engaged(); }
670 return this->_M_is_engaged()
672 : (__throw_bad_optional_access("Attempt to access value of a "
673 "disengaged optional object"),
680 return this->_M_is_engaged()
682 : (__throw_bad_optional_access("Attempt to access value of a "
683 "disengaged optional object"),
690 return this->_M_is_engaged()
691 ? std::move(this->_M_get())
692 : (__throw_bad_optional_access("Attempt to access value of a "
693 "disengaged optional object"),
694 std::move(this->_M_get()));
697 constexpr const _Tp&&
700 return this->_M_is_engaged()
701 ? std::move(this->_M_get())
702 : (__throw_bad_optional_access("Attempt to access value of a "
703 "disengaged optional object"),
704 std::move(this->_M_get()));
707 template<typename _Up>
709 value_or(_Up&& __u) const&
711 static_assert(__and_<is_copy_constructible<_Tp>,
712 is_convertible<_Up&&, _Tp>>(),
713 "Cannot return value");
715 return this->_M_is_engaged()
717 : static_cast<_Tp>(std::forward<_Up>(__u));
720 template<typename _Up>
722 value_or(_Up&& __u) &&
724 static_assert(__and_<is_move_constructible<_Tp>,
725 is_convertible<_Up&&, _Tp>>(),
726 "Cannot return value" );
728 return this->_M_is_engaged()
729 ? std::move(this->_M_get())
730 : static_cast<_Tp>(std::forward<_Up>(__u));
732 void reset() noexcept { this->_M_reset(); }
735 template<typename _Tp>
736 using __optional_relop_t =
737 enable_if_t<is_convertible<_Tp, bool>::value, bool>;
739 // Comparisons between optional values.
740 template<typename _Tp>
742 operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
743 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Tp>())>
745 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
746 && (!__lhs || *__lhs == *__rhs);
749 template<typename _Tp>
751 operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
752 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Tp>())>
754 return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
755 || (static_cast<bool>(__lhs) && *__lhs != *__rhs);
758 template<typename _Tp>
760 operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
761 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Tp>())>
763 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
766 template<typename _Tp>
768 operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
769 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Tp>())>
771 return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
774 template<typename _Tp>
776 operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
777 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Tp>())>
779 return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
782 template<typename _Tp>
784 operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
785 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Tp>())>
787 return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
790 // Comparisons with nullopt.
791 template<typename _Tp>
793 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
796 template<typename _Tp>
798 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
801 template<typename _Tp>
803 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
804 { return static_cast<bool>(__lhs); }
806 template<typename _Tp>
808 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
809 { return static_cast<bool>(__rhs); }
811 template<typename _Tp>
813 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
816 template<typename _Tp>
818 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
819 { return static_cast<bool>(__rhs); }
821 template<typename _Tp>
823 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
824 { return static_cast<bool>(__lhs); }
826 template<typename _Tp>
828 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
831 template<typename _Tp>
833 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
836 template<typename _Tp>
838 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
841 template<typename _Tp>
843 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
846 template<typename _Tp>
848 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
851 // Comparisons with value type.
852 template<typename _Tp>
854 operator==(const optional<_Tp>& __lhs, const _Tp& __rhs)
855 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Tp>())>
856 { return __lhs && *__lhs == __rhs; }
858 template<typename _Tp>
860 operator==(const _Tp& __lhs, const optional<_Tp>& __rhs)
861 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Tp>())>
862 { return __rhs && __lhs == *__rhs; }
864 template<typename _Tp>
866 operator!=(const optional<_Tp>& __lhs, const _Tp& __rhs)
867 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Tp>())>
868 { return !__lhs || *__lhs != __rhs; }
870 template<typename _Tp>
872 operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs)
873 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Tp>())>
874 { return !__rhs || __lhs != *__rhs; }
876 template<typename _Tp>
878 operator<(const optional<_Tp>& __lhs, const _Tp& __rhs)
879 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Tp>())>
880 { return !__lhs || *__lhs < __rhs; }
882 template<typename _Tp>
884 operator<(const _Tp& __lhs, const optional<_Tp>& __rhs)
885 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Tp>())>
886 { return __rhs && __lhs < *__rhs; }
888 template<typename _Tp>
890 operator>(const optional<_Tp>& __lhs, const _Tp& __rhs)
891 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Tp>())>
892 { return __lhs && *__lhs > __rhs; }
894 template<typename _Tp>
896 operator>(const _Tp& __lhs, const optional<_Tp>& __rhs)
897 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Tp>())>
898 { return !__rhs || __lhs > *__rhs; }
900 template<typename _Tp>
902 operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs)
903 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Tp>())>
904 { return !__lhs || *__lhs <= __rhs; }
906 template<typename _Tp>
908 operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs)
909 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Tp>())>
910 { return __rhs && __lhs <= *__rhs; }
912 template<typename _Tp>
914 operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs)
915 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Tp>())>
916 { return __lhs && *__lhs >= __rhs; }
918 template<typename _Tp>
920 operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs)
921 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Tp>())>
922 { return !__rhs || __lhs >= *__rhs; }
924 // Swap and creation functions.
926 // _GLIBCXX_RESOLVE_LIB_DEFECTS
927 // 2748. swappable traits for optionals
928 template<typename _Tp>
929 inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>>
930 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
931 noexcept(noexcept(__lhs.swap(__rhs)))
932 { __lhs.swap(__rhs); }
934 template<typename _Tp>
935 enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)>
936 swap(optional<_Tp>&, optional<_Tp>&) = delete;
938 template<typename _Tp>
939 constexpr optional<decay_t<_Tp>>
940 make_optional(_Tp&& __t)
941 { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
943 template<typename _Tp, typename ..._Args>
944 constexpr optional<_Tp>
945 make_optional(_Args&&... __args)
946 { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; }
948 template<typename _Tp, typename _Up, typename ..._Args>
949 constexpr optional<_Tp>
950 make_optional(initializer_list<_Up> __il, _Args&&... __args)
951 { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; }
954 template<typename _Tp>
955 struct hash<optional<_Tp>> : private __poison_hash<remove_const_t<_Tp>>
957 using result_type = size_t;
958 using argument_type = optional<_Tp>;
961 operator()(const optional<_Tp>& __t) const
962 noexcept(noexcept(hash<_Tp> {}(*__t)))
964 // We pick an arbitrary hash for disengaged optionals which hopefully
965 // usual values of _Tp won't typically hash to.
966 constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
967 return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash;
973 _GLIBCXX_END_NAMESPACE_VERSION
978 #endif // _GLIBCXX_OPTIONAL