30#ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL
31#define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1
35#if __cplusplus >= 201402L
47namespace std _GLIBCXX_VISIBILITY(default)
49_GLIBCXX_BEGIN_NAMESPACE_VERSION
53inline 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,
163 initializer_list<_Up>&,
166 constexpr explicit _Optional_base(in_place_t,
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)
180 noexcept(is_nothrow_move_constructible<_Tp>())
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)
205 noexcept(__and_<is_nothrow_move_constructible<_Tp>,
206 is_nothrow_move_assignable<_Tp>>())
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)
247 noexcept(is_nothrow_constructible<_Stored_type, _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,
299 initializer_list<_Up>&,
302 constexpr explicit _Optional_base(in_place_t,
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)
315 noexcept(is_nothrow_move_constructible<_Tp>())
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)
338 noexcept(__and_<is_nothrow_move_constructible<_Tp>,
339 is_nothrow_move_assignable<_Tp>>())
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)
371 noexcept(is_nothrow_constructible<_Stored_type, _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>&>,
405 is_constructible<_Tp, optional<_Up>&>,
406 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>&>,
416 is_assignable<_Tp&, optional<_Up>&>,
417 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,
440 static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>,
nullopt_t>>,
441 __not_<is_same<remove_cv_t<_Tp>,
in_place_t>>,
442 __not_<is_reference<_Tp>>>(),
443 "Invalid instantiation of optional<T>");
446 using _Base = _Optional_base<_Tp>;
449 using value_type = _Tp;
454 constexpr optional() =
default;
456 template <
typename _Up = _Tp,
460 is_convertible<_Up&&, _Tp>
461 >::value,
bool> =
true>
462 constexpr optional(_Up&& __t)
465 template <
typename _Up = _Tp,
469 __not_<is_convertible<_Up&&, _Tp>>
470 >::value,
bool> =
false>
471 explicit constexpr optional(_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>
481 constexpr optional(
const optional<_Up>& __t)
487 template <
typename _Up,
489 __not_<is_same<_Tp, _Up>>,
491 __not_<is_convertible<const _Up&, _Tp>>,
492 __not_<__converts_from_optional<_Tp, _Up>>
493 >::value,
bool> =
false>
494 explicit constexpr optional(
const optional<_Up>& __t)
500 template <
typename _Up,
502 __not_<is_same<_Tp, _Up>>,
504 is_convertible<_Up&&, _Tp>,
505 __not_<__converts_from_optional<_Tp, _Up>>
506 >::value,
bool> =
true>
507 constexpr optional(optional<_Up>&& __t)
513 template <
typename _Up,
515 __not_<is_same<_Tp, _Up>>,
517 __not_<is_convertible<_Up&&, _Tp>>,
518 __not_<__converts_from_optional<_Tp, _Up>>
519 >::value,
bool> =
false>
520 explicit constexpr optional(optional<_Up>&& __t)
534 template<
typename _Up = _Tp>
538 __not_<__and_<is_scalar<_Tp>,
544 if (this->_M_is_engaged())
552 template<
typename _Up>
554 __not_<is_same<_Tp, _Up>>,
557 __not_<__converts_from_optional<_Tp, _Up>>,
558 __not_<__assigns_from_optional<_Tp, _Up>>
561 operator=(
const optional<_Up>& __u)
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>>,
582 __not_<__converts_from_optional<_Tp, _Up>>,
583 __not_<__assigns_from_optional<_Tp, _Up>>
586 operator=(optional<_Up>&& __u)
590 if (this->_M_is_engaged())
603 template<
typename... _Args>
605 emplace(_Args&&... __args)
611 template<
typename _Up,
typename... _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&
712 static_assert(__and_<is_copy_constructible<_Tp>,
713 is_convertible<_Up&&, _Tp>>(),
714 "Cannot return value");
716 if (this->_M_is_engaged())
717 return this->_M_get();
722 template<
typename _Up>
724 value_or(_Up&& __u) &&
726 static_assert(__and_<is_move_constructible<_Tp>,
727 is_convertible<_Up&&, _Tp>>(),
728 "Cannot return value" );
730 if (this->_M_is_engaged())
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>
762 operator>(
const optional<_Tp>& __lhs,
const optional<_Tp>& __rhs)
763 {
return __rhs < __lhs; }
765 template<
typename _Tp>
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>
801 template<
typename _Tp>
804 {
return static_cast<bool>(__rhs); }
806 template<
typename _Tp>
809 {
return static_cast<bool>(__lhs); }
811 template<
typename _Tp>
816 template<
typename _Tp>
821 template<
typename _Tp>
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>
860 {
return !__lhs || *__lhs < __rhs; }
862 template<
typename _Tp>
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>
880 {
return !__lhs || !(__rhs < *__lhs); }
882 template<
typename _Tp>
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>
920 using result_type = size_t;
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
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 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.
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
void swap(any &__x, any &__y) noexcept
Exchange the states of two any objects.
constexpr nullopt_t nullopt
Tag to disengage optional objects.
constexpr in_place_t in_place
Tag for in-place construction.
ISO C++ entities toplevel namespace is std.
Namespace for features defined in ISO Technical Specifications.
logic_error(const string &__arg)
Primary class template hash.
is_nothrow_move_constructible
is_trivially_destructible
Class template for optional values.
Tag type for in-place construction.
Tag type to disengage optional objects.
Exception class thrown when a disengaged optional object is dereferenced.