Created
August 14, 2016 23:54
-
-
Save EricWF/c5cc1e2e25c858b3488b955a9b36a2bb 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 298f91a..9675ee7 100644 | |
| --- a/include/optional | |
| +++ b/include/optional | |
| @@ -241,7 +241,7 @@ struct __optional_destruct_base<_Tp, true> | |
| __engaged_(true) {} | |
| }; | |
| -template <class _Tp> | |
| +template <class _Tp, bool = is_trivially_copyable<_Tp>::value> | |
| struct __optional_construct_base : __optional_destruct_base<_Tp> | |
| { | |
| using __base = __optional_destruct_base<_Tp>; | |
| @@ -249,66 +249,16 @@ struct __optional_construct_base : __optional_destruct_base<_Tp> | |
| using __base::__base; | |
| - 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; | |
| - } | |
| + constexpr __optional_construct_base() noexcept : __base() {} | |
| _LIBCPP_INLINE_VISIBILITY | |
| - void reset() noexcept | |
| + __optional_construct_base(const __optional_construct_base& __opt) | |
| { | |
| - if (this->__engaged_) | |
| - { | |
| - this->__val_.~value_type(); | |
| - this->__engaged_ = false; | |
| - } | |
| + if (__opt.__engaged_) | |
| + this->__construct(__opt.__val_); | |
| } | |
| -}; | |
| - | |
| -template <class _Tp, bool = is_move_constructible<_Tp>::value, | |
| - bool = is_trivially_copyable<__optional_destruct_base<_Tp>>::value> | |
| -struct __optional_move_base; | |
| - | |
| -template <class _Tp, bool _IsTC> | |
| -struct __optional_move_base<_Tp, false, _IsTC> : __optional_construct_base<_Tp> | |
| -{ | |
| - using __base = __optional_construct_base<_Tp>; | |
| - using __base::__base; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_base() = default; | |
| _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_base(__optional_move_base&&) = delete; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_base(const __optional_move_base&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_base& operator=(__optional_move_base&&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_base& operator=(const __optional_move_base&) = default; | |
| -}; | |
| - | |
| -template <class _Tp> | |
| -struct __optional_move_base<_Tp, true, true> : __optional_construct_base<_Tp> | |
| -{ | |
| - using __base = __optional_construct_base<_Tp>; | |
| - using __base::__base; | |
| -}; | |
| - | |
| -template <class _Tp> | |
| -struct __optional_move_base<_Tp, true, false> : __optional_construct_base<_Tp> | |
| -{ | |
| - using __base = __optional_construct_base<_Tp>; | |
| - using typename __base::value_type; | |
| - using __base::__base; | |
| - | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_base() = default; | |
| - | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_base(__optional_move_base&& __opt) | |
| + __optional_construct_base(__optional_construct_base&& __opt) | |
| noexcept(is_nothrow_move_constructible<value_type>::value) | |
| { | |
| if (__opt.__engaged_) | |
| @@ -316,108 +266,25 @@ struct __optional_move_base<_Tp, true, false> : __optional_construct_base<_Tp> | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_base(const __optional_move_base&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_base& operator=(__optional_move_base&&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_base& operator=(const __optional_move_base&) = default; | |
| -}; | |
| - | |
| -template <class _Tp, bool = is_copy_constructible<_Tp>::value, | |
| - bool = is_trivially_copyable<__optional_destruct_base<_Tp>>::value> | |
| -struct __optional_copy_base; | |
| - | |
| -template <class _Tp, bool _IsTC> | |
| -struct __optional_copy_base<_Tp, false, _IsTC> : __optional_move_base<_Tp> | |
| -{ | |
| - using __base = __optional_move_base<_Tp>; | |
| - using __base::__base; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_base() = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_base(__optional_copy_base&&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_base(const __optional_copy_base&) = delete; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_base& operator=(__optional_copy_base&&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_base& operator=(const __optional_copy_base&) = default; | |
| -}; | |
| - | |
| -template <class _Tp> | |
| -struct __optional_copy_base<_Tp, true, true> : __optional_move_base<_Tp> | |
| -{ | |
| - using __base = __optional_move_base<_Tp>; | |
| - using __base::__base; | |
| -}; | |
| - | |
| -template <class _Tp> | |
| -struct __optional_copy_base<_Tp, true, false> : __optional_move_base<_Tp> | |
| -{ | |
| - using __base = __optional_move_base<_Tp>; | |
| - using typename __base::value_type; | |
| - using __base::__base; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_base() = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_base(__optional_copy_base&&) = default; | |
| - | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_base(const __optional_copy_base& __opt) | |
| + __optional_construct_base& operator=(const __optional_construct_base& __opt) | |
| { | |
| - if (__opt.__engaged_) | |
| - this->__construct(__opt.__val_); | |
| + if (this->__engaged_ == __opt.__engaged_) | |
| + { | |
| + if (this->__engaged_) | |
| + this->__val_ = __opt.__val_; | |
| + } | |
| + else | |
| + { | |
| + if (this->__engaged_) | |
| + this->reset(); | |
| + else | |
| + this->__construct(__opt.__val_); | |
| + } | |
| + return *this; | |
| } | |
| _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_base& operator=(__optional_copy_base&&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_base& operator=(const __optional_copy_base&) = default; | |
| -}; | |
| - | |
| -template <class _Tp, bool = is_move_assignable<_Tp>::value, | |
| - bool = is_trivially_copyable<__optional_destruct_base<_Tp>>::value> | |
| -struct __optional_move_assign_base; | |
| - | |
| -template <class _Tp, bool _IsTC> | |
| -struct __optional_move_assign_base<_Tp, false, _IsTC> : __optional_copy_base<_Tp> | |
| -{ | |
| - using __base = __optional_copy_base<_Tp>; | |
| - using __base::__base; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_assign_base() = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_assign_base(__optional_move_assign_base&&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_assign_base(const __optional_move_assign_base&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_assign_base& operator=(__optional_move_assign_base&&) = delete; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; | |
| -}; | |
| - | |
| -template <class _Tp> | |
| -struct __optional_move_assign_base<_Tp, true, true> : __optional_copy_base<_Tp> | |
| -{ | |
| - using __base = __optional_copy_base<_Tp>; | |
| - using __base::__base; | |
| -}; | |
| - | |
| -template <class _Tp> | |
| -struct __optional_move_assign_base<_Tp, true, false> : __optional_copy_base<_Tp> | |
| -{ | |
| - using __base = __optional_copy_base<_Tp>; | |
| - using typename __base::value_type; | |
| - using __base::__base; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_assign_base() = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_assign_base(__optional_move_assign_base&&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_assign_base(const __optional_move_assign_base&) = default; | |
| - | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_assign_base& operator=(__optional_move_assign_base&& __opt) | |
| + __optional_construct_base& operator=(__optional_construct_base&& __opt) | |
| noexcept(is_nothrow_move_assignable<value_type>::value && | |
| is_nothrow_move_constructible<value_type>::value) | |
| { | |
| @@ -436,77 +303,59 @@ struct __optional_move_assign_base<_Tp, true, false> : __optional_copy_base<_Tp> | |
| return *this; | |
| } | |
| + template <class... _Args> | |
| _LIBCPP_INLINE_VISIBILITY | |
| - __optional_move_assign_base& operator=(const __optional_move_assign_base&) = default; | |
| -}; | |
| - | |
| -template <class _Tp, bool = is_copy_assignable<_Tp>::value, | |
| - bool = is_trivially_copyable<__optional_destruct_base<_Tp>>::value> | |
| -struct __optional_copy_assign_base; | |
| + void __construct(_Args&&... __args) | |
| + { | |
| + _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); | |
| + ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); | |
| + this->__engaged_ = true; | |
| + } | |
| -template <class _Tp, bool _IsTC> | |
| -struct __optional_copy_assign_base<_Tp, false, _IsTC> : __optional_move_assign_base<_Tp> | |
| -{ | |
| - using __base = __optional_move_assign_base<_Tp>; | |
| - using __base::__base; | |
| _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_assign_base() = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_assign_base(__optional_copy_assign_base&&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_assign_base(const __optional_copy_assign_base&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_assign_base& operator=(const __optional_copy_assign_base&) = delete; | |
| -}; | |
| - | |
| -template <class _Tp> | |
| -struct __optional_copy_assign_base<_Tp, true, true> : __optional_move_assign_base<_Tp> | |
| -{ | |
| - using __base = __optional_move_assign_base<_Tp>; | |
| - using __base::__base; | |
| + void reset() noexcept | |
| + { | |
| + if (this->__engaged_) | |
| + { | |
| + this->__val_.~value_type(); | |
| + this->__engaged_ = false; | |
| + } | |
| + } | |
| }; | |
| template <class _Tp> | |
| -struct __optional_copy_assign_base<_Tp, true, false> : __optional_move_assign_base<_Tp> | |
| +struct __optional_construct_base<_Tp, true> : __optional_destruct_base<_Tp> | |
| { | |
| - using __base = __optional_move_assign_base<_Tp>; | |
| + using __base = __optional_destruct_base<_Tp>; | |
| using typename __base::value_type; | |
| + | |
| using __base::__base; | |
| + | |
| + template <class... _Args> | |
| _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_assign_base() = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_assign_base(__optional_copy_assign_base&&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_assign_base(const __optional_copy_assign_base&) = default; | |
| - _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_assign_base& operator=(__optional_copy_assign_base&&) = default; | |
| + void __construct(_Args&&... __args) | |
| + { | |
| + _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); | |
| + ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); | |
| + this->__engaged_ = true; | |
| + } | |
| _LIBCPP_INLINE_VISIBILITY | |
| - __optional_copy_assign_base& operator=(const __optional_copy_assign_base& __opt) | |
| + void reset() noexcept | |
| { | |
| - if (this->__engaged_ == __opt.__engaged_) | |
| - { | |
| - if (this->__engaged_) | |
| - this->__val_ = __opt.__val_; | |
| - } | |
| - else | |
| + if (this->__engaged_) | |
| { | |
| - if (this->__engaged_) | |
| - this->reset(); | |
| - else | |
| - this->__construct(__opt.__val_); | |
| + this->__val_.~value_type(); | |
| + this->__engaged_ = false; | |
| } | |
| - return *this; | |
| } | |
| }; | |
| template <class _Tp, class = void> | |
| -class __optional_storage : __optional_copy_assign_base<_Tp> | |
| +class __optional_storage : __optional_construct_base<_Tp> | |
| { | |
| public: | |
| - using __base = __optional_copy_assign_base<_Tp>; | |
| + using __base = __optional_construct_base<_Tp>; | |
| using typename __base::value_type; | |
| using __base::__base; | |
| @@ -557,9 +406,75 @@ constexpr bool _Is_specialization = false; | |
| template <class... _Args, template <class...> class _Template> | |
| constexpr bool _Is_specialization<_Template<_Args...>, _Template> = true; | |
| + | |
| +template <bool _CanCopy, bool _CanMove> | |
| +struct __optional_sfinae_ctor_base {}; | |
| +template <> | |
| +struct __optional_sfinae_ctor_base<false, false> { | |
| + __optional_sfinae_ctor_base() = default; | |
| + __optional_sfinae_ctor_base(__optional_sfinae_ctor_base const&) = delete; | |
| + __optional_sfinae_ctor_base(__optional_sfinae_ctor_base &&) = delete; | |
| + __optional_sfinae_ctor_base& operator=(__optional_sfinae_ctor_base const&) = default; | |
| + __optional_sfinae_ctor_base& operator=(__optional_sfinae_ctor_base&&) = default; | |
| +}; | |
| +template <> | |
| +struct __optional_sfinae_ctor_base<true, false> { | |
| + __optional_sfinae_ctor_base() = default; | |
| + __optional_sfinae_ctor_base(__optional_sfinae_ctor_base const&) = default; | |
| + __optional_sfinae_ctor_base(__optional_sfinae_ctor_base &&) = delete; | |
| + __optional_sfinae_ctor_base& operator=(__optional_sfinae_ctor_base const&) = default; | |
| + __optional_sfinae_ctor_base& operator=(__optional_sfinae_ctor_base&&) = default; | |
| +}; | |
| +template <> | |
| +struct __optional_sfinae_ctor_base<false, true> { | |
| + __optional_sfinae_ctor_base() = default; | |
| + __optional_sfinae_ctor_base(__optional_sfinae_ctor_base const&) = delete; | |
| + __optional_sfinae_ctor_base(__optional_sfinae_ctor_base &&) = default; | |
| + __optional_sfinae_ctor_base& operator=(__optional_sfinae_ctor_base const&) = default; | |
| + __optional_sfinae_ctor_base& operator=(__optional_sfinae_ctor_base&&) = default; | |
| +}; | |
| +template <class _Tp> | |
| +using __optional_sfinae_ctor_base_t = __optional_sfinae_ctor_base< | |
| + is_copy_constructible<_Tp>::value, | |
| + is_move_constructible<_Tp>::value | |
| +>; | |
| +template <bool _CanCopy, bool _CanMove> | |
| +struct __optional_sfinae_assign_base {}; | |
| +template <> | |
| +struct __optional_sfinae_assign_base<false, false> { | |
| + __optional_sfinae_assign_base() = default; | |
| + __optional_sfinae_assign_base(__optional_sfinae_assign_base const&) = default; | |
| + __optional_sfinae_assign_base(__optional_sfinae_assign_base &&) = default; | |
| + __optional_sfinae_assign_base& operator=(__optional_sfinae_assign_base const&) = delete; | |
| + __optional_sfinae_assign_base& operator=(__optional_sfinae_assign_base&&) = delete; | |
| +}; | |
| +template <> | |
| +struct __optional_sfinae_assign_base<true, false> { | |
| + __optional_sfinae_assign_base() = default; | |
| + __optional_sfinae_assign_base(__optional_sfinae_assign_base const&) = default; | |
| + __optional_sfinae_assign_base(__optional_sfinae_assign_base &&) = default; | |
| + __optional_sfinae_assign_base& operator=(__optional_sfinae_assign_base const&) = default; | |
| + __optional_sfinae_assign_base& operator=(__optional_sfinae_assign_base&&) = delete; | |
| +}; | |
| +template <> | |
| +struct __optional_sfinae_assign_base<false, true> { | |
| + __optional_sfinae_assign_base() = default; | |
| + __optional_sfinae_assign_base(__optional_sfinae_assign_base const&) = default; | |
| + __optional_sfinae_assign_base(__optional_sfinae_assign_base &&) = default; | |
| + __optional_sfinae_assign_base& operator=(__optional_sfinae_assign_base const&) = delete; | |
| + __optional_sfinae_assign_base& operator=(__optional_sfinae_assign_base&&) = default; | |
| +}; | |
| +template <class _Tp> | |
| +using __optional_sfinae_assign_base_t = __optional_sfinae_assign_base< | |
| + is_copy_assignable<_Tp>::value, | |
| + is_move_assignable<_Tp>::value | |
| +>; | |
| + | |
| template <class _Tp> | |
| class optional | |
| - : private __optional_storage<_Tp> | |
| + : private __optional_storage<_Tp>, | |
| + private __optional_sfinae_ctor_base_t<_Tp>, | |
| + private __optional_sfinae_assign_base_t<_Tp> | |
| { | |
| template <class> friend class optional; | |
| using __base = __optional_storage<_Tp>; | |
| @@ -570,7 +485,7 @@ public: | |
| "Instantiation of optional with a reference type is ill-formed."); | |
| static_assert(!is_same<remove_cv_t<value_type>, nullopt_t>::value, | |
| "Instantiation of optional with a nullopt_t type is ill-formed."); | |
| - static_assert(is_reference<value_type>::value || is_object<value_type>::value, | |
| + static_assert(is_object<value_type>::value, | |
| "Instantiation of optional with a non-object type is undefined behavior."); | |
| _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment