Created
August 15, 2016 10:14
-
-
Save EricWF/a43e98641c3270b411a9358601bc2f0d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/include/optional b/include/optional | |
| index d60f375..cfccc42 100644 | |
| --- a/include/optional | |
| +++ b/include/optional | |
| @@ -1,1144 +1,1237 @@ | |
| // -*- C++ -*- | |
| //===-------------------------- optional ----------------------------------===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is dual licensed under the MIT and the University of Illinois Open | |
| // Source Licenses. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef _LIBCPP_OPTIONAL | |
| #define _LIBCPP_OPTIONAL | |
| /* | |
| optional synopsis | |
| // C++1z | |
| namespace std { | |
| // 20.6.3, optional for object types | |
| template <class T> class optional; | |
| // 20.6.4, no-value state indicator | |
| struct nullopt_t{see below }; | |
| constexpr nullopt_t nullopt(unspecified ); | |
| // 20.6.5, class bad_optional_access | |
| class bad_optional_access; | |
| // 20.6.6, relational operators | |
| template <class T> | |
| constexpr bool operator==(const optional<T>&, const optional<T>&); | |
| template <class T> | |
| constexpr bool operator!=(const optional<T>&, const optional<T>&); | |
| template <class T> | |
| constexpr bool operator<(const optional<T>&, const optional<T>&); | |
| template <class T> | |
| constexpr bool operator>(const optional<T>&, const optional<T>&); | |
| template <class T> | |
| constexpr bool operator<=(const optional<T>&, const optional<T>&); | |
| template <class T> | |
| constexpr bool operator>=(const optional<T>&, const optional<T>&); | |
| template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; | |
| template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; | |
| template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; | |
| template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; | |
| template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; | |
| template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; | |
| template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; | |
| template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; | |
| template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept; | |
| template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept; | |
| template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; | |
| template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; | |
| // 20.6.8, comparison with T | |
| template <class T> constexpr bool operator==(const optional<T>&, const T&); | |
| template <class T> constexpr bool operator==(const T&, const optional<T>&); | |
| template <class T> constexpr bool operator!=(const optional<T>&, const T&); | |
| template <class T> constexpr bool operator!=(const T&, const optional<T>&); | |
| template <class T> constexpr bool operator<(const optional<T>&, const T&); | |
| template <class T> constexpr bool operator<(const T&, const optional<T>&); | |
| template <class T> constexpr bool operator<=(const optional<T>&, const T&); | |
| template <class T> constexpr bool operator<=(const T&, const optional<T>&); | |
| template <class T> constexpr bool operator>(const optional<T>&, const T&); | |
| template <class T> constexpr bool operator>(const T&, const optional<T>&); | |
| template <class T> constexpr bool operator>=(const optional<T>&, const T&); | |
| template <class T> constexpr bool operator>=(const T&, const optional<T>&); | |
| // 20.6.9, specialized algorithms | |
| template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below ); | |
| template <class T> constexpr optional<see below > make_optional(T&&); | |
| template <class T, class... Args> | |
| constexpr optional<T> make_optional(Args&&... args); | |
| template <class T, class U, class... Args> | |
| constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); | |
| // 20.6.10, hash support | |
| template <class T> struct hash; | |
| template <class T> struct hash<optional<T>>; | |
| template <class T> class optional { | |
| public: | |
| using value_type = T; | |
| // 20.6.3.1, constructors | |
| constexpr optional() noexcept; | |
| constexpr optional(nullopt_t) noexcept; | |
| optional(const optional &); | |
| optional(optional &&) noexcept(see below ); | |
| template <class... Args> constexpr explicit optional(in_place_t, Args &&...); | |
| template <class U, class... Args> | |
| constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...); | |
| template <class U = T> | |
| constexpr EXPLICIT optional(U &&); | |
| template <class U> | |
| constexpr EXPLICIT optional(const optional<U> &); | |
| template <class U> | |
| constexpr EXPLICIT optional(optional<U> &&); | |
| // 20.6.3.2, destructor | |
| ~optional(); | |
| // 20.6.3.3, assignment | |
| optional &operator=(nullopt_t) noexcept; | |
| optional &operator=(const optional &); | |
| optional &operator=(optional &&) noexcept(see below ); | |
| template <class U = T> optional &operator=(U &&); | |
| template <class U> optional &operator=(const optional<U> &); | |
| template <class U> optional &operator=(optional<U> &&); | |
| template <class... Args> void emplace(Args &&...); | |
| template <class U, class... Args> | |
| void emplace(initializer_list<U>, Args &&...); | |
| // 20.6.3.4, swap | |
| void swap(optional &) noexcept(see below ); | |
| // 20.6.3.5, observers | |
| constexpr T const *operator->() const; | |
| constexpr T *operator->(); | |
| constexpr T const &operator*() const &; | |
| constexpr T &operator*() &; | |
| constexpr T &&operator*() &&; | |
| constexpr const T &&operator*() const &&; | |
| constexpr explicit operator bool() const noexcept; | |
| constexpr bool has_value() const noexcept; | |
| constexpr T const &value() const &; | |
| constexpr T &value() &; | |
| constexpr T &&value() &&; | |
| constexpr const T &&value() const &&; | |
| template <class U> constexpr T value_or(U &&) const &; | |
| template <class U> constexpr T value_or(U &&) &&; | |
| // 20.6.3.6, modifiers | |
| void reset() noexcept; | |
| private: | |
| T *val; // exposition only | |
| }; | |
| } // namespace std | |
| */ | |
| #include <__config> | |
| #include <__debug> | |
| #include <__functional_base> | |
| #include <__undef_min_max> | |
| #include <functional> | |
| #include <initializer_list> | |
| #include <new> | |
| #include <stdexcept> | |
| #include <type_traits> | |
| #include <utility> | |
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | |
| #pragma GCC system_header | |
| #endif | |
| namespace std // purposefully not using versioning namespace | |
| { | |
| class _LIBCPP_EXCEPTION_ABI bad_optional_access | |
| : public logic_error | |
| { | |
| public: | |
| _LIBCPP_INLINE_VISIBILITY | |
| bad_optional_access() : logic_error("Bad optional access") {} | |
| // Get the key function ~bad_optional_access() into the dylib | |
| virtual ~bad_optional_access() _NOEXCEPT; | |
| }; | |
| } // std | |
| #if _LIBCPP_STD_VER > 14 | |
| _LIBCPP_BEGIN_NAMESPACE_STD | |
| struct nullopt_t | |
| { | |
| struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; }; | |
| _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {} | |
| }; | |
| /* inline */ constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}}; | |
| -template <class _Tp, bool = is_trivially_destructible_v<_Tp>> | |
| +template <class _Tp, bool = is_trivially_destructible_v<_Tp>, bool = is_reference<_Tp>::value> | |
| struct __optional_destruct_base; | |
| -template <class _Tp> | |
| -struct __optional_destruct_base<_Tp, false> | |
| +template <class _Tp, bool _IsRef> | |
| +struct __optional_destruct_base<_Tp, false, _IsRef> | |
| { | |
| typedef _Tp value_type; | |
| union | |
| { | |
| char __null_state_; | |
| value_type __val_; | |
| }; | |
| bool __engaged_; | |
| _LIBCPP_INLINE_VISIBILITY | |
| ~__optional_destruct_base() | |
| { | |
| if (__engaged_) | |
| __val_.~value_type(); | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr __optional_destruct_base() noexcept | |
| : __null_state_(), | |
| __engaged_(false) {} | |
| template <class... _Args> | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) | |
| : __val_(_VSTD::forward<_Args>(__args)...), | |
| __engaged_(true) {} | |
| _LIBCPP_INLINE_VISIBILITY | |
| void reset() noexcept | |
| { | |
| if (__engaged_) | |
| { | |
| __val_.~value_type(); | |
| __engaged_ = false; | |
| } | |
| } | |
| }; | |
| template <class _Tp> | |
| -struct __optional_destruct_base<_Tp, true> | |
| +struct __optional_destruct_base<_Tp, true, false> | |
| { | |
| typedef _Tp value_type; | |
| union | |
| { | |
| char __null_state_; | |
| value_type __val_; | |
| }; | |
| bool __engaged_; | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr __optional_destruct_base() noexcept | |
| : __null_state_(), | |
| __engaged_(false) {} | |
| template <class... _Args> | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) | |
| : __val_(_VSTD::forward<_Args>(__args)...), | |
| __engaged_(true) {} | |
| _LIBCPP_INLINE_VISIBILITY | |
| void reset() noexcept | |
| { | |
| if (__engaged_) | |
| { | |
| __engaged_ = false; | |
| } | |
| } | |
| }; | |
| + | |
| template <class _Tp> | |
| +struct __optional_destruct_base<_Tp, true, true> | |
| +{ | |
| + using value_type = _Tp; | |
| + using __raw_type = remove_reference_t<_Tp>; | |
| + __raw_type* __value_; | |
| + | |
| + _LIBCPP_INLINE_VISIBILITY | |
| + constexpr __optional_destruct_base() noexcept | |
| + : __value_(nullptr) {} | |
| + | |
| + template <class _UArg> | |
| + _LIBCPP_INLINE_VISIBILITY | |
| + constexpr explicit __optional_destruct_base(in_place_t, _UArg&& __uarg) | |
| + : __value_(_VSTD::addressof(__uarg)) {} | |
| + | |
| + _LIBCPP_INLINE_VISIBILITY | |
| + void reset() noexcept | |
| + { | |
| + __value_ = nullptr; | |
| + } | |
| +}; | |
| + | |
| +template <class _Tp, bool = is_reference<_Tp>::value> | |
| struct __optional_storage_base : __optional_destruct_base<_Tp> | |
| { | |
| using __base = __optional_destruct_base<_Tp>; | |
| using typename __base::value_type; | |
| using __base::__base; | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr bool has_value() const noexcept | |
| { | |
| return this->__engaged_; | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr value_type& __get() & noexcept | |
| { | |
| return this->__val_; | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr const value_type& __get() const& noexcept | |
| { | |
| return this->__val_; | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr value_type&& __get() && noexcept | |
| { | |
| return _VSTD::move(this->__val_); | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr const value_type&& __get() const&& noexcept | |
| { | |
| return _VSTD::move(this->__val_); | |
| } | |
| template <class... _Args> | |
| _LIBCPP_INLINE_VISIBILITY | |
| void __construct(_Args&&... __args) | |
| { | |
| _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); | |
| ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); | |
| this->__engaged_ = true; | |
| } | |
| template <class _That> | |
| _LIBCPP_INLINE_VISIBILITY | |
| void __construct_from(_That&& __opt) | |
| { | |
| if (__opt.has_value()) | |
| __construct(_VSTD::forward<_That>(__opt).__get()); | |
| } | |
| template <class _That> | |
| _LIBCPP_INLINE_VISIBILITY | |
| void __assign_from(_That&& __opt) | |
| { | |
| if (this->__engaged_ == __opt.has_value()) | |
| { | |
| if (this->__engaged_) | |
| this->__val_ = _VSTD::forward<_That>(__opt).__get(); | |
| } | |
| else | |
| { | |
| if (this->__engaged_) | |
| this->reset(); | |
| else | |
| __construct(_VSTD::forward<_That>(__opt).__get()); | |
| } | |
| } | |
| }; | |
| + | |
| +template <class _Tp> | |
| +struct __optional_storage_base<_Tp, true> : __optional_destruct_base<_Tp> | |
| +{ | |
| + using __base = __optional_destruct_base<_Tp>; | |
| + using typename __base::value_type; | |
| + using __base::__base; | |
| + | |
| + _LIBCPP_INLINE_VISIBILITY | |
| + constexpr bool has_value() const noexcept | |
| + { | |
| + return this->__value_; | |
| + } | |
| + | |
| + _LIBCPP_INLINE_VISIBILITY | |
| + constexpr value_type& __get() & noexcept | |
| + { | |
| + return *this->__value_; | |
| + } | |
| + _LIBCPP_INLINE_VISIBILITY | |
| + constexpr const value_type& __get() const& noexcept | |
| + { | |
| + return *this->__value_; | |
| + } | |
| + _LIBCPP_INLINE_VISIBILITY | |
| + constexpr value_type&& __get() && noexcept | |
| + { | |
| + return _VSTD::move(*this->__value_); | |
| + } | |
| + _LIBCPP_INLINE_VISIBILITY | |
| + constexpr const value_type&& __get() const&& noexcept | |
| + { | |
| + return _VSTD::move(*this->__value_); | |
| + } | |
| + | |
| + template <class _UArg> | |
| + _LIBCPP_INLINE_VISIBILITY | |
| + void __construct(_UArg&& __uarg) | |
| + { | |
| + _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); | |
| + this->__value_ = _VSTD::addressof(__uarg); | |
| + } | |
| + | |
| + template <class _That> | |
| + _LIBCPP_INLINE_VISIBILITY | |
| + void __construct_from(_That&& __opt) | |
| + { | |
| + if (__opt.has_value()) | |
| + __construct(_VSTD::forward<_That>(__opt).__get()); | |
| + } | |
| + | |
| + template <class _That> | |
| + _LIBCPP_INLINE_VISIBILITY | |
| + void __assign_from(_That&& __opt) | |
| + { | |
| + if (has_value() == __opt.has_value()) | |
| + { | |
| + if (this->has_value()) | |
| + *this->__value_ = _VSTD::forward<_That>(__opt).__get(); | |
| + } | |
| + else | |
| + { | |
| + if (this->has_value()) | |
| + this->reset(); | |
| + else | |
| + __construct(_VSTD::forward<_That>(__opt).__get()); | |
| + } | |
| + } | |
| +}; | |
| + | |
| template <class _Tp, bool = is_trivially_copyable_v<_Tp>> | |
| struct __optional_storage; | |
| template <class _Tp> | |
| struct __optional_storage<_Tp, true> : __optional_storage_base<_Tp> | |
| { | |
| using __optional_storage_base<_Tp>::__optional_storage_base; | |
| }; | |
| template <class _Tp> | |
| struct __optional_storage<_Tp, false> : __optional_storage_base<_Tp> | |
| { | |
| using typename __optional_storage_base<_Tp>::value_type; | |
| using __optional_storage_base<_Tp>::__optional_storage_base; | |
| _LIBCPP_INLINE_VISIBILITY | |
| __optional_storage() = default; | |
| _LIBCPP_INLINE_VISIBILITY | |
| __optional_storage(const __optional_storage& __opt) | |
| { | |
| this->__construct_from(__opt); | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| __optional_storage(__optional_storage&& __opt) | |
| noexcept(is_nothrow_move_constructible_v<value_type>) | |
| { | |
| this->__construct_from(_VSTD::move(__opt)); | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| __optional_storage& operator=(const __optional_storage& __opt) | |
| { | |
| this->__assign_from(__opt); | |
| return *this; | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| __optional_storage& operator=(__optional_storage&& __opt) | |
| noexcept(is_nothrow_move_assignable_v<value_type> && | |
| is_nothrow_move_constructible_v<value_type>) | |
| { | |
| this->__assign_from(_VSTD::move(__opt)); | |
| return *this; | |
| } | |
| }; | |
| template <class _Tp, template <class...> class _Template> | |
| constexpr bool _Is_specialization = false; | |
| template <class... _Args, template <class...> class _Template> | |
| constexpr bool _Is_specialization<_Template<_Args...>, _Template> = true; | |
| template <class _Tp> | |
| using __optional_sfinae_ctor_base_t = __sfinae_ctor_base< | |
| is_copy_constructible<_Tp>::value, | |
| is_move_constructible<_Tp>::value | |
| >; | |
| template <class _Tp> | |
| using __optional_sfinae_assign_base_t = __sfinae_assign_base< | |
| (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value), | |
| (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) || | |
| (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value) | |
| >; | |
| template <class _Tp> | |
| class optional | |
| : __optional_storage<_Tp> | |
| , __optional_sfinae_ctor_base_t<_Tp> | |
| , __optional_sfinae_assign_base_t<_Tp> | |
| { | |
| public: | |
| using __base = __optional_storage<_Tp>; | |
| using typename __base::value_type; | |
| + using __raw_type = remove_reference_t<_Tp>; | |
| - static_assert(!is_reference_v<value_type>, | |
| - "Instantiation of optional with a reference type is ill-formed."); | |
| static_assert(!is_same_v<remove_cv_t<value_type>, nullopt_t>, | |
| "Instantiation of optional with a nullopt_t type is ill-formed."); | |
| static_assert(is_reference_v<value_type> || is_object_v<value_type>, | |
| "Instantiation of optional with a non-object type is undefined behavior."); | |
| _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {} | |
| _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default; | |
| _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default; | |
| _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {} | |
| template <class... _Args, | |
| class = enable_if_t | |
| < | |
| is_constructible_v<value_type, _Args...> | |
| > | |
| > | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr explicit optional(in_place_t, _Args&&... __args) | |
| : __base(in_place, _VSTD::forward<_Args>(__args)...) {} | |
| template <class _Up, class... _Args, | |
| class = enable_if_t | |
| < | |
| is_constructible_v<value_type, initializer_list<_Up>&, _Args...> | |
| > | |
| > | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) | |
| : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {} | |
| // LWG2756: conditionally explicit conversion from _Up | |
| template <class _Up> | |
| using _AllowDirectConversion = typename conjunction< | |
| negation<bool_constant<_Is_specialization<decay_t<_Up>, _VSTD::optional>>>, | |
| negation<is_same<_Up, in_place_t>>, | |
| is_constructible<value_type, _Up>>::type; | |
| template <class _Up = value_type, enable_if_t<conjunction_v< | |
| _AllowDirectConversion<_Up>, is_convertible<_Up, value_type>>, int> = 0> | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr optional(_Up&& __v) | |
| : __base(in_place, _VSTD::forward<_Up>(__v)) {} | |
| template <class _Up, enable_if_t<conjunction_v< | |
| _AllowDirectConversion<_Up>, negation<is_convertible<_Up, value_type>>>, int> = 0> | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr explicit optional(_Up&& __v) | |
| : __base(in_place, _VSTD::forward<_Up>(__v)) {} | |
| // LWG2756: conditionally explicit conversion from const optional<_Up>& | |
| template <class _Up, enable_if_t< | |
| is_constructible_v<value_type, const _Up&> && | |
| is_convertible_v<const _Up&, value_type>, int> = 0> | |
| _LIBCPP_INLINE_VISIBILITY | |
| optional(const optional<_Up>& __v) | |
| { | |
| this->__construct_from(__v); | |
| } | |
| template <class _Up, enable_if_t< | |
| is_constructible_v<value_type, const _Up&> && | |
| !is_convertible_v<const _Up&, value_type>, int> = 0> | |
| _LIBCPP_INLINE_VISIBILITY | |
| explicit optional(const optional<_Up>& __v) | |
| { | |
| this->__construct_from(__v); | |
| } | |
| // LWG2756: conditionally explicit conversion from optional<_Up>&& | |
| template <class _Up, enable_if_t< | |
| is_constructible_v<value_type, _Up> && | |
| is_convertible_v<_Up, value_type>, int> = 0> | |
| _LIBCPP_INLINE_VISIBILITY | |
| optional(optional<_Up>&& __v) | |
| { | |
| this->__construct_from(_VSTD::move(__v)); | |
| } | |
| template <class _Up, enable_if_t< | |
| is_constructible_v<value_type, _Up> && | |
| !is_convertible_v<_Up, value_type>, int> = 0> | |
| _LIBCPP_INLINE_VISIBILITY | |
| explicit optional(optional<_Up>&& __v) | |
| { | |
| this->__construct_from(_VSTD::move(__v)); | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| optional& operator=(nullopt_t) noexcept | |
| { | |
| reset(); | |
| return *this; | |
| } | |
| _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default; | |
| _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default; | |
| // LWG2756 | |
| template <class _Up = value_type, | |
| class = enable_if_t | |
| < | |
| !_Is_specialization<_Up, _VSTD::optional> && | |
| is_constructible_v<value_type, _Up> && | |
| is_assignable_v<value_type&, _Up> | |
| > | |
| > | |
| _LIBCPP_INLINE_VISIBILITY | |
| optional& | |
| operator=(_Up&& __v) | |
| { | |
| if (this->has_value()) | |
| this->__get() = _VSTD::forward<_Up>(__v); | |
| else | |
| this->__construct(_VSTD::forward<_Up>(__v)); | |
| return *this; | |
| } | |
| // LWG2756 | |
| template <class _Up, | |
| class = enable_if_t | |
| < | |
| is_constructible_v<value_type, const _Up&> && | |
| is_assignable_v<value_type&, const _Up&> | |
| > | |
| > | |
| _LIBCPP_INLINE_VISIBILITY | |
| optional& | |
| operator=(const optional<_Up>& __v) | |
| { | |
| this->__assign_from(__v); | |
| return *this; | |
| } | |
| // LWG2756 | |
| template <class _Up, | |
| class = enable_if_t | |
| < | |
| is_constructible_v<value_type, _Up> && | |
| is_assignable_v<value_type&, _Up> | |
| > | |
| > | |
| _LIBCPP_INLINE_VISIBILITY | |
| optional& | |
| operator=(optional<_Up>&& __v) | |
| { | |
| this->__assign_from(_VSTD::move(__v)); | |
| return *this; | |
| } | |
| template <class... _Args, | |
| class = enable_if_t | |
| < | |
| is_constructible_v<value_type, _Args...> | |
| > | |
| > | |
| _LIBCPP_INLINE_VISIBILITY | |
| void | |
| emplace(_Args&&... __args) | |
| { | |
| reset(); | |
| this->__construct(_VSTD::forward<_Args>(__args)...); | |
| } | |
| template <class _Up, class... _Args, | |
| class = enable_if_t | |
| < | |
| is_constructible_v<value_type, initializer_list<_Up>&, _Args...> | |
| > | |
| > | |
| _LIBCPP_INLINE_VISIBILITY | |
| void | |
| emplace(initializer_list<_Up> __il, _Args&&... __args) | |
| { | |
| reset(); | |
| this->__construct(__il, _VSTD::forward<_Args>(__args)...); | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| void | |
| swap(optional& __opt) | |
| noexcept(is_nothrow_move_constructible_v<value_type> && | |
| is_nothrow_swappable_v<value_type>) | |
| { | |
| if (this->has_value() == __opt.has_value()) | |
| { | |
| using _VSTD::swap; | |
| if (this->has_value()) | |
| swap(this->__get(), __opt.__get()); | |
| } | |
| else | |
| { | |
| if (this->has_value()) | |
| { | |
| __opt.__construct(_VSTD::move(this->__get())); | |
| reset(); | |
| } | |
| else | |
| { | |
| this->__construct(_VSTD::move(__opt.__get())); | |
| __opt.reset(); | |
| } | |
| } | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr | |
| - value_type const* | |
| + __raw_type const* | |
| operator->() const | |
| { | |
| _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value"); | |
| #if __has_builtin(__builtin_addressof) | |
| return _VSTD::addressof(this->__get()); | |
| #else | |
| return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get()); | |
| #endif | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr | |
| - value_type* | |
| + __raw_type* | |
| operator->() | |
| { | |
| _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value"); | |
| #if __has_builtin(__builtin_addressof) | |
| return _VSTD::addressof(this->__get()); | |
| #else | |
| return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get()); | |
| #endif | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr | |
| const value_type& | |
| operator*() const& | |
| { | |
| _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); | |
| return this->__get(); | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr | |
| value_type& | |
| operator*() & | |
| { | |
| _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); | |
| return this->__get(); | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr | |
| value_type&& | |
| operator*() && | |
| { | |
| _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); | |
| return _VSTD::move(this->__get()); | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr | |
| const value_type&& | |
| operator*() const&& | |
| { | |
| _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); | |
| return _VSTD::move(this->__get()); | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr explicit operator bool() const noexcept { return has_value(); } | |
| using __base::has_value; | |
| using __base::__get; | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr value_type const& value() const& | |
| { | |
| if (!this->has_value()) | |
| __libcpp_throw(bad_optional_access()); | |
| return this->__get(); | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr value_type& value() & | |
| { | |
| if (!this->has_value()) | |
| __libcpp_throw(bad_optional_access()); | |
| return this->__get(); | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr value_type&& value() && | |
| { | |
| if (!this->has_value()) | |
| __libcpp_throw(bad_optional_access()); | |
| return _VSTD::move(this->__get()); | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr value_type const&& value() const&& | |
| { | |
| if (!this->has_value()) | |
| __libcpp_throw(bad_optional_access()); | |
| return _VSTD::move(this->__get()); | |
| } | |
| template <class _Up> | |
| _LIBCPP_INLINE_VISIBILITY | |
| constexpr value_type value_or(_Up&& __v) const& | |
| { | |
| static_assert(is_copy_constructible_v<value_type>, | |
| "optional<T>::value_or: T must be copy constructible"); | |
| static_assert(is_convertible_v<_Up, value_type>, | |
| "optional<T>::value_or: U must be convertible to T"); | |
| return this->has_value() ? this->__get() : | |
| static_cast<value_type>(_VSTD::forward<_Up>(__v)); | |
| } | |
| template <class _Up> | |
| _LIBCPP_INLINE_VISIBILITY | |
| value_type value_or(_Up&& __v) && | |
| { | |
| static_assert(is_move_constructible_v<value_type>, | |
| "optional<T>::value_or: T must be move constructible"); | |
| static_assert(is_convertible_v<_Up, value_type>, | |
| "optional<T>::value_or: U must be convertible to T"); | |
| return this->has_value() ? _VSTD::move(this->__get()) : | |
| static_cast<value_type>(_VSTD::forward<_Up>(__v)); | |
| } | |
| using __base::reset; | |
| private: | |
| template <class _Up> | |
| _LIBCPP_INLINE_VISIBILITY | |
| static _Up* | |
| __operator_arrow(true_type, _Up& __x) | |
| { | |
| return _VSTD::addressof(__x); | |
| } | |
| template <class _Up> | |
| _LIBCPP_INLINE_VISIBILITY | |
| static constexpr _Up* | |
| __operator_arrow(false_type, _Up& __x) | |
| { | |
| return &__x; | |
| } | |
| }; | |
| // Comparisons between optionals | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator==(const optional<_Tp>& __x, const optional<_Tp>& __y) | |
| { | |
| if (static_cast<bool>(__x) != static_cast<bool>(__y)) | |
| return false; | |
| if (!static_cast<bool>(__x)) | |
| return true; | |
| return *__x == *__y; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator!=(const optional<_Tp>& __x, const optional<_Tp>& __y) | |
| { | |
| if (static_cast<bool>(__x) != static_cast<bool>(__y)) | |
| return true; | |
| if (!static_cast<bool>(__x)) | |
| return false; | |
| return *__x != *__y; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator<(const optional<_Tp>& __x, const optional<_Tp>& __y) | |
| { | |
| if (!static_cast<bool>(__y)) | |
| return false; | |
| if (!static_cast<bool>(__x)) | |
| return true; | |
| return *__x < *__y; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator>(const optional<_Tp>& __x, const optional<_Tp>& __y) | |
| { | |
| if (!static_cast<bool>(__x)) | |
| return false; | |
| if (!static_cast<bool>(__y)) | |
| return true; | |
| return *__x > *__y; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator<=(const optional<_Tp>& __x, const optional<_Tp>& __y) | |
| { | |
| if (!static_cast<bool>(__x)) | |
| return true; | |
| if (!static_cast<bool>(__y)) | |
| return false; | |
| return *__x <= *__y; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator>=(const optional<_Tp>& __x, const optional<_Tp>& __y) | |
| { | |
| if (!static_cast<bool>(__y)) | |
| return true; | |
| if (!static_cast<bool>(__x)) | |
| return false; | |
| return *__x >= *__y; | |
| } | |
| // Comparisons with nullopt | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| bool | |
| operator==(const optional<_Tp>& __x, nullopt_t) noexcept | |
| { | |
| return !static_cast<bool>(__x); | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| bool | |
| operator==(nullopt_t, const optional<_Tp>& __x) noexcept | |
| { | |
| return !static_cast<bool>(__x); | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| bool | |
| operator!=(const optional<_Tp>& __x, nullopt_t) noexcept | |
| { | |
| return static_cast<bool>(__x); | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| bool | |
| operator!=(nullopt_t, const optional<_Tp>& __x) noexcept | |
| { | |
| return static_cast<bool>(__x); | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| bool | |
| operator<(const optional<_Tp>&, nullopt_t) noexcept | |
| { | |
| return false; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| bool | |
| operator<(nullopt_t, const optional<_Tp>& __x) noexcept | |
| { | |
| return static_cast<bool>(__x); | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| bool | |
| operator<=(const optional<_Tp>& __x, nullopt_t) noexcept | |
| { | |
| return !static_cast<bool>(__x); | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| bool | |
| operator<=(nullopt_t, const optional<_Tp>& __x) noexcept | |
| { | |
| return true; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| bool | |
| operator>(const optional<_Tp>& __x, nullopt_t) noexcept | |
| { | |
| return static_cast<bool>(__x); | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| bool | |
| operator>(nullopt_t, const optional<_Tp>& __x) noexcept | |
| { | |
| return false; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| bool | |
| operator>=(const optional<_Tp>&, nullopt_t) noexcept | |
| { | |
| return true; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| bool | |
| operator>=(nullopt_t, const optional<_Tp>& __x) noexcept | |
| { | |
| return !static_cast<bool>(__x); | |
| } | |
| // Comparisons with T | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator==(const optional<_Tp>& __x, const _Tp& __v) | |
| { | |
| return static_cast<bool>(__x) ? *__x == __v : false; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator==(const _Tp& __v, const optional<_Tp>& __x) | |
| { | |
| return static_cast<bool>(__x) ? __v == *__x : false; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator!=(const optional<_Tp>& __x, const _Tp& __v) | |
| { | |
| return static_cast<bool>(__x) ? *__x != __v : true; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator!=(const _Tp& __v, const optional<_Tp>& __x) | |
| { | |
| return static_cast<bool>(__x) ? __v != *__x : true; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator<(const optional<_Tp>& __x, const _Tp& __v) | |
| { | |
| return static_cast<bool>(__x) ? *__x < __v : true; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator<(const _Tp& __v, const optional<_Tp>& __x) | |
| { | |
| return static_cast<bool>(__x) ? __v < *__x : false; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator<=(const optional<_Tp>& __x, const _Tp& __v) | |
| { | |
| return static_cast<bool>(__x) ? *__x <= __v : true; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator<=(const _Tp& __v, const optional<_Tp>& __x) | |
| { | |
| return static_cast<bool>(__x) ? __v <= *__x : false; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator>(const optional<_Tp>& __x, const _Tp& __v) | |
| { | |
| return static_cast<bool>(__x) ? *__x > __v : false; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator>(const _Tp& __v, const optional<_Tp>& __x) | |
| { | |
| return static_cast<bool>(__x) ? __v > *__x : true; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator>=(const optional<_Tp>& __x, const _Tp& __v) | |
| { | |
| return static_cast<bool>(__x) ? *__x >= __v : false; | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| enable_if_t< | |
| is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= | |
| _VSTD::declval<const _Tp&>()), bool>, | |
| bool | |
| > | |
| operator>=(const _Tp& __v, const optional<_Tp>& __x) | |
| { | |
| return static_cast<bool>(__x) ? __v >= *__x : true; | |
| } | |
| template <class _Tp> | |
| inline _LIBCPP_INLINE_VISIBILITY | |
| enable_if_t< | |
| is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, | |
| void | |
| > | |
| swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) | |
| { | |
| __x.swap(__y); | |
| } | |
| template <class _Tp> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| optional<decay_t<_Tp>> make_optional(_Tp&& __v) | |
| { | |
| return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v)); | |
| } | |
| template <class _Tp, class... _Args> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| optional<_Tp> make_optional(_Args&&... __args) | |
| { | |
| return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...); | |
| } | |
| template <class _Tp, class _Up, class... _Args> | |
| _LIBCPP_INLINE_VISIBILITY constexpr | |
| optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) | |
| { | |
| return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...); | |
| } | |
| template <class _Tp> | |
| struct _LIBCPP_TYPE_VIS_ONLY hash<optional<_Tp> > | |
| { | |
| typedef optional<_Tp> argument_type; | |
| typedef size_t result_type; | |
| _LIBCPP_INLINE_VISIBILITY | |
| result_type operator()(const argument_type& __opt) const _NOEXCEPT | |
| { | |
| return static_cast<bool>(__opt) ? hash<_Tp>()(*__opt) : 0; | |
| } | |
| }; | |
| _LIBCPP_END_NAMESPACE_STD | |
| #endif // _LIBCPP_STD_VER > 14 | |
| #endif // _LIBCPP_OPTIONAL | |
| diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp | |
| index ddd6af2..e405e5d 100644 | |
| --- a/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp | |
| +++ b/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp | |
| @@ -1,61 +1,89 @@ | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is dual licensed under the MIT and the University of Illinois Open | |
| // Source Licenses. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | |
| // <optional> | |
| // constexpr optional() noexcept; | |
| #include <optional> | |
| #include <type_traits> | |
| #include <cassert> | |
| using std::optional; | |
| template <class Opt> | |
| void | |
| test_constexpr() | |
| { | |
| static_assert(std::is_nothrow_default_constructible<Opt>::value, ""); | |
| constexpr Opt opt; | |
| static_assert(static_cast<bool>(opt) == false, ""); | |
| struct test_constexpr_ctor | |
| : public Opt | |
| { | |
| constexpr test_constexpr_ctor() {} | |
| }; | |
| } | |
| template <class Opt> | |
| void | |
| test() | |
| { | |
| static_assert(std::is_nothrow_default_constructible<Opt>::value, ""); | |
| Opt opt; | |
| assert(static_cast<bool>(opt) == false); | |
| struct test_constexpr_ctor | |
| : public Opt | |
| { | |
| constexpr test_constexpr_ctor() {} | |
| }; | |
| } | |
| struct X | |
| { | |
| X(); | |
| }; | |
| int main() | |
| { | |
| test_constexpr<optional<int>>(); | |
| test_constexpr<optional<int*>>(); | |
| test<optional<X>>(); | |
| +#ifdef _LIBCPP_VERSION | |
| + { | |
| + optional<int&> opt; | |
| + assert(!opt); | |
| + int x = 42; | |
| + opt = x; | |
| + assert(opt); | |
| + assert(&opt.value() == &x); | |
| + int y = 101; | |
| + opt = y; | |
| + assert(opt); | |
| + assert(&opt.value() == &x); | |
| + assert(*opt == 101); | |
| + } | |
| + { | |
| + optional<int&&> opt; | |
| + assert(!opt); | |
| + int x = 42; | |
| + opt = std::move(x); | |
| + assert(opt); | |
| + assert(&opt.value() == &x); | |
| + int y = 101; | |
| + opt = std::move(y); | |
| + assert(opt); | |
| + assert(&opt.value() == &x); | |
| + assert(*opt == 101); | |
| + } | |
| +#endif | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment