29 #ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL
30 #define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1
44 #if __cplusplus <= 201103L
58 namespace std _GLIBCXX_VISIBILITY(default)
60 namespace experimental
62 inline namespace fundamentals_v1
64 _GLIBCXX_BEGIN_NAMESPACE_VERSION
77 #define __cpp_lib_experimental_optional 201411
82 template<
typename _Tp>
101 enum class _Construct { _Token };
104 explicit constexpr
nullopt_t(_Construct) { }
129 __throw_bad_optional_access(
const char*)
130 __attribute__((__noreturn__));
134 __throw_bad_optional_access(const
char* __s)
137 #ifndef __cpp_lib_addressof_constexpr
138 template<
typename _Tp,
typename =
void>
141 template<
typename _Tp>
142 struct _Has_addressof_mem<_Tp,
143 __void_t<decltype( std::declval<const _Tp&>().operator&() )>
147 template<
typename _Tp,
typename =
void>
150 template<
typename _Tp>
151 struct _Has_addressof_free<_Tp,
152 __void_t<decltype( operator&(std::declval<const _Tp&>()) )>
163 template<
typename _Tp>
165 : std::__or_<_Has_addressof_mem<_Tp>, _Has_addressof_free<_Tp>>::type
174 template<
typename _Tp>
176 enable_if_t<!_Has_addressof<_Tp>::value, _Tp*>
183 template<
typename _Tp>
185 enable_if_t<_Has_addressof<_Tp>::value, _Tp*>
188 #endif // __cpp_lib_addressof_constexpr
202 template<
typename _Tp,
bool _ShouldProvideDestructor =
203 !is_trivially_destructible<_Tp>::value>
210 using _Stored_type = remove_const_t<_Tp>;
223 template<
typename... _Args>
225 : _M_payload(std::forward<_Args>(__args)...), _M_engaged(
true) { }
227 template<
typename _Up,
typename... _Args,
228 enable_if_t<is_constructible<_Tp,
235 : _M_payload(__il, std::forward<_Args>(__args)...),
239 _Optional_base(
const _Optional_base& __other)
241 if (__other._M_engaged)
242 this->_M_construct(__other._M_get());
245 _Optional_base(_Optional_base&& __other)
246 noexcept(is_nothrow_move_constructible<_Tp>())
248 if (__other._M_engaged)
249 this->_M_construct(std::move(__other._M_get()));
254 operator=(
const _Optional_base& __other)
256 if (this->_M_engaged && __other._M_engaged)
257 this->_M_get() = __other._M_get();
260 if (__other._M_engaged)
261 this->_M_construct(__other._M_get());
270 operator=(_Optional_base&& __other)
271 noexcept(__and_<is_nothrow_move_constructible<_Tp>,
272 is_nothrow_move_assignable<_Tp>>())
274 if (this->_M_engaged && __other._M_engaged)
275 this->_M_get() = std::move(__other._M_get());
278 if (__other._M_engaged)
279 this->_M_construct(std::move(__other._M_get()));
289 if (this->_M_engaged)
290 this->_M_payload.~_Stored_type();
296 constexpr
bool _M_is_engaged()
const noexcept
297 {
return this->_M_engaged; }
302 {
return _M_payload; }
305 _M_get()
const noexcept
306 {
return _M_payload; }
310 template<
typename... _Args>
312 _M_construct(_Args&&... __args)
313 noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
316 _Stored_type(std::forward<_Args>(__args)...);
317 this->_M_engaged =
true;
323 this->_M_engaged =
false;
324 this->_M_payload.~_Stored_type();
331 if (this->_M_engaged)
336 struct _Empty_byte { };
338 _Empty_byte _M_empty;
339 _Stored_type _M_payload;
341 bool _M_engaged =
false;
346 template<
typename _Tp>
350 using _Stored_type = remove_const_t<_Tp>;
359 template<
typename... _Args>
361 : _M_payload(std::forward<_Args>(__args)...), _M_engaged(
true) { }
363 template<
typename _Up,
typename... _Args,
364 enable_if_t<is_constructible<_Tp,
371 : _M_payload(__il, std::forward<_Args>(__args)...),
374 _Optional_base(
const _Optional_base& __other)
376 if (__other._M_engaged)
377 this->_M_construct(__other._M_get());
380 _Optional_base(_Optional_base&& __other)
381 noexcept(is_nothrow_move_constructible<_Tp>())
383 if (__other._M_engaged)
384 this->_M_construct(std::move(__other._M_get()));
388 operator=(
const _Optional_base& __other)
390 if (this->_M_engaged && __other._M_engaged)
391 this->_M_get() = __other._M_get();
394 if (__other._M_engaged)
395 this->_M_construct(__other._M_get());
403 operator=(_Optional_base&& __other)
404 noexcept(__and_<is_nothrow_move_constructible<_Tp>,
405 is_nothrow_move_assignable<_Tp>>())
407 if (this->_M_engaged && __other._M_engaged)
408 this->_M_get() = std::move(__other._M_get());
411 if (__other._M_engaged)
412 this->_M_construct(std::move(__other._M_get()));
423 constexpr
bool _M_is_engaged()
const noexcept
424 {
return this->_M_engaged; }
428 {
return _M_payload; }
431 _M_get()
const noexcept
432 {
return _M_payload; }
434 template<
typename... _Args>
436 _M_construct(_Args&&... __args)
437 noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
440 _Stored_type(std::forward<_Args>(__args)...);
441 this->_M_engaged =
true;
447 this->_M_engaged =
false;
448 this->_M_payload.~_Stored_type();
454 if (this->_M_engaged)
459 struct _Empty_byte { };
462 _Empty_byte _M_empty;
463 _Stored_type _M_payload;
465 bool _M_engaged =
false;
468 template<
typename _Tp>
471 template<
typename _Tp,
typename _Up>
472 using __converts_from_optional =
473 __or_<is_constructible<_Tp, const optional<_Up>&>,
474 is_constructible<_Tp, optional<_Up>&>,
475 is_constructible<_Tp, const optional<_Up>&&>,
476 is_constructible<_Tp, optional<_Up>&&>,
477 is_convertible<const optional<_Up>&, _Tp>,
478 is_convertible<optional<_Up>&, _Tp>,
479 is_convertible<const optional<_Up>&&, _Tp>,
480 is_convertible<optional<_Up>&&, _Tp>>;
482 template<
typename _Tp,
typename _Up>
483 using __assigns_from_optional =
484 __or_<is_assignable<_Tp&, const optional<_Up>&>,
485 is_assignable<_Tp&, optional<_Up>&>,
486 is_assignable<_Tp&, const optional<_Up>&&>,
487 is_assignable<_Tp&, optional<_Up>&&>>;
492 template<
typename _Tp>
497 is_copy_constructible<_Tp>::value,
499 __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value,
501 is_move_constructible<_Tp>::value,
503 __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value,
507 static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>,
nullopt_t>>,
508 __not_<is_same<remove_cv_t<_Tp>,
in_place_t>>,
510 "Invalid instantiation of optional<T>");
516 using value_type = _Tp;
523 template <
typename _Up = _Tp,
525 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
526 is_constructible<_Tp, _Up&&>,
527 is_convertible<_Up&&, _Tp>
528 >::value,
bool> =
true>
532 template <
typename _Up = _Tp,
534 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
535 is_constructible<_Tp, _Up&&>,
536 __not_<is_convertible<_Up&&, _Tp>>
537 >::value,
bool> =
false>
538 explicit constexpr optional(_Up&& __t)
541 template <
typename _Up,
543 __not_<is_same<_Tp, _Up>>,
544 is_constructible<_Tp, const _Up&>,
545 is_convertible<const _Up&, _Tp>,
546 __not_<__converts_from_optional<_Tp, _Up>>
547 >::value,
bool> =
true>
548 constexpr optional(
const optional<_Up>& __t)
554 template <
typename _Up,
556 __not_<is_same<_Tp, _Up>>,
557 is_constructible<_Tp, const _Up&>,
558 __not_<is_convertible<const _Up&, _Tp>>,
559 __not_<__converts_from_optional<_Tp, _Up>>
560 >::value,
bool> =
false>
561 explicit constexpr optional(
const optional<_Up>& __t)
567 template <
typename _Up,
569 __not_<is_same<_Tp, _Up>>,
570 is_constructible<_Tp, _Up&&>,
571 is_convertible<_Up&&, _Tp>,
572 __not_<__converts_from_optional<_Tp, _Up>>
573 >::value,
bool> =
true>
574 constexpr optional(optional<_Up>&& __t)
577 emplace(std::move(*__t));
580 template <
typename _Up,
582 __not_<is_same<_Tp, _Up>>,
583 is_constructible<_Tp, _Up&&>,
584 __not_<is_convertible<_Up&&, _Tp>>,
585 __not_<__converts_from_optional<_Tp, _Up>>
586 >::value,
bool> =
false>
587 explicit constexpr optional(optional<_Up>&& __t)
590 emplace(std::move(*__t));
595 operator=(nullopt_t) noexcept
601 template<
typename _Up = _Tp>
603 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
604 is_constructible<_Tp, _Up>,
605 __not_<__and_<is_scalar<_Tp>,
606 is_same<_Tp, decay_t<_Up>>>>,
607 is_assignable<_Tp&, _Up>>::value,
611 if (this->_M_is_engaged())
612 this->_M_get() = std::forward<_Up>(__u);
614 this->_M_construct(std::forward<_Up>(__u));
619 template<
typename _Up>
621 __not_<is_same<_Tp, _Up>>,
622 is_constructible<_Tp, const _Up&>,
623 is_assignable<_Tp&, _Up>,
624 __not_<__converts_from_optional<_Tp, _Up>>,
625 __not_<__assigns_from_optional<_Tp, _Up>>
628 operator=(
const optional<_Up>& __u)
632 if (this->_M_is_engaged())
633 this->_M_get() = *__u;
635 this->_M_construct(*__u);
644 template<
typename _Up>
646 __not_<is_same<_Tp, _Up>>,
647 is_constructible<_Tp, _Up>,
648 is_assignable<_Tp&, _Up>,
649 __not_<__converts_from_optional<_Tp, _Up>>,
650 __not_<__assigns_from_optional<_Tp, _Up>>
653 operator=(optional<_Up>&& __u)
657 if (this->_M_is_engaged())
658 this->_M_get() = std::move(*__u);
660 this->_M_construct(std::move(*__u));
670 template<
typename... _Args>
671 enable_if_t<is_constructible<_Tp, _Args&&...>::value>
672 emplace(_Args&&... __args)
675 this->_M_construct(std::forward<_Args>(__args)...);
678 template<
typename _Up,
typename... _Args>
679 enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
681 emplace(initializer_list<_Up> __il, _Args&&... __args)
684 this->_M_construct(__il, std::forward<_Args>(__args)...);
691 swap(optional& __other)
692 noexcept(is_nothrow_move_constructible<_Tp>()
693 && noexcept(swap(declval<_Tp&>(), declval<_Tp&>())))
697 if (this->_M_is_engaged() && __other._M_is_engaged())
698 swap(this->_M_get(), __other._M_get());
699 else if (this->_M_is_engaged())
701 __other._M_construct(std::move(this->_M_get()));
704 else if (__other._M_is_engaged())
706 this->_M_construct(std::move(__other._M_get()));
707 __other._M_destruct();
715 #ifndef __cpp_lib_addressof_constexpr
728 {
return this->_M_get(); }
732 {
return this->_M_get(); }
736 {
return std::move(this->_M_get()); }
738 constexpr
const _Tp&&
740 {
return std::move(this->_M_get()); }
742 constexpr
explicit operator bool() const noexcept
743 {
return this->_M_is_engaged(); }
748 return this->_M_is_engaged()
750 : (__throw_bad_optional_access(
"Attempt to access value of a "
751 "disengaged optional object"),
758 return this->_M_is_engaged()
760 : (__throw_bad_optional_access(
"Attempt to access value of a "
761 "disengaged optional object"),
768 return this->_M_is_engaged()
769 ? std::move(this->_M_get())
770 : (__throw_bad_optional_access(
"Attempt to access value of a "
771 "disengaged optional object"),
772 std::move(this->_M_get()));
775 constexpr
const _Tp&&
778 return this->_M_is_engaged()
779 ? std::move(this->_M_get())
780 : (__throw_bad_optional_access(
"Attempt to access value of a "
781 "disengaged optional object"),
782 std::move(this->_M_get()));
785 template<
typename _Up>
787 value_or(_Up&& __u) const&
789 static_assert(__and_<is_copy_constructible<_Tp>,
790 is_convertible<_Up&&, _Tp>>(),
791 "Cannot return value");
793 return this->_M_is_engaged()
795 : static_cast<_Tp>(std::
forward<_Up>(__u));
798 template<
typename _Up>
800 value_or(_Up&& __u) &&
802 static_assert(__and_<is_move_constructible<_Tp>,
803 is_convertible<_Up&&, _Tp>>(),
804 "Cannot return value" );
806 return this->_M_is_engaged()
807 ? std::move(this->_M_get())
808 : static_cast<_Tp>(std::
forward<_Up>(__u));
813 template<
typename _Tp>
815 operator==(
const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
817 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
818 && (!__lhs || *__lhs == *__rhs);
821 template<
typename _Tp>
823 operator!=(
const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
824 {
return !(__lhs == __rhs); }
826 template<
typename _Tp>
828 operator<(const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
830 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
833 template<
typename _Tp>
835 operator>(
const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
836 {
return __rhs < __lhs; }
838 template<
typename _Tp>
840 operator<=(const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
841 {
return !(__rhs < __lhs); }
843 template<
typename _Tp>
845 operator>=(
const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
846 {
return !(__lhs < __rhs); }
849 template<
typename _Tp>
851 operator==(
const optional<_Tp>& __lhs, nullopt_t) noexcept
854 template<
typename _Tp>
856 operator==(nullopt_t,
const optional<_Tp>& __rhs) noexcept
859 template<
typename _Tp>
861 operator!=(
const optional<_Tp>& __lhs, nullopt_t) noexcept
862 {
return static_cast<bool>(__lhs); }
864 template<
typename _Tp>
866 operator!=(nullopt_t,
const optional<_Tp>& __rhs) noexcept
867 {
return static_cast<bool>(__rhs); }
869 template<
typename _Tp>
871 operator<(const optional<_Tp>& , nullopt_t) noexcept
874 template<
typename _Tp>
876 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
877 {
return static_cast<bool>(__rhs); }
879 template<
typename _Tp>
881 operator>(
const optional<_Tp>& __lhs, nullopt_t) noexcept
882 {
return static_cast<bool>(__lhs); }
884 template<
typename _Tp>
886 operator>(nullopt_t,
const optional<_Tp>& ) noexcept
889 template<
typename _Tp>
891 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
894 template<
typename _Tp>
896 operator<=(nullopt_t, const optional<_Tp>& ) noexcept
899 template<
typename _Tp>
901 operator>=(
const optional<_Tp>& , nullopt_t) noexcept
904 template<
typename _Tp>
906 operator>=(nullopt_t,
const optional<_Tp>& __rhs) noexcept
910 template<
typename _Tp>
912 operator==(
const optional<_Tp>& __lhs,
const _Tp& __rhs)
913 {
return __lhs && *__lhs == __rhs; }
915 template<
typename _Tp>
917 operator==(
const _Tp& __lhs,
const optional<_Tp>& __rhs)
918 {
return __rhs && __lhs == *__rhs; }
920 template<
typename _Tp>
922 operator!=(
const optional<_Tp>& __lhs, _Tp
const& __rhs)
923 {
return !__lhs || !(*__lhs == __rhs); }
925 template<
typename _Tp>
927 operator!=(
const _Tp& __lhs,
const optional<_Tp>& __rhs)
928 {
return !__rhs || !(__lhs == *__rhs); }
930 template<
typename _Tp>
932 operator<(const optional<_Tp>& __lhs,
const _Tp& __rhs)
933 {
return !__lhs || *__lhs < __rhs; }
935 template<
typename _Tp>
937 operator<(const _Tp& __lhs, const optional<_Tp>& __rhs)
938 {
return __rhs && __lhs < *__rhs; }
940 template<
typename _Tp>
942 operator>(
const optional<_Tp>& __lhs,
const _Tp& __rhs)
943 {
return __lhs && __rhs < *__lhs; }
945 template<
typename _Tp>
947 operator>(
const _Tp& __lhs,
const optional<_Tp>& __rhs)
948 {
return !__rhs || *__rhs < __lhs; }
950 template<
typename _Tp>
952 operator<=(const optional<_Tp>& __lhs,
const _Tp& __rhs)
953 {
return !__lhs || !(__rhs < *__lhs); }
955 template<
typename _Tp>
957 operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs)
958 {
return __rhs && !(*__rhs < __lhs); }
960 template<
typename _Tp>
962 operator>=(
const optional<_Tp>& __lhs,
const _Tp& __rhs)
963 {
return __lhs && !(*__lhs < __rhs); }
965 template<
typename _Tp>
967 operator>=(
const _Tp& __lhs,
const optional<_Tp>& __rhs)
968 {
return !__rhs || !(__lhs < *__rhs); }
971 template<
typename _Tp>
973 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
974 noexcept(noexcept(__lhs.swap(__rhs)))
975 { __lhs.swap(__rhs); }
977 template<
typename _Tp>
978 constexpr optional<decay_t<_Tp>>
979 make_optional(_Tp&& __t)
980 {
return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
983 _GLIBCXX_END_NAMESPACE_VERSION
988 template<
typename _Tp>
989 struct hash<experimental::optional<_Tp>>
991 using result_type = size_t;
992 using argument_type = experimental::optional<_Tp>;
995 operator()(
const experimental::optional<_Tp>& __t)
const
996 noexcept(noexcept(hash<_Tp> {}(*__t)))
1000 constexpr
size_t __magic_disengaged_hash =
static_cast<size_t>(-3333);
1001 return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash;
1008 #endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Class template for optional values.
Exception class thrown when a disengaged optional object is dereferenced.
constexpr in_place_t in_place
Tag for in-place construction.
Tag type to disengage optional objects.
logic_error(const string &__arg) _GLIBCXX_TXN_SAFE
Trait that detects the presence of an overloaded unary operator&.
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
A mixin helper to conditionally enable or disable the copy/move special members.
One of two subclasses of exception.
constexpr enable_if_t<!_Has_addressof< _Tp >::value, _Tp * > __constexpr_addressof(_Tp &__t)
An overload that attempts to take the address of an lvalue as a constant expression. Falls back to __addressof in the presence of an overloaded addressof operator (unary operator&), in which case the call will not be a constant expression.
constexpr nullopt_t nullopt
Tag to disengage optional objects.
Class template that holds the necessary state for Optional values and that has the responsibility for...
Tag type for in-place construction.