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 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<_Tp,
137 initializer_list<_Up>&,
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 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<_Tp,
273 initializer_list<_Up>&,
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 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 is_constructible<_Tp, _Up&&>,
445 __not_<is_convertible<_Up&&, _Tp>>
446 >::value, bool> = false>
447 explicit constexpr optional(_Up&& __t)
448 : _Base(std::in_place, std::forward<_Up>(__t)) { }
450 template <typename _Up,
452 __not_<is_same<_Tp, _Up>>,
453 is_constructible<_Tp, const _Up&>,
454 is_convertible<const _Up&, _Tp>,
455 __not_<__converts_from_optional<_Tp, _Up>>
456 >::value, bool> = true>
457 constexpr optional(const optional<_Up>& __t)
463 template <typename _Up,
465 __not_<is_same<_Tp, _Up>>,
466 is_constructible<_Tp, const _Up&>,
467 __not_<is_convertible<const _Up&, _Tp>>,
468 __not_<__converts_from_optional<_Tp, _Up>>
469 >::value, bool> = false>
470 explicit constexpr optional(const optional<_Up>& __t)
476 template <typename _Up,
478 __not_<is_same<_Tp, _Up>>,
479 is_constructible<_Tp, _Up&&>,
480 is_convertible<_Up&&, _Tp>,
481 __not_<__converts_from_optional<_Tp, _Up>>
482 >::value, bool> = true>
483 constexpr optional(optional<_Up>&& __t)
486 emplace(std::move(*__t));
489 template <typename _Up,
491 __not_<is_same<_Tp, _Up>>,
492 is_constructible<_Tp, _Up&&>,
493 __not_<is_convertible<_Up&&, _Tp>>,
494 __not_<__converts_from_optional<_Tp, _Up>>
495 >::value, bool> = false>
496 explicit constexpr optional(optional<_Up>&& __t)
499 emplace(std::move(*__t));
502 template<typename... _Args>
503 explicit constexpr optional(in_place_t, _Args&&... __args)
504 : _Base(std::in_place, std::forward<_Args>(__args)...) { }
506 template<typename _Up, typename... _Args,
507 enable_if_t<is_constructible<_Tp,
508 initializer_list<_Up>&,
511 explicit constexpr optional(in_place_t,
512 initializer_list<_Up> __il,
514 : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { }
516 // Assignment operators.
518 operator=(nullopt_t) noexcept
524 template<typename _Up = _Tp>
526 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
527 is_constructible<_Tp, _Up>,
528 __not_<__and_<is_scalar<_Tp>,
529 is_same<_Tp, decay_t<_Up>>>>,
530 is_assignable<_Tp&, _Up>>::value,
534 if (this->_M_is_engaged())
535 this->_M_get() = std::forward<_Up>(__u);
537 this->_M_construct(std::forward<_Up>(__u));
542 template<typename _Up>
544 __not_<is_same<_Tp, _Up>>,
545 is_constructible<_Tp, const _Up&>,
546 is_assignable<_Tp&, _Up>,
547 __not_<__converts_from_optional<_Tp, _Up>>,
548 __not_<__assigns_from_optional<_Tp, _Up>>
551 operator=(const optional<_Up>& __u)
555 if (this->_M_is_engaged())
556 this->_M_get() = *__u;
558 this->_M_construct(*__u);
567 template<typename _Up>
569 __not_<is_same<_Tp, _Up>>,
570 is_constructible<_Tp, _Up>,
571 is_assignable<_Tp&, _Up>,
572 __not_<__converts_from_optional<_Tp, _Up>>,
573 __not_<__assigns_from_optional<_Tp, _Up>>
576 operator=(optional<_Up>&& __u)
580 if (this->_M_is_engaged())
581 this->_M_get() = std::move(*__u);
583 this->_M_construct(std::move(*__u));
593 template<typename... _Args>
594 enable_if_t<is_constructible<_Tp, _Args&&...>::value>
595 emplace(_Args&&... __args)
598 this->_M_construct(std::forward<_Args>(__args)...);
601 template<typename _Up, typename... _Args>
602 enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
604 emplace(initializer_list<_Up> __il, _Args&&... __args)
607 this->_M_construct(__il, std::forward<_Args>(__args)...);
610 // Destructor is implicit, implemented in _Optional_base.
614 swap(optional& __other)
615 noexcept(is_nothrow_move_constructible<_Tp>()
616 && is_nothrow_swappable_v<_Tp>)
620 if (this->_M_is_engaged() && __other._M_is_engaged())
621 swap(this->_M_get(), __other._M_get());
622 else if (this->_M_is_engaged())
624 __other._M_construct(std::move(this->_M_get()));
627 else if (__other._M_is_engaged())
629 this->_M_construct(std::move(__other._M_get()));
630 __other._M_destruct();
637 { return std::__addressof(this->_M_get()); }
641 { return std::__addressof(this->_M_get()); }
645 { return this->_M_get(); }
649 { return this->_M_get(); }
653 { return std::move(this->_M_get()); }
655 constexpr const _Tp&&
657 { return std::move(this->_M_get()); }
659 constexpr explicit operator bool() const noexcept
660 { return this->_M_is_engaged(); }
662 constexpr bool has_value() const noexcept
663 { return this->_M_is_engaged(); }
668 return this->_M_is_engaged()
670 : (__throw_bad_optional_access("Attempt to access value of a "
671 "disengaged optional object"),
678 return this->_M_is_engaged()
680 : (__throw_bad_optional_access("Attempt to access value of a "
681 "disengaged optional object"),
688 return this->_M_is_engaged()
689 ? std::move(this->_M_get())
690 : (__throw_bad_optional_access("Attempt to access value of a "
691 "disengaged optional object"),
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("Attempt to access value of a "
701 "disengaged optional object"),
702 std::move(this->_M_get()));
705 template<typename _Up>
707 value_or(_Up&& __u) const&
709 static_assert(__and_<is_copy_constructible<_Tp>,
710 is_convertible<_Up&&, _Tp>>(),
711 "Cannot return value");
713 return this->_M_is_engaged()
715 : static_cast<_Tp>(std::forward<_Up>(__u));
718 template<typename _Up>
720 value_or(_Up&& __u) &&
722 static_assert(__and_<is_move_constructible<_Tp>,
723 is_convertible<_Up&&, _Tp>>(),
724 "Cannot return value" );
726 return this->_M_is_engaged()
727 ? std::move(this->_M_get())
728 : static_cast<_Tp>(std::forward<_Up>(__u));
730 void reset() noexcept { this->_M_reset(); }
733 template<typename _Tp>
734 using __optional_relop_t =
735 enable_if_t<is_convertible<_Tp, bool>::value, bool>;
737 // Comparisons between optional values.
738 template<typename _Tp>
740 operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
741 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Tp>())>
743 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
744 && (!__lhs || *__lhs == *__rhs);
747 template<typename _Tp>
749 operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
750 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Tp>())>
752 return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
753 || (static_cast<bool>(__lhs) && *__lhs != *__rhs);
756 template<typename _Tp>
758 operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
759 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Tp>())>
761 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
764 template<typename _Tp>
766 operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
767 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Tp>())>
769 return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
772 template<typename _Tp>
774 operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
775 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Tp>())>
777 return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
780 template<typename _Tp>
782 operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
783 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Tp>())>
785 return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
788 // Comparisons with nullopt.
789 template<typename _Tp>
791 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
794 template<typename _Tp>
796 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
799 template<typename _Tp>
801 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
802 { return static_cast<bool>(__lhs); }
804 template<typename _Tp>
806 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
807 { return static_cast<bool>(__rhs); }
809 template<typename _Tp>
811 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
814 template<typename _Tp>
816 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
817 { return static_cast<bool>(__rhs); }
819 template<typename _Tp>
821 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
822 { return static_cast<bool>(__lhs); }
824 template<typename _Tp>
826 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
829 template<typename _Tp>
831 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
834 template<typename _Tp>
836 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
839 template<typename _Tp>
841 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
844 template<typename _Tp>
846 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
849 // Comparisons with value type.
850 template<typename _Tp>
852 operator==(const optional<_Tp>& __lhs, const _Tp& __rhs)
853 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Tp>())>
854 { return __lhs && *__lhs == __rhs; }
856 template<typename _Tp>
858 operator==(const _Tp& __lhs, const optional<_Tp>& __rhs)
859 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Tp>())>
860 { return __rhs && __lhs == *__rhs; }
862 template<typename _Tp>
864 operator!=(const optional<_Tp>& __lhs, const _Tp& __rhs)
865 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Tp>())>
866 { return !__lhs || *__lhs != __rhs; }
868 template<typename _Tp>
870 operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs)
871 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Tp>())>
872 { return !__rhs || __lhs != *__rhs; }
874 template<typename _Tp>
876 operator<(const optional<_Tp>& __lhs, const _Tp& __rhs)
877 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Tp>())>
878 { return !__lhs || *__lhs < __rhs; }
880 template<typename _Tp>
882 operator<(const _Tp& __lhs, const optional<_Tp>& __rhs)
883 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Tp>())>
884 { return __rhs && __lhs < *__rhs; }
886 template<typename _Tp>
888 operator>(const optional<_Tp>& __lhs, const _Tp& __rhs)
889 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Tp>())>
890 { return __lhs && *__lhs > __rhs; }
892 template<typename _Tp>
894 operator>(const _Tp& __lhs, const optional<_Tp>& __rhs)
895 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Tp>())>
896 { return !__rhs || __lhs > *__rhs; }
898 template<typename _Tp>
900 operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs)
901 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Tp>())>
902 { return !__lhs || *__lhs <= __rhs; }
904 template<typename _Tp>
906 operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs)
907 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Tp>())>
908 { return __rhs && __lhs <= *__rhs; }
910 template<typename _Tp>
912 operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs)
913 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Tp>())>
914 { return __lhs && *__lhs >= __rhs; }
916 template<typename _Tp>
918 operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs)
919 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Tp>())>
920 { return !__rhs || __lhs >= *__rhs; }
922 // Swap and creation functions.
924 // _GLIBCXX_RESOLVE_LIB_DEFECTS
925 // 2748. swappable traits for optionals
926 template<typename _Tp>
927 inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>>
928 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
929 noexcept(noexcept(__lhs.swap(__rhs)))
930 { __lhs.swap(__rhs); }
932 template<typename _Tp>
933 constexpr optional<decay_t<_Tp>>
934 make_optional(_Tp&& __t)
935 { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
937 template<typename _Tp, typename ..._Args>
938 constexpr optional<_Tp>
939 make_optional(_Args&&... __args)
940 { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; }
942 template<typename _Tp, typename _Up, typename ..._Args>
943 constexpr optional<_Tp>
944 make_optional(initializer_list<_Up> __il, _Args&&... __args)
945 { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; }
948 template<typename _Tp>
949 struct hash<optional<_Tp>> : private __poison_hash<remove_const_t<_Tp>>
951 using result_type = size_t;
952 using argument_type = optional<_Tp>;
955 operator()(const optional<_Tp>& __t) const
956 noexcept(noexcept(hash<_Tp> {}(*__t)))
958 // We pick an arbitrary hash for disengaged optionals which hopefully
959 // usual values of _Tp won't typically hash to.
960 constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
961 return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash;
967 _GLIBCXX_END_NAMESPACE_VERSION
972 #endif // _GLIBCXX_OPTIONAL