diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -156,6 +156,11 @@ // The implementation moved to the header, but we still export the symbols from // the dylib for backwards compatibility. # define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10 + +// Defines exactly one std::default_delete for the whole program, as opposed +// to one per std::unique_ptr (only relevant to std::unique_ptr: other instances +// can still exist). +# define _LIBCPP_EXACTLY_ONE_DEFAULT_DELETE_PER_TYPE # elif _LIBCPP_ABI_VERSION == 1 # if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF)) // Enable compiling copies of now inline methods into the dylib to support diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h --- a/libcxx/include/__memory/unique_ptr.h +++ b/libcxx/include/__memory/unique_ptr.h @@ -35,7 +35,9 @@ #include <__type_traits/is_swappable.h> #include <__type_traits/is_void.h> #include <__type_traits/remove_extent.h> +#include <__type_traits/remove_pointer.h> #include <__type_traits/type_identity.h> +#include <__utility/exchange.h> #include <__utility/forward.h> #include <__utility/move.h> #include @@ -302,7 +304,6 @@ } }; - template class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> { public: @@ -509,6 +510,213 @@ } }; +template +class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp, default_delete<_Tp>> { +public: + using pointer _LIBCPP_NODEBUG = _Tp*; + using element_type _LIBCPP_NODEBUG = _Tp; + using deleter_type _LIBCPP_NODEBUG = default_delete<_Tp>; + +private: + template + inline static constexpr bool __constructible_from = + is_convertible_v && + (!is_reference_v && is_convertible_v); + + template + inline static constexpr bool __assignable_from = + is_convertible_v && is_assignable_v; + +public: + _LIBCPP_INLINE_VISIBILITY constexpr unique_ptr() = default; + + _LIBCPP_INLINE_VISIBILITY constexpr unique_ptr(nullptr_t) noexcept {} + + // CTAD only considers the primary template, so we can use pointer directly. + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(pointer __p) noexcept : __p_(__p) {} + + // CTAD only considers the primary template, so we can use pointer directly. + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, default_delete<_Tp>) noexcept + : __p_(__p) {} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __other) noexcept + : __p_(std::exchange(__other.__p_, nullptr)) {} + + template >>> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr<_Up, _Ep>&& __other) noexcept + : __p_(std::exchange(__other.__p_, nullptr)) {} + + template + _LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr<_Up[], _Ep>&&) = delete; + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 ~unique_ptr() noexcept { reset(); } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr&& __other) noexcept { + reset(__other.release()); + return *this; + } + + template + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 auto operator=(unique_ptr<_Up, _Ep>&& __other) noexcept + -> enable_if_t<__assignable_from>, unique_ptr&> { + reset(__other.release()); + return *this; + } + + template + _LIBCPP_INLINE_VISIBILITY unique_ptr& operator=(unique_ptr<_Up[], _Ep>&&) = delete; + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(nullptr_t) noexcept { + reset(); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 __add_lvalue_reference(_Tp) operator*() const noexcept { + return *__p_; + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer operator->() const noexcept { return __p_; } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const noexcept { return __p_; } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 deleter_type& get_deleter() noexcept { return __deleter; } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 const deleter_type& get_deleter() const noexcept { + return __deleter; + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit operator bool() const noexcept { + return __p_ != nullptr; + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer release() noexcept { + return std::exchange(__p_, nullptr); + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 void reset(pointer __other = nullptr) noexcept { + pointer __old = __p_; + __p_ = __other; + delete __old; + } + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 void swap(unique_ptr& other) noexcept { + std::swap(__p_, other.__p_); + } + +private: + pointer __p_ = nullptr; +#if defined(_LIBCPP_EXACTLY_ONE_DEFAULT_DELETE_PER_TYPE) + inline static deleter_type __deleter; +#else + deleter_type __deleter; +#endif + + template + friend class unique_ptr; +}; + +template +class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], default_delete<_Tp[]>> { +public: + using pointer = _Tp*; + using element_type = _Tp; + using deleter_type = default_delete<_Tp[]>; + +private: + template + inline static constexpr bool __pointer_compatible = + is_same_v<_Up, pointer> || + (is_pointer_v<_Up> && is_convertible_v (*)[], element_type (*)[]>); + + template + inline static constexpr bool __assignable = + is_same_v && + is_convertible_v && + is_assignable_v; + + template + inline static constexpr bool __constructible = + is_same_v && + is_convertible_v && + is_convertible_v; + +public: + constexpr unique_ptr() noexcept = default; + constexpr unique_ptr(nullptr_t, deleter_type = {}) noexcept {} + + template >> + _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(_Up __p) noexcept : __p_(__p) {} + + template >> + _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(_Up __p, default_delete<_Tp[]>) noexcept : __p_(__p) {} + + _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __other) noexcept + : __p_(std::exchange(__other.__p_, nullptr)) {} + + template >>> + _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr<_Up[], _Ep>&& __other) noexcept + : __p_(std::exchange(__other.__ptr_.first, nullptr)) {} + + _LIBCPP_CONSTEXPR_SINCE_CXX23 ~unique_ptr() { reset(); } + + _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr&& __other) noexcept { + reset(__other.release()); + return *this; + } + + template + _LIBCPP_CONSTEXPR_SINCE_CXX23 auto operator=(unique_ptr<_Up[], _Ep>&& __other) noexcept + -> enable_if_t<__assignable>, unique_ptr&> { + reset(__other.release()); + return *this; + } + + _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(nullptr_t) noexcept { + reset(); + return *this; + } + + _LIBCPP_CONSTEXPR_SINCE_CXX23 _Tp& operator[](const size_t __i) const noexcept { return __p_[__i]; } + + _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const noexcept { return __p_; } + + _LIBCPP_CONSTEXPR_SINCE_CXX23 deleter_type& get_deleter() noexcept { return __deleter; } + + _LIBCPP_CONSTEXPR_SINCE_CXX23 const deleter_type& get_deleter() const noexcept { return __deleter; } + + _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit operator bool() const noexcept { return __p_ != nullptr; } + + _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer release() noexcept { return std::exchange(__p_, nullptr); } + + template + _LIBCPP_CONSTEXPR_SINCE_CXX23 auto reset(_Up __other) noexcept -> enable_if_t<__pointer_compatible<_Up>> { + pointer __old = std::exchange(__p_, __other); + delete[] __old; + } + + constexpr void reset(nullptr_t = nullptr) noexcept { + delete[] __p_; + __p_ = nullptr; + } + + _LIBCPP_CONSTEXPR_SINCE_CXX23 void swap(unique_ptr& __other) noexcept { std::swap(__p_, __other.__p_); } + + // disable copy from lvalue + unique_ptr(const unique_ptr&) = delete; + unique_ptr& operator=(const unique_ptr&) = delete; + +private: + pointer __p_ = nullptr; +#if defined(_LIBCPP_EXACTLY_ONE_DEFAULT_DELETE_PER_TYPE) + inline static deleter_type __deleter; +#else + deleter_type __deleter; +#endif + + template + friend class unique_ptr; +}; + template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 typename enable_if< __is_swappable<_Dp>::value, void >::type