template <class _Ty>
class shared_ptr : public _Ptr_base<_Ty> {
// class for reference counted resource management
private:
constexpr shared_ptr() noexcept = default;
constexpr shared_ptr(nullptr_t) noexcept {
} // construct empty shared_ptr
template <class _Ux,
enable_if_t<conjunction_v<conditional_t<is_array_v<_Ty>, _Can_array_delete<_Ux>, _Can_scalar_delete<_Ux>>,
_SP_convertible<_Ux, _Ty>>,
int> = 0>
explicit shared_ptr(_Ux* _Px) {
// construct shared_ptr object that owns _Px
if constexpr (is_array_v<_Ty>) {
_Setpd(_Px, default_delete<_Ux[]>{
});
} else {
_Temporary_owner<_Ux> _Owner(_Px);
_Set_ptr_rep_and_enable_shared(_Owner._Ptr, new _Ref_count<_Ux>(_Owner._Ptr));
_Owner._Ptr = nullptr;
}
}
template <class _Ux, class _Dx,
enable_if_t<conjunction_v<is_move_constructible<_Dx>, _Can_call_function_object<_Dx&, _Ux*&>,
_SP_convertible<_Ux, _Ty>>,
int> = 0>
shared_ptr(_Ux* _Px, _Dx _Dt) {
// construct with _Px, deleter
_Setpd(_Px, _STD move(_Dt));
}
template <class _Ux, class _Dx, class _Alloc,
enable_if_t<conjunction_v<is_move_constructible<_Dx>, _Can_call_function_object<_Dx&, _Ux*&>,
_SP_convertible<_Ux, _Ty>>,
int> = 0>
shared_ptr(_Ux* _Px, _Dx _Dt, _Alloc _Ax) {
// construct with _Px, deleter, allocator
_Setpda(_Px, _STD move(_Dt), _Ax);
}
template <class _Dx,
enable_if_t<conjunction_v<is_move_constructible<_Dx>, _Can_call_function_object<_Dx&, nullptr_t&>>, int> = 0>
shared_ptr(nullptr_t, _Dx _Dt) {
// construct with nullptr, deleter
_Setpd(nullptr, _STD move(_Dt));
}
template <class _Dx, class _Alloc,
enable_if_t<conjunction_v<is_move_constructible<_Dx>, _Can_call_function_object<_Dx&, nullptr_t&>>, int> = 0>
shared_ptr(nullptr_t, _Dx _Dt, _Alloc _Ax) {
// construct with nullptr, deleter, allocator
_Setpda(nullptr, _STD move(_Dt), _Ax);
}
template <class _Ty2>
shared_ptr(const shared_ptr<_Ty2>& _Right, element_type* _Px) noexcept {
// construct shared_ptr object that aliases _Right
this->_Alias_construct_from(_Right, _Px);
}
template <class _Ty2>
shared_ptr(shared_ptr<_Ty2>&& _Right, element_type* _Px) noexcept {
// move construct shared_ptr object that aliases _Right
this->_Alias_move_construct_from(_STD move(_Right), _Px);
}
shared_ptr(const shared_ptr& _Other) noexcept {
// construct shared_ptr object that owns same resource as _Other
this->_Copy_construct_from(_Other);
}
template <class _Ty2, enable_if_t<_SP_pointer_compatible<_Ty2, _Ty>::value, int> = 0>
shared_ptr(const shared_ptr<_Ty2>& _Other) noexcept {
// construct shared_ptr object that owns same resource as _Other
this->_Copy_construct_from(_Other);
}
shared_ptr(shared_ptr&& _Right) noexcept {
// construct shared_ptr object that takes resource from _Right
this->_Move_construct_from(_STD move(_Right));
}
template <class _Ty2, enable_if_t<_SP_pointer_compatible<_Ty2, _Ty>::value, int> = 0>
shared_ptr(shared_ptr<_Ty2>&& _Right) noexcept {
// construct shared_ptr object that takes resource from _Right
this->_Move_construct_from(_STD move(_Right));
}
template <class _Ty2, enable_if_t<_SP_pointer_compatible<_Ty2, _Ty>::value, int> = 0>
explicit shared_ptr(const weak_ptr<_Ty2>& _Other) {
// construct shared_ptr object that owns resource *_Other
if (!this->_Construct_from_weak(_Other)) {
_Throw_bad_weak_ptr();
}
}
template <class _Ux, class _Dx,
enable_if_t<conjunction_v<_SP_pointer_compatible<_Ux, _Ty>,
is_convertible<typename unique_ptr<_Ux, _Dx>::pointer, element_type*>>,
int> = 0>
shared_ptr(unique_ptr<_Ux, _Dx>&& _Other) {
using _Fancy_t = typename unique_ptr<_Ux, _Dx>::pointer;
using _Raw_t = typename unique_ptr<_Ux, _Dx>::element_type*;
using _Deleter_t = conditional_t<is_reference_v<_Dx>, decltype(_STD ref(_Other.get_deleter())), _Dx>;
const _Fancy_t _Fancy = _Other.get();
if (_Fancy) {
const _Raw_t _Raw = _Fancy;
const auto _Rx = new _Ref_count_resource<_Fancy_t, _Deleter_t>(_Fancy, _Other.get_deleter());
_Set_ptr_rep_and_enable_shared(_Raw, _Rx);
_Other.release();
}
}
~shared_ptr() noexcept {
// release resource
this->_Decref();
}
shared_ptr& operator=(const shared_ptr& _Right) noexcept {
shared_ptr(_Right).swap(*this);
return *this;
}
template <class _Ty2>
shared_ptr& operator=(const shared_ptr<_Ty2>& _Right) noexcept {
shared_ptr(_Right).swap(*this);
return *this;
}
shared_ptr& operator=(shared_ptr&& _Right) noexcept {
// take resource from _Right
shared_ptr(_STD move(_Right)).swap(*this);
return *this;
}
template <class _Ty2>
shared_ptr& operator=(shared_ptr<_Ty2>&& _Right) noexcept {
// take resource from _Right
shared_ptr(_STD move(_Right)).swap(*this);
return *this;
}
template <class _Ux, class _Dx>
shared_ptr& operator=(unique_ptr<_Ux, _Dx>&& _Right) {
// move from unique_ptr
shared_ptr(_STD move(_Right)).swap(*this);
return *this;
}
void swap(shared_ptr& _Other) noexcept {
this->_Swap(_Other);
}
void reset() noexcept {
// release resource and convert to empty shared_ptr object
shared_ptr().swap(*this);
}
template <class _Ux>
void reset(_Ux* _Px) {
// release, take ownership of _Px
shared_ptr(_Px).swap(*this);
}
template <class _Ux, class _Dx>
void reset(_Ux* _Px, _Dx _Dt) {
// release, take ownership of _Px, with deleter _Dt
shared_ptr(_Px, _Dt).swap(*this);
}
template <class _Ux, class _Dx, class _Alloc>
void reset(_Ux* _Px, _Dx _Dt, _Alloc _Ax) {
// release, take ownership of _Px, with deleter _Dt, allocator _Ax
shared_ptr(_Px, _Dt, _Ax).swap(*this);
}
template <class _Ty2 = _Ty, enable_if_t<!disjunction_v<is_array<_Ty2>, is_void<_Ty2>>, int> = 0>
_NODISCARD _Ty2& operator*() const noexcept {
return *get();
}
template <class _Ty2 = _Ty, enable_if_t<!is_array_v<_Ty2>, int> = 0>
_NODISCARD _Ty2* operator->() const noexcept {
return get();
}
template <class _Ty2 = _Ty, class _Elem = element_type, enable_if_t<is_array_v<_Ty2>, int> = 0>
_NODISCARD _Elem& operator[](ptrdiff_t _Idx) const noexcept /* strengthened */ {
return get()[_Idx];
}
explicit operator bool() const noexcept {
return get() != nullptr;
}
template <class _UxptrOrNullptr, class _Dx>
void _Setpd(const _UxptrOrNullptr _Px, _Dx _Dt) {
// take ownership of _Px, deleter _Dt
_Temporary_owner_del<_UxptrOrNullptr, _Dx> _Owner(_Px, _Dt);
_Set_ptr_rep_and_enable_shared(
_Owner._Ptr, new _Ref_count_resource<_UxptrOrNullptr, _Dx>(_Owner._Ptr, _STD move(_Dt)));
_Owner._Call_deleter = false;
}
template <class _UxptrOrNullptr, class _Dx, class _Alloc>
void _Setpda(const _UxptrOrNullptr _Px, _Dx _Dt, _Alloc _Ax) {
// take ownership of _Px, deleter _Dt, allocator _Ax
using _Alref_alloc = _Rebind_alloc_t<_Alloc, _Ref_count_resource_alloc<_UxptrOrNullptr, _Dx, _Alloc>>;
_Temporary_owner_del<_UxptrOrNullptr, _Dx> _Owner(_Px, _Dt);
_Alref_alloc _Alref(_Ax);
_Alloc_construct_ptr<_Alref_alloc> _Constructor(_Alref);
_Constructor._Allocate();
_Construct_in_place(*_Constructor._Ptr, _Owner._Ptr, _STD move(_Dt), _Ax);
_Set_ptr_rep_and_enable_shared(_Owner._Ptr, _Unfancy(_Constructor._Ptr));
_Constructor._Ptr = nullptr;
_Owner._Call_deleter = false;
}
template <class _Ux>
void _Set_ptr_rep_and_enable_shared(_Ux* const _Px, _Ref_count_base* const _Rx) noexcept {
// take ownership of _Px
this->_Ptr = _Px;
this->_Rep = _Rx;
if constexpr (conjunction_v<negation<is_array<_Ty>>, negation<is_volatile<_Ux>>, _Can_enable_shared<_Ux>>) {
if (_Px && _Px->_Wptr.expired()) {
_Px->_Wptr = shared_ptr<remove_cv_t<_Ux>>(*this, const_cast<remove_cv_t<_Ux>*>(_Px));
}
}
}
void _Set_ptr_rep_and_enable_shared(nullptr_t, _Ref_count_base* const _Rx) noexcept {
// take ownership of nullptr
this->_Ptr = nullptr;
this->_Rep = _Rx;
}
};
c++新特性11 (10)shared_ptr八”shared_ptr类“
猜你喜欢
转载自blog.csdn.net/thefist11cc/article/details/123930161
今日推荐
周排行