30 #ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL 31 #define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1 35 #if __cplusplus >= 201402L 47 namespace std _GLIBCXX_VISIBILITY(default)
49 _GLIBCXX_BEGIN_NAMESPACE_VERSION
51 namespace experimental
53 inline namespace fundamentals_v1
66 #define __cpp_lib_experimental_optional 201411 71 template<
typename _Tp>
90 enum class _Construct { _Token };
93 explicit constexpr
nullopt_t(_Construct) { }
120 [[noreturn]]
inline void 121 __throw_bad_optional_access(
const char* __s)
136 template<
typename _Tp,
bool _ShouldProvideDestructor =
144 using _Stored_type = remove_const_t<_Tp>;
150 constexpr _Optional_base() noexcept
153 constexpr _Optional_base(
nullopt_t) noexcept
154 : _Optional_base{} { }
157 template<
typename... _Args>
158 constexpr
explicit _Optional_base(
in_place_t, _Args&&... __args)
159 : _M_payload(std::forward<_Args>(__args)...), _M_engaged(
true) { }
161 template<
typename _Up,
typename... _Args,
167 initializer_list<_Up> __il,
169 : _M_payload(__il, std::forward<_Args>(__args)...),
173 _Optional_base(
const _Optional_base& __other)
175 if (__other._M_engaged)
176 this->_M_construct(__other._M_get());
179 _Optional_base(_Optional_base&& __other)
182 if (__other._M_engaged)
183 this->_M_construct(
std::move(__other._M_get()));
188 operator=(
const _Optional_base& __other)
190 if (this->_M_engaged && __other._M_engaged)
191 this->_M_get() = __other._M_get();
194 if (__other._M_engaged)
195 this->_M_construct(__other._M_get());
204 operator=(_Optional_base&& __other)
208 if (this->_M_engaged && __other._M_engaged)
209 this->_M_get() =
std::move(__other._M_get());
212 if (__other._M_engaged)
213 this->_M_construct(
std::move(__other._M_get()));
223 if (this->_M_engaged)
224 this->_M_payload.~_Stored_type();
230 constexpr
bool _M_is_engaged()
const noexcept
231 {
return this->_M_engaged; }
236 {
return _M_payload; }
239 _M_get()
const noexcept
240 {
return _M_payload; }
244 template<
typename... _Args>
246 _M_construct(_Args&&... __args)
250 _Stored_type(std::forward<_Args>(__args)...);
251 this->_M_engaged =
true;
257 this->_M_engaged =
false;
258 this->_M_payload.~_Stored_type();
265 if (this->_M_engaged)
270 struct _Empty_byte { };
272 _Empty_byte _M_empty;
273 _Stored_type _M_payload;
275 bool _M_engaged =
false;
280 template<
typename _Tp>
281 class _Optional_base<_Tp, false>
284 using _Stored_type = remove_const_t<_Tp>;
287 constexpr _Optional_base() noexcept
290 constexpr _Optional_base(
nullopt_t) noexcept
291 : _Optional_base{} { }
293 template<
typename... _Args>
294 constexpr
explicit _Optional_base(
in_place_t, _Args&&... __args)
295 : _M_payload(std::forward<_Args>(__args)...), _M_engaged(
true) { }
297 template<
typename _Up,
typename... _Args,
303 initializer_list<_Up> __il,
305 : _M_payload(__il, std::forward<_Args>(__args)...),
308 _Optional_base(
const _Optional_base& __other)
310 if (__other._M_engaged)
311 this->_M_construct(__other._M_get());
314 _Optional_base(_Optional_base&& __other)
317 if (__other._M_engaged)
318 this->_M_construct(
std::move(__other._M_get()));
322 operator=(
const _Optional_base& __other)
324 if (this->_M_engaged && __other._M_engaged)
325 this->_M_get() = __other._M_get();
328 if (__other._M_engaged)
329 this->_M_construct(__other._M_get());
337 operator=(_Optional_base&& __other)
341 if (this->_M_engaged && __other._M_engaged)
342 this->_M_get() =
std::move(__other._M_get());
345 if (__other._M_engaged)
346 this->_M_construct(
std::move(__other._M_get()));
357 constexpr
bool _M_is_engaged()
const noexcept
358 {
return this->_M_engaged; }
362 {
return _M_payload; }
365 _M_get()
const noexcept
366 {
return _M_payload; }
368 template<
typename... _Args>
370 _M_construct(_Args&&... __args)
374 _Stored_type(std::forward<_Args>(__args)...);
375 this->_M_engaged =
true;
381 this->_M_engaged =
false;
382 this->_M_payload.~_Stored_type();
388 if (this->_M_engaged)
393 struct _Empty_byte { };
396 _Empty_byte _M_empty;
397 _Stored_type _M_payload;
399 bool _M_engaged =
false;
402 template<
typename _Tp,
typename _Up>
403 using __converts_from_optional =
404 __or_<is_constructible<_Tp, const optional<_Up>&>,
407 is_constructible<_Tp, optional<_Up>&&>,
408 is_convertible<const optional<_Up>&, _Tp>,
409 is_convertible<optional<_Up>&, _Tp>,
410 is_convertible<const optional<_Up>&&, _Tp>,
411 is_convertible<optional<_Up>&&, _Tp>>;
413 template<
typename _Tp,
typename _Up>
414 using __assigns_from_optional =
415 __or_<is_assignable<_Tp&, const optional<_Up>&>,
418 is_assignable<_Tp&, optional<_Up>&&>>;
425 template<
typename _Tp>
427 :
private _Optional_base<_Tp>,
428 private _Enable_copy_move<
430 is_copy_constructible<_Tp>::value,
432 __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value,
434 is_move_constructible<_Tp>::value,
436 __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value,
443 "Invalid instantiation of optional<T>");
446 using _Base = _Optional_base<_Tp>;
449 using value_type = _Tp;
456 template <
typename _Up = _Tp,
460 is_convertible<_Up&&, _Tp>
461 >::value,
bool> =
true>
463 : _Base(in_place, std::forward<_Up>(__t)) { }
465 template <
typename _Up = _Tp,
467 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
468 is_constructible<_Tp, _Up&&>,
469 __not_<is_convertible<_Up&&, _Tp>>
470 >::value,
bool> =
false>
471 explicit constexpr optional(_Up&& __t)
472 : _Base(in_place, std::forward<_Up>(__t)) { }
474 template <
typename _Up,
476 __not_<is_same<_Tp, _Up>>,
478 is_convertible<const _Up&, _Tp>,
479 __not_<__converts_from_optional<_Tp, _Up>>
480 >::value,
bool> =
true>
487 template <
typename _Up,
489 __not_<is_same<_Tp, _Up>>,
490 is_constructible<_Tp, const _Up&>,
491 __not_<is_convertible<const _Up&, _Tp>>,
492 __not_<__converts_from_optional<_Tp, _Up>>
493 >::value,
bool> =
false>
500 template <
typename _Up,
502 __not_<is_same<_Tp, _Up>>,
503 is_constructible<_Tp, _Up&&>,
504 is_convertible<_Up&&, _Tp>,
505 __not_<__converts_from_optional<_Tp, _Up>>
506 >::value,
bool> =
true>
513 template <
typename _Up,
515 __not_<is_same<_Tp, _Up>>,
516 is_constructible<_Tp, _Up&&>,
517 __not_<is_convertible<_Up&&, _Tp>>,
518 __not_<__converts_from_optional<_Tp, _Up>>
519 >::value,
bool> =
false>
534 template<
typename _Up = _Tp>
536 __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
538 __not_<__and_<is_scalar<_Tp>,
544 if (this->_M_is_engaged())
545 this->_M_get() = std::forward<_Up>(__u);
547 this->_M_construct(std::forward<_Up>(__u));
552 template<
typename _Up>
554 __not_<is_same<_Tp, _Up>>,
555 is_constructible<_Tp, const _Up&>,
557 __not_<__converts_from_optional<_Tp, _Up>>,
558 __not_<__assigns_from_optional<_Tp, _Up>>
565 if (this->_M_is_engaged())
566 this->_M_get() = *__u;
568 this->_M_construct(*__u);
577 template<
typename _Up>
579 __not_<is_same<_Tp, _Up>>,
580 is_constructible<_Tp, _Up>,
581 is_assignable<_Tp&, _Up>,
582 __not_<__converts_from_optional<_Tp, _Up>>,
583 __not_<__assigns_from_optional<_Tp, _Up>>
590 if (this->_M_is_engaged())
603 template<
typename... _Args>
605 emplace(_Args&&... __args)
608 this->_M_construct(std::forward<_Args>(__args)...);
611 template<
typename _Up,
typename... _Args>
617 this->_M_construct(__il, std::forward<_Args>(__args)...);
624 swap(optional& __other)
626 && __is_nothrow_swappable<_Tp>::value)
630 if (this->_M_is_engaged() && __other._M_is_engaged())
631 swap(this->_M_get(), __other._M_get());
632 else if (this->_M_is_engaged())
634 __other._M_construct(
std::move(this->_M_get()));
637 else if (__other._M_is_engaged())
639 this->_M_construct(
std::move(__other._M_get()));
640 __other._M_destruct();
655 {
return this->_M_get(); }
659 {
return this->_M_get(); }
665 constexpr
const _Tp&&
669 constexpr
explicit operator bool()
const noexcept
670 {
return this->_M_is_engaged(); }
675 if (this->_M_is_engaged())
676 return this->_M_get();
677 __throw_bad_optional_access(
"Attempt to access value of a " 678 "disengaged optional object");
684 if (this->_M_is_engaged())
685 return this->_M_get();
686 __throw_bad_optional_access(
"Attempt to access value of a " 687 "disengaged optional object");
693 if (this->_M_is_engaged())
695 __throw_bad_optional_access(
"Attempt to access value of a " 696 "disengaged optional object");
699 constexpr
const _Tp&&
702 if (this->_M_is_engaged())
704 __throw_bad_optional_access(
"Attempt to access value of a " 705 "disengaged optional object");
708 template<
typename _Up>
710 value_or(_Up&& __u)
const&
713 is_convertible<_Up&&, _Tp>>(),
714 "Cannot return value");
716 if (this->_M_is_engaged())
717 return this->_M_get();
719 return static_cast<_Tp
>(std::forward<_Up>(__u));
722 template<
typename _Up>
724 value_or(_Up&& __u) &&
727 is_convertible<_Up&&, _Tp>>(),
728 "Cannot return value" );
730 if (this->_M_is_engaged())
733 return static_cast<_Tp
>(std::forward<_Up>(__u));
740 template<
typename _Tp>
744 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
745 && (!__lhs || *__lhs == *__rhs);
748 template<
typename _Tp>
751 {
return !(__lhs == __rhs); }
753 template<
typename _Tp>
755 operator<(const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
757 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
760 template<
typename _Tp>
763 {
return __rhs < __lhs; }
765 template<
typename _Tp>
767 operator<=(const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
768 {
return !(__rhs < __lhs); }
770 template<
typename _Tp>
773 {
return !(__lhs < __rhs); }
776 template<
typename _Tp>
781 template<
typename _Tp>
786 template<
typename _Tp>
789 {
return static_cast<bool>(__lhs); }
791 template<
typename _Tp>
794 {
return static_cast<bool>(__rhs); }
796 template<
typename _Tp>
798 operator<(const optional<_Tp>& ,
nullopt_t) noexcept
801 template<
typename _Tp>
803 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
804 {
return static_cast<bool>(__rhs); }
806 template<
typename _Tp>
809 {
return static_cast<bool>(__lhs); }
811 template<
typename _Tp>
816 template<
typename _Tp>
818 operator<=(const optional<_Tp>& __lhs,
nullopt_t) noexcept
821 template<
typename _Tp>
823 operator<=(nullopt_t, const optional<_Tp>& ) noexcept
826 template<
typename _Tp>
831 template<
typename _Tp>
837 template<
typename _Tp>
840 {
return __lhs && *__lhs == __rhs; }
842 template<
typename _Tp>
845 {
return __rhs && __lhs == *__rhs; }
847 template<
typename _Tp>
850 {
return !__lhs || !(*__lhs == __rhs); }
852 template<
typename _Tp>
855 {
return !__rhs || !(__lhs == *__rhs); }
857 template<
typename _Tp>
859 operator<(const optional<_Tp>& __lhs,
const _Tp& __rhs)
860 {
return !__lhs || *__lhs < __rhs; }
862 template<
typename _Tp>
864 operator<(const _Tp& __lhs, const optional<_Tp>& __rhs)
865 {
return __rhs && __lhs < *__rhs; }
867 template<
typename _Tp>
870 {
return __lhs && __rhs < *__lhs; }
872 template<
typename _Tp>
875 {
return !__rhs || *__rhs < __lhs; }
877 template<
typename _Tp>
879 operator<=(const optional<_Tp>& __lhs,
const _Tp& __rhs)
880 {
return !__lhs || !(__rhs < *__lhs); }
882 template<
typename _Tp>
884 operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs)
885 {
return __rhs && !(*__rhs < __lhs); }
887 template<
typename _Tp>
890 {
return __lhs && !(*__lhs < __rhs); }
892 template<
typename _Tp>
895 {
return !__rhs || !(__lhs < *__rhs); }
898 template<
typename _Tp>
901 noexcept(noexcept(__lhs.swap(__rhs)))
902 { __lhs.swap(__rhs); }
904 template<
typename _Tp>
906 make_optional(_Tp&& __t)
917 template<
typename _Tp>
918 struct hash<experimental::optional<_Tp>>
920 using result_type = size_t;
921 using argument_type = experimental::optional<_Tp>;
924 operator()(
const experimental::optional<_Tp>& __t)
const 929 constexpr
size_t __magic_disengaged_hash =
static_cast<size_t>(-3333);
930 return __t ?
hash<_Tp> {}(*__t) : __magic_disengaged_hash;
934 _GLIBCXX_END_NAMESPACE_VERSION
939 #endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL typename enable_if< _Cond, _Tp >::type enable_if_t
Alias template for enable_if.
Exception class thrown when a disengaged optional object is dereferenced.
Class template for optional values.
typename decay< _Tp >::type decay_t
Alias template for decay.
Tag type to disengage optional objects.
ISO C++ entities toplevel namespace is std.
One of two subclasses of exception.
Tag type for in-place construction.
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
is_trivially_destructible
Primary class template hash.
constexpr complex< _Tp > operator*(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x times y.
is_nothrow_move_assignable
is_nothrow_move_constructible
constexpr nullopt_t nullopt
Tag to disengage optional objects.