29 #ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL
30 #define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1
44 #if __cplusplus >= 201402L
56 namespace std _GLIBCXX_VISIBILITY(default)
58 _GLIBCXX_BEGIN_NAMESPACE_VERSION
60 namespace experimental
62 inline namespace fundamentals_v1
75 #define __cpp_lib_experimental_optional 201411
80 template<
typename _Tp>
99 enum class _Construct { _Token };
102 explicit constexpr
nullopt_t(_Construct) { }
127 __throw_bad_optional_access(
const char*)
128 __attribute__((__noreturn__));
132 __throw_bad_optional_access(const
char* __s)
135 #ifndef __cpp_lib_addressof_constexpr
136 template<
typename _Tp,
typename =
void>
139 template<
typename _Tp>
140 struct _Has_addressof_mem<_Tp,
141 __void_t<decltype( std::declval<const _Tp&>().operator&() )>
145 template<
typename _Tp,
typename =
void>
148 template<
typename _Tp>
149 struct _Has_addressof_free<_Tp,
150 __void_t<decltype( operator&(std::declval<const _Tp&>()) )>
161 template<
typename _Tp>
163 : std::__or_<_Has_addressof_mem<_Tp>, _Has_addressof_free<_Tp>>::type
172 template<
typename _Tp>
181 template<
typename _Tp>
186 #endif // __cpp_lib_addressof_constexpr
200 template<
typename _Tp,
bool _ShouldProvideDestructor =
221 template<
typename... _Args>
223 : _M_payload(std::forward<_Args>(__args)...), _M_engaged(
true) { }
225 template<
typename _Up,
typename... _Args,
233 : _M_payload(__il, std::forward<_Args>(__args)...),
237 _Optional_base(
const _Optional_base& __other)
239 if (__other._M_engaged)
240 this->_M_construct(__other._M_get());
243 _Optional_base(_Optional_base&& __other)
246 if (__other._M_engaged)
247 this->_M_construct(std::move(__other._M_get()));
252 operator=(
const _Optional_base& __other)
254 if (this->_M_engaged && __other._M_engaged)
255 this->_M_get() = __other._M_get();
258 if (__other._M_engaged)
259 this->_M_construct(__other._M_get());
268 operator=(_Optional_base&& __other)
272 if (this->_M_engaged && __other._M_engaged)
273 this->_M_get() = std::move(__other._M_get());
276 if (__other._M_engaged)
277 this->_M_construct(std::move(__other._M_get()));
287 if (this->_M_engaged)
288 this->_M_payload.~_Stored_type();
294 constexpr
bool _M_is_engaged()
const noexcept
295 {
return this->_M_engaged; }
300 {
return _M_payload; }
304 {
return _M_payload; }
308 template<
typename... _Args>
310 _M_construct(_Args&&... __args)
314 _Stored_type(std::forward<_Args>(__args)...);
315 this->_M_engaged =
true;
321 this->_M_engaged =
false;
322 this->_M_payload.~_Stored_type();
329 if (this->_M_engaged)
334 struct _Empty_byte { };
336 _Empty_byte _M_empty;
337 _Stored_type _M_payload;
339 bool _M_engaged =
false;
344 template<
typename _Tp>
357 template<
typename... _Args>
359 : _M_payload(std::forward<_Args>(__args)...), _M_engaged(
true) { }
361 template<
typename _Up,
typename... _Args,
369 : _M_payload(__il, std::forward<_Args>(__args)...),
372 _Optional_base(
const _Optional_base& __other)
374 if (__other._M_engaged)
375 this->_M_construct(__other._M_get());
378 _Optional_base(_Optional_base&& __other)
381 if (__other._M_engaged)
382 this->_M_construct(std::move(__other._M_get()));
386 operator=(
const _Optional_base& __other)
388 if (this->_M_engaged && __other._M_engaged)
389 this->_M_get() = __other._M_get();
392 if (__other._M_engaged)
393 this->_M_construct(__other._M_get());
401 operator=(_Optional_base&& __other)
405 if (this->_M_engaged && __other._M_engaged)
406 this->_M_get() = std::move(__other._M_get());
409 if (__other._M_engaged)
410 this->_M_construct(std::move(__other._M_get()));
421 constexpr
bool _M_is_engaged()
const noexcept
422 {
return this->_M_engaged; }
426 {
return _M_payload; }
430 {
return _M_payload; }
432 template<
typename... _Args>
434 _M_construct(_Args&&... __args)
438 _Stored_type(std::forward<_Args>(__args)...);
439 this->_M_engaged =
true;
445 this->_M_engaged =
false;
446 this->_M_payload.~_Stored_type();
452 if (this->_M_engaged)
457 struct _Empty_byte { };
460 _Empty_byte _M_empty;
461 _Stored_type _M_payload;
463 bool _M_engaged =
false;
466 template<
typename _Tp>
469 template<
typename _Tp,
typename _Up>
470 using __converts_from_optional =
471 __or_<is_constructible<_Tp, const optional<_Up>&>,
480 template<
typename _Tp,
typename _Up>
481 using __assigns_from_optional =
482 __or_<is_assignable<_Tp&, const optional<_Up>&>,
490 template<
typename _Tp>
495 is_copy_constructible<_Tp>::value,
497 __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value,
499 is_move_constructible<_Tp>::value,
501 __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value,
508 "Invalid instantiation of optional<T>");
514 using value_type = _Tp;
521 template <
typename _Up = _Tp,
526 >::value,
bool> =
true>
530 template <
typename _Up = _Tp,
534 __not_<is_convertible<_Up&&, _Tp>>
535 >::value,
bool> =
false>
536 explicit constexpr optional(_Up&& __t)
539 template <
typename _Up,
541 __not_<is_same<_Tp, _Up>>,
544 __not_<__converts_from_optional<_Tp, _Up>>
545 >::value,
bool> =
true>
546 constexpr optional(
const optional<_Up>& __t)
552 template <
typename _Up,
554 __not_<is_same<_Tp, _Up>>,
555 is_constructible<_Tp, const _Up&>,
556 __not_<is_convertible<const _Up&, _Tp>>,
557 __not_<__converts_from_optional<_Tp, _Up>>
558 >::value,
bool> =
false>
559 explicit constexpr optional(
const optional<_Up>& __t)
565 template <
typename _Up,
567 __not_<is_same<_Tp, _Up>>,
568 is_constructible<_Tp, _Up&&>,
569 is_convertible<_Up&&, _Tp>,
570 __not_<__converts_from_optional<_Tp, _Up>>
571 >::value,
bool> =
true>
572 constexpr optional(optional<_Up>&& __t)
575 emplace(std::move(*__t));
578 template <
typename _Up,
580 __not_<is_same<_Tp, _Up>>,
581 is_constructible<_Tp, _Up&&>,
582 __not_<is_convertible<_Up&&, _Tp>>,
583 __not_<__converts_from_optional<_Tp, _Up>>
584 >::value,
bool> =
false>
585 explicit constexpr optional(optional<_Up>&& __t)
588 emplace(std::move(*__t));
599 template<
typename _Up = _Tp>
601 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
602 is_constructible<_Tp, _Up>,
603 __not_<__and_<is_scalar<_Tp>,
604 is_same<_Tp, decay_t<_Up>>>>,
605 is_assignable<_Tp&, _Up>>::value,
609 if (this->_M_is_engaged())
610 this->_M_get() = std::forward<_Up>(__u);
612 this->_M_construct(std::forward<_Up>(__u));
617 template<
typename _Up>
619 __not_<is_same<_Tp, _Up>>,
620 is_constructible<_Tp, const _Up&>,
621 is_assignable<_Tp&, _Up>,
622 __not_<__converts_from_optional<_Tp, _Up>>,
623 __not_<__assigns_from_optional<_Tp, _Up>>
626 operator=(
const optional<_Up>& __u)
630 if (this->_M_is_engaged())
631 this->_M_get() = *__u;
633 this->_M_construct(*__u);
642 template<
typename _Up>
644 __not_<is_same<_Tp, _Up>>,
645 is_constructible<_Tp, _Up>,
646 is_assignable<_Tp&, _Up>,
647 __not_<__converts_from_optional<_Tp, _Up>>,
648 __not_<__assigns_from_optional<_Tp, _Up>>
651 operator=(optional<_Up>&& __u)
655 if (this->_M_is_engaged())
656 this->_M_get() = std::move(*__u);
658 this->_M_construct(std::move(*__u));
668 template<
typename... _Args>
669 enable_if_t<is_constructible<_Tp, _Args&&...>::value>
670 emplace(_Args&&... __args)
673 this->_M_construct(std::forward<_Args>(__args)...);
676 template<
typename _Up,
typename... _Args>
677 enable_if_t<is_constructible<_Tp, initializer_list<_Up>&,
679 emplace(initializer_list<_Up> __il, _Args&&... __args)
682 this->_M_construct(__il, std::forward<_Args>(__args)...);
689 swap(optional& __other)
690 noexcept(is_nothrow_move_constructible<_Tp>()
691 && __is_nothrow_swappable<_Tp>::value)
695 if (this->_M_is_engaged() && __other._M_is_engaged())
696 swap(this->_M_get(), __other._M_get());
697 else if (this->_M_is_engaged())
699 __other._M_construct(std::move(this->_M_get()));
702 else if (__other._M_is_engaged())
704 this->_M_construct(std::move(__other._M_get()));
705 __other._M_destruct();
713 #ifndef __cpp_lib_addressof_constexpr
726 {
return this->_M_get(); }
730 {
return this->_M_get(); }
734 {
return std::move(this->_M_get()); }
736 constexpr
const _Tp&&
738 {
return std::move(this->_M_get()); }
740 constexpr
explicit operator bool() const
noexcept
741 {
return this->_M_is_engaged(); }
746 return this->_M_is_engaged()
748 : (__throw_bad_optional_access(
"Attempt to access value of a "
749 "disengaged optional object"),
756 return this->_M_is_engaged()
758 : (__throw_bad_optional_access(
"Attempt to access value of a "
759 "disengaged optional object"),
766 return this->_M_is_engaged()
767 ? std::move(this->_M_get())
768 : (__throw_bad_optional_access(
"Attempt to access value of a "
769 "disengaged optional object"),
770 std::move(this->_M_get()));
773 constexpr
const _Tp&&
776 return this->_M_is_engaged()
777 ? std::move(this->_M_get())
778 : (__throw_bad_optional_access(
"Attempt to access value of a "
779 "disengaged optional object"),
780 std::move(this->_M_get()));
783 template<
typename _Up>
785 value_or(_Up&& __u) const&
787 static_assert(__and_<is_copy_constructible<_Tp>,
788 is_convertible<_Up&&, _Tp>>(),
789 "Cannot return value");
791 return this->_M_is_engaged()
793 : static_cast<_Tp>(std::
forward<_Up>(__u));
796 template<
typename _Up>
798 value_or(_Up&& __u) &&
800 static_assert(__and_<is_move_constructible<_Tp>,
801 is_convertible<_Up&&, _Tp>>(),
802 "Cannot return value" );
804 return this->_M_is_engaged()
805 ? std::move(this->_M_get())
806 : static_cast<_Tp>(std::
forward<_Up>(__u));
811 template<
typename _Tp>
813 operator==(
const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
815 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
816 && (!__lhs || *__lhs == *__rhs);
819 template<
typename _Tp>
821 operator!=(
const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
822 {
return !(__lhs == __rhs); }
824 template<
typename _Tp>
826 operator<(const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
828 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
831 template<
typename _Tp>
833 operator>(
const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
834 {
return __rhs < __lhs; }
836 template<
typename _Tp>
838 operator<=(const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
839 {
return !(__rhs < __lhs); }
841 template<
typename _Tp>
843 operator>=(
const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
844 {
return !(__lhs < __rhs); }
847 template<
typename _Tp>
849 operator==(
const optional<_Tp>& __lhs, nullopt_t)
noexcept
852 template<
typename _Tp>
854 operator==(nullopt_t,
const optional<_Tp>& __rhs)
noexcept
857 template<
typename _Tp>
859 operator!=(
const optional<_Tp>& __lhs, nullopt_t)
noexcept
860 {
return static_cast<bool>(__lhs); }
862 template<
typename _Tp>
864 operator!=(nullopt_t,
const optional<_Tp>& __rhs)
noexcept
865 {
return static_cast<bool>(__rhs); }
867 template<
typename _Tp>
869 operator<(const optional<_Tp>& , nullopt_t)
noexcept
872 template<
typename _Tp>
874 operator<(nullopt_t, const optional<_Tp>& __rhs)
noexcept
875 {
return static_cast<bool>(__rhs); }
877 template<
typename _Tp>
879 operator>(
const optional<_Tp>& __lhs, nullopt_t)
noexcept
880 {
return static_cast<bool>(__lhs); }
882 template<
typename _Tp>
884 operator>(nullopt_t,
const optional<_Tp>& )
noexcept
887 template<
typename _Tp>
889 operator<=(const optional<_Tp>& __lhs, nullopt_t)
noexcept
892 template<
typename _Tp>
894 operator<=(nullopt_t, const optional<_Tp>& )
noexcept
897 template<
typename _Tp>
899 operator>=(
const optional<_Tp>& , nullopt_t)
noexcept
902 template<
typename _Tp>
904 operator>=(nullopt_t,
const optional<_Tp>& __rhs)
noexcept
908 template<
typename _Tp>
910 operator==(
const optional<_Tp>& __lhs,
const _Tp& __rhs)
911 {
return __lhs && *__lhs == __rhs; }
913 template<
typename _Tp>
915 operator==(
const _Tp& __lhs,
const optional<_Tp>& __rhs)
916 {
return __rhs && __lhs == *__rhs; }
918 template<
typename _Tp>
920 operator!=(
const optional<_Tp>& __lhs, _Tp
const& __rhs)
921 {
return !__lhs || !(*__lhs == __rhs); }
923 template<
typename _Tp>
925 operator!=(
const _Tp& __lhs,
const optional<_Tp>& __rhs)
926 {
return !__rhs || !(__lhs == *__rhs); }
928 template<
typename _Tp>
930 operator<(const optional<_Tp>& __lhs,
const _Tp& __rhs)
931 {
return !__lhs || *__lhs < __rhs; }
933 template<
typename _Tp>
935 operator<(const _Tp& __lhs, const optional<_Tp>& __rhs)
936 {
return __rhs && __lhs < *__rhs; }
938 template<
typename _Tp>
940 operator>(
const optional<_Tp>& __lhs,
const _Tp& __rhs)
941 {
return __lhs && __rhs < *__lhs; }
943 template<
typename _Tp>
945 operator>(
const _Tp& __lhs,
const optional<_Tp>& __rhs)
946 {
return !__rhs || *__rhs < __lhs; }
948 template<
typename _Tp>
950 operator<=(const optional<_Tp>& __lhs,
const _Tp& __rhs)
951 {
return !__lhs || !(__rhs < *__lhs); }
953 template<
typename _Tp>
955 operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs)
956 {
return __rhs && !(*__rhs < __lhs); }
958 template<
typename _Tp>
960 operator>=(
const optional<_Tp>& __lhs,
const _Tp& __rhs)
961 {
return __lhs && !(*__lhs < __rhs); }
963 template<
typename _Tp>
965 operator>=(
const _Tp& __lhs,
const optional<_Tp>& __rhs)
966 {
return !__rhs || !(__lhs < *__rhs); }
969 template<
typename _Tp>
971 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
973 { __lhs.swap(__rhs); }
975 template<
typename _Tp>
976 constexpr optional<decay_t<_Tp>>
977 make_optional(_Tp&& __t)
978 {
return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
985 template<
typename _Tp>
986 struct hash<experimental::optional<_Tp>>
988 using result_type = size_t;
989 using argument_type = experimental::optional<_Tp>;
992 operator()(
const experimental::optional<_Tp>& __t)
const
997 constexpr
size_t __magic_disengaged_hash =
static_cast<size_t>(-3333);
998 return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash;
1002 _GLIBCXX_END_NAMESPACE_VERSION
1007 #endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL
One of two subclasses of exception.
is_nothrow_move_constructible
Exception class thrown when a disengaged optional object is dereferenced.
constexpr nullopt_t nullopt
Tag to disengage optional objects.
Tag type to disengage optional objects.
Trait that detects the presence of an overloaded unary operator&.
enable_if< ::__array_traits< _Tp, _Nm >::_Is_swappable::value >::type noexcept(noexcept(__one.swap(__two)))
swap
is_nothrow_move_assignable
Class template for optional values.
Tag type for in-place construction.
typename remove_const< _Tp >::type remove_const_t
Alias template for remove_const.
A mixin helper to conditionally enable or disable the copy/move special members.
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
logic_error(const string &__arg) _GLIBCXX_TXN_SAFE
typename enable_if< _Cond, _Tp >::type enable_if_t
Alias template for enable_if.
typename decay< _Tp >::type decay_t
Alias template for decay.
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
constexpr in_place_t in_place
Tag for in-place construction.
is_trivially_destructible
Class template that holds the necessary state for Optional values and that has the responsibility for...
typename remove_cv< _Tp >::type remove_cv_t
Alias template for remove_cv.
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.