diff --git a/Redcraft.Utility/Source/Public/Templates/SharedPointer.h b/Redcraft.Utility/Source/Public/Templates/SharedPointer.h index 94718bb..66e3e27 100644 --- a/Redcraft.Utility/Source/Public/Templates/SharedPointer.h +++ b/Redcraft.Utility/Source/Public/Templates/SharedPointer.h @@ -303,6 +303,130 @@ private: }; +struct FSharedHelper +{ + template requires (CSameAs> && CSameAs> + && (CTSharedRef || CTSharedPtr) && (CTSharedRef || CTSharedPtr)) + static T& CopySharedReference(T& This, const U& InValue) + { + if (This.Controller == InValue.Controller) + { + This.Pointer = InValue.Pointer; + return This; + } + + if constexpr (CTSharedRef) + { + This.Controller->ReleaseSharedReference(); + } + else if (This.Controller != nullptr) + { + This.Controller->ReleaseSharedReference(); + } + + This.Pointer = InValue.Pointer; + This.Controller = InValue.Controller; + + if constexpr (CTSharedRef || CTSharedRef) + { + This.Controller->AddSharedReference(); + } + else if (This.Controller != nullptr) + { + This.Controller->AddSharedReference(); + } + + return This; + } + + template requires (CSameAs> && CSameAs> + && (CTSharedRef || CTSharedPtr) && (CTSharedRef || CTSharedPtr)) + static T& MoveSharedReference(T& This, U&& InValue) + { + if constexpr (CTSharedRef) + { + Swap(This.Pointer, InValue.Pointer); + Swap(This.Controller, InValue.Controller); + } + else if constexpr (CTSharedPtr && CTSharedPtr) + { + if (&InValue == &This) UNLIKELY return This; + + if (This.Controller != nullptr) + { + This.Controller->ReleaseSharedReference(); + } + + This.Pointer = Exchange(InValue.Pointer, nullptr); + This.Controller = Exchange(InValue.Controller, nullptr); + } + else + { + CopySharedReference(This, InValue); + } + + return This; + } + + template requires (CSameAs> && CSameAs> + && CTWeakPtr && (CTSharedRef || CTSharedPtr || CTWeakPtr)) + static T& CopyWeakReference(T& This, const U& InValue) + { + if constexpr (CTWeakPtr && CTWeakPtr) + { + if (This.Controller == InValue.Controller) + { + This.Pointer = InValue.Pointer; + return This; + } + } + + if (This.Controller != nullptr) + { + This.Controller->ReleaseWeakReference(); + } + + This.Pointer = InValue.Pointer; + This.Controller = InValue.Controller; + + if constexpr (CTSharedRef) + { + This.Controller->AddWeakReference(); + } + else if (This.Controller != nullptr) + { + This.Controller->AddWeakReference(); + } + + return This; + } + + template requires (CSameAs> && CSameAs> + && CTWeakPtr && (CTSharedRef || CTSharedPtr || CTWeakPtr)) + static T& MoveWeakReference(T& This, U&& InValue) + { + if constexpr (CTWeakPtr && CTWeakPtr) + { + if (&InValue == &This) UNLIKELY return This; + + if (This.Controller != nullptr) + { + This.Controller->ReleaseWeakReference(); + } + + This.Pointer = Exchange(InValue.Pointer, nullptr); + This.Controller = Exchange(InValue.Controller, nullptr); + } + else + { + CopyWeakReference(This, InValue); + } + + return This; + } + +}; + template class TSharedProxy : private FSingleton { @@ -419,6 +543,10 @@ private: template requires (CObject && !CBoundedArray) class TSharedRef final { +private: + + using Helper = NAMESPACE_PRIVATE::FSharedHelper; + public: using ElementType = T; @@ -488,38 +616,18 @@ public: FORCEINLINE ~TSharedRef() { Controller->ReleaseSharedReference(); } /** Replaces the managed object with the one managed by 'InValue'. */ - TSharedRef& operator=(const TSharedRef& InValue) - { - if (Controller == InValue.Controller) - { - Pointer = InValue.Pointer; - return *this; - } - - Controller->ReleaseSharedReference(); - - Pointer = InValue.Pointer; - Controller = InValue.Controller; - - Controller->AddSharedReference(); - - return *this; - } + FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return Helper::CopySharedReference(*this, InValue); } /** Replaces the managed object with the one managed by 'InValue'. */ template requires (CConvertibleTo && !CArray) - FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return *this = *reinterpret_cast(&InValue); } + FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return Helper::CopySharedReference(*this, InValue); } /** Replaces the managed object with the one managed by 'InValue'. */ - FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) - { - Swap(*this, InValue); - return *this; - } + FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); } /** Replaces the managed object with the one managed by 'InValue'. */ template requires (CConvertibleTo && !CArray) - FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return *this = MoveTemp(*reinterpret_cast(&InValue)); } + FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); } /** Compares the pointer values of two TSharedRef. */ NODISCARD friend FORCEINLINE constexpr bool operator==(const TSharedRef& LHS, const TSharedRef& RHS) { return LHS.Get() == RHS.Get(); } @@ -643,12 +751,18 @@ private: template friend class NAMESPACE_PRIVATE::TSharedProxy; + friend struct NAMESPACE_PRIVATE::FSharedHelper; + }; /** Shared-ownership non-nullable smart pointer. Use this when you need an array's lifetime to be managed by a shared smart pointer. */ template class TSharedRef final { +private: + + using Helper = NAMESPACE_PRIVATE::FSharedHelper; + public: using ElementType = T; @@ -720,38 +834,18 @@ public: FORCEINLINE ~TSharedRef() { Controller->ReleaseSharedReference(); } /** Replaces the managed array with the one managed by 'InValue'. */ - TSharedRef& operator=(const TSharedRef& InValue) - { - if (Controller == InValue.Controller) - { - Pointer = InValue.Pointer; - return *this; - } - - Controller->ReleaseSharedReference(); - - Pointer = InValue.Pointer; - Controller = InValue.Controller; - - Controller->AddSharedReference(); - - return *this; - } + FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return Helper::CopySharedReference(*this, InValue); } /** Replaces the managed array with the one managed by 'InValue'. */ template requires (CConvertibleTo(*)[], T(*)[]> && CArray) - FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return *this = *reinterpret_cast(&InValue); } + FORCEINLINE TSharedRef& operator=(const TSharedRef& InValue) { return Helper::CopySharedReference(*this, InValue); } /** Replaces the managed array with the one managed by 'InValue'. */ - FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) - { - Swap(*this, InValue); - return *this; - } + FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); } /** Replaces the managed array with the one managed by 'InValue'. */ template requires (CConvertibleTo(*)[], T(*)[]> && CArray) - FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return *this = MoveTemp(*reinterpret_cast(&InValue)); } + FORCEINLINE TSharedRef& operator=(TSharedRef&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); } /** Compares the pointer values of two TSharedRef. */ NODISCARD friend FORCEINLINE constexpr bool operator==(const TSharedRef& LHS, const TSharedRef& RHS) { return LHS.Get() == RHS.Get(); } @@ -864,12 +958,18 @@ private: template friend class NAMESPACE_PRIVATE::TSharedProxy; + friend struct NAMESPACE_PRIVATE::FSharedHelper; + }; /** Shared-ownership smart pointer. Use this when you need an object's lifetime to be managed by a shared smart pointer. */ template requires (CObject && !CBoundedArray) class TSharedPtr final { +private: + + using Helper = NAMESPACE_PRIVATE::FSharedHelper; + public: using ElementType = T; @@ -943,20 +1043,6 @@ public: InValue.Controller = nullptr; } - /** - * Aliasing constructor used to create a shared reference which shares its reference count with - * another shared object, but pointing to a different object, typically a subobject. - * Must not be nullptr. - * - * @param InValue - The shared reference whose reference count should be shared. - * @param InPtr - The object pointer to use (instead of the incoming shared pointer's object). - */ - template - FORCEINLINE TSharedPtr(TSharedRef&& InValue, T* InPtr) - { - new (this) TSharedRef(MoveTemp(InValue), InPtr); - } - /** Constructs a TSharedPtr which shares ownership of the object managed by 'InValue'. */ FORCEINLINE TSharedPtr(const TSharedPtr& InValue) : TSharedPtr(InValue, InValue.Get()) { } @@ -975,10 +1061,6 @@ public: template requires (CConvertibleTo && !CArray) FORCEINLINE TSharedPtr(TSharedPtr&& InValue) : TSharedPtr(MoveTemp(InValue), InValue.Get()) { } - /** Constructs a TSharedPtr which shares ownership of the object managed by 'InValue'. */ - template requires (CConvertibleTo && !CArray) - FORCEINLINE TSharedPtr(TSharedRef&& InValue) : TSharedPtr(MoveTemp(InValue), InValue.Get()) { } - /** Constructs a TSharedPtr which gets ownership of the object managed by 'InValue'. */ template requires (CConvertibleTo && !CArray && (CDestructible || CLValueReference)) FORCEINLINE TSharedPtr(TUniquePtr&& InValue) : TSharedPtr(InValue.Release(), Forward(InValue.GetDeleter())) { } @@ -987,61 +1069,22 @@ public: FORCEINLINE ~TSharedPtr() { if (Controller != nullptr) Controller->ReleaseSharedReference(); } /** Replaces the managed object with the one managed by 'InValue'. */ - TSharedPtr& operator=(const TSharedPtr& InValue) - { - if (Controller == InValue.Controller) - { - Pointer = InValue.Pointer; - return *this; - } - - if (Controller != nullptr) - { - Controller->ReleaseSharedReference(); - } - - Pointer = InValue.Pointer; - Controller = InValue.Controller; - - if (Controller != nullptr) - { - Controller->AddSharedReference(); - } - - return *this; - } + FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return Helper::CopySharedReference(*this, InValue); } /** Replaces the managed object with the one managed by 'InValue'. */ template requires (CConvertibleTo && !CArray) - FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return *this = *reinterpret_cast(&InValue); } + FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return Helper::CopySharedReference(*this, InValue); } /** Replaces the managed object with the one managed by 'InValue'. */ template requires (CConvertibleTo && !CArray) - FORCEINLINE TSharedPtr& operator=(const TSharedRef& InValue) { return *reinterpret_cast*>(this) = InValue; } + FORCEINLINE TSharedPtr& operator=(const TSharedRef& InValue) { return Helper::CopySharedReference(*this, InValue); } /** Replaces the managed object with the one managed by 'InValue'. */ - TSharedPtr& operator=(TSharedPtr&& InValue) - { - if (&InValue == this) UNLIKELY return *this; - - if (Controller != nullptr) - { - Controller->ReleaseSharedReference(); - } - - Pointer = Exchange(InValue.Pointer, nullptr); - Controller = Exchange(InValue.Controller, nullptr); - - return *this; - } + FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); } /** Replaces the managed object with the one managed by 'InValue'. */ template requires (CConvertibleTo && !CArray) - FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return *this = MoveTemp(*reinterpret_cast(&InValue)); } - - /** Replaces the managed object with the one managed by 'InValue'. */ - template requires (CConvertibleTo && !CArray) - FORCEINLINE TSharedPtr& operator=(TSharedRef&& InValue) { return *reinterpret_cast*>(this) = MoveTemp(InValue); } + FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); } /** Replaces the managed object with the one managed by 'InValue'. */ template requires (CConvertibleTo && !CArray && (CDestructible || CLValueReference)) @@ -1183,12 +1226,18 @@ private: template friend class NAMESPACE_PRIVATE::TSharedProxy; + friend struct NAMESPACE_PRIVATE::FSharedHelper; + }; /** Shared-ownership smart pointer. Use this when you need an array's lifetime to be managed by a shared smart pointer. */ template class TSharedPtr final { +private: + + using Helper = NAMESPACE_PRIVATE::FSharedHelper; + public: using ElementType = T; @@ -1264,20 +1313,6 @@ public: InValue.Controller = nullptr; } - /** - * Aliasing constructor used to create a shared reference which shares its reference count with - * another shared array, but pointing to a different array, typically a subobject. - * Must not be nullptr. - * - * @param InValue - The shared reference whose reference count should be shared. - * @param InPtr - The array pointer to use (instead of the incoming shared pointer's array). - */ - template requires (CNullPointer || (CPointer && CConvertibleTo(*)[], T(*)[]>)) - FORCEINLINE TSharedPtr(TSharedRef&& InValue, V InPtr) - { - new (this) TSharedRef(MoveTemp(InValue), InPtr); - } - /** Constructs a TSharedPtr which shares ownership of the array managed by 'InValue'. */ FORCEINLINE TSharedPtr(const TSharedPtr& InValue) : TSharedPtr(InValue, InValue.Get()) { } @@ -1296,10 +1331,6 @@ public: template requires (CConvertibleTo(*)[], T(*)[]> && CArray) FORCEINLINE TSharedPtr(TSharedPtr&& InValue) : TSharedPtr(MoveTemp(InValue), InValue.Get()) { } - /** Constructs a TSharedPtr which shares ownership of the array managed by 'InValue'. */ - template requires (CConvertibleTo(*)[], T(*)[]> && CArray) - FORCEINLINE TSharedPtr(TSharedRef&& InValue) : TSharedPtr(MoveTemp(InValue), InValue.Get()) { } - /** Constructs a TSharedPtr which gets ownership of the array managed by 'InValue'. */ template requires (CConvertibleTo(*)[], T(*)[]> && CArray && (CDestructible || CLValueReference)) FORCEINLINE TSharedPtr(TUniquePtr&& InValue) : TSharedPtr(InValue.Release(), Forward(InValue.GetDeleter())) { } @@ -1308,61 +1339,22 @@ public: FORCEINLINE ~TSharedPtr() { if (Controller != nullptr) Controller->ReleaseSharedReference(); } /** Replaces the managed array with the one managed by 'InValue'. */ - TSharedPtr& operator=(const TSharedPtr& InValue) - { - if (Controller == InValue.Controller) - { - Pointer = InValue.Pointer; - return *this; - } - - if (Controller != nullptr) - { - Controller->ReleaseSharedReference(); - } - - Pointer = InValue.Pointer; - Controller = InValue.Controller; - - if (Controller != nullptr) - { - Controller->AddSharedReference(); - } - - return *this; - } + FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return Helper::CopySharedReference(*this, InValue); } /** Replaces the managed array with the one managed by 'InValue'. */ template requires (CConvertibleTo(*)[], T(*)[]> && CArray) - FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return *this = *reinterpret_cast(&InValue); } + FORCEINLINE TSharedPtr& operator=(const TSharedPtr& InValue) { return Helper::CopySharedReference(*this, InValue); } /** Replaces the managed array with the one managed by 'InValue'. */ template requires (CConvertibleTo(*)[], T(*)[]> && CArray) - FORCEINLINE TSharedPtr& operator=(const TSharedRef& InValue) { return *reinterpret_cast*>(this) = InValue; } + FORCEINLINE TSharedPtr& operator=(const TSharedRef& InValue) { return Helper::CopySharedReference(*this, InValue); } /** Replaces the managed array with the one managed by 'InValue'. */ - TSharedPtr& operator=(TSharedPtr&& InValue) - { - if (&InValue == this) UNLIKELY return *this; - - if (Controller != nullptr) - { - Controller->ReleaseSharedReference(); - } - - Pointer = Exchange(InValue.Pointer, nullptr); - Controller = Exchange(InValue.Controller, nullptr); - - return *this; - } + FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); } /** Replaces the managed array with the one managed by 'InValue'. */ template requires (CConvertibleTo(*)[], T(*)[]> && CArray) - FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return *this = MoveTemp(*reinterpret_cast(&InValue)); } - - /** Replaces the managed array with the one managed by 'InValue'. */ - template requires (CConvertibleTo(*)[], T(*)[]> && CArray) - FORCEINLINE TSharedPtr& operator=(TSharedRef&& InValue) { return *reinterpret_cast*>(this) = MoveTemp(InValue); } + FORCEINLINE TSharedPtr& operator=(TSharedPtr&& InValue) { return Helper::MoveSharedReference(*this, MoveTemp(InValue)); } /** Replaces the managed array with the one managed by 'InValue'. */ template requires (CConvertibleTo(*)[], T(*)[]> && CArray && (CDestructible || CLValueReference)) @@ -1495,12 +1487,18 @@ private: template friend class NAMESPACE_PRIVATE::TSharedProxy; + friend struct NAMESPACE_PRIVATE::FSharedHelper; + }; /** TWeakPtr is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by shared pointer. */ template requires (CObject && !CBoundedArray) class TWeakPtr final { +private: + + using Helper = NAMESPACE_PRIVATE::FSharedHelper; + public: using ElementType = T; @@ -1512,8 +1510,7 @@ public: FORCEINLINE constexpr TWeakPtr(nullptr_t) : TWeakPtr() { } /** Constructs new TWeakPtr which shares an object managed by 'InValue'. */ - FORCEINLINE TWeakPtr(const TWeakPtr& InValue) - : Pointer(InValue.Pointer), Controller(InValue.Controller) + FORCEINLINE TWeakPtr(const TWeakPtr& InValue) : Pointer(InValue.Pointer), Controller(InValue.Controller) { if (Controller != nullptr) { @@ -1523,14 +1520,20 @@ public: /** Constructs new TWeakPtr which shares an object managed by 'InValue'. */ template requires (CConvertibleTo && !CArray) - FORCEINLINE constexpr TWeakPtr(const TWeakPtr& InValue) : TWeakPtr(*reinterpret_cast(&InValue)) { } + FORCEINLINE constexpr TWeakPtr(const TWeakPtr& InValue) : Pointer(InValue.Pointer), Controller(InValue.Controller) + { + if (Controller != nullptr) + { + Controller->AddWeakReference(); + } + } /** Move constructors. Moves a TWeakPtr instance from 'InValue' into this. */ FORCEINLINE TWeakPtr(TWeakPtr&& InValue) : Pointer(Exchange(InValue.Pointer, nullptr)), Controller(Exchange(InValue.Controller, nullptr)) { } /** Move constructors. Moves a TWeakPtr instance from 'InValue' into this. */ template requires (CConvertibleTo && !CArray) - FORCEINLINE constexpr TWeakPtr(TWeakPtr&& InValue) : TWeakPtr(MoveTemp(*reinterpret_cast(&InValue))) { } + FORCEINLINE constexpr TWeakPtr(TWeakPtr&& InValue) : Pointer(Exchange(InValue.Pointer, nullptr)), Controller(Exchange(InValue.Controller, nullptr)) { } /** Constructs a weak pointer from a shared reference. */ template requires (CConvertibleTo && !CArray) @@ -1553,90 +1556,26 @@ public: FORCEINLINE ~TWeakPtr() { if (Controller != nullptr) Controller->ReleaseWeakReference(); } /** Replaces the managed object with the one managed by 'InValue'. */ - TWeakPtr& operator=(const TWeakPtr& InValue) - { - if (Controller == InValue.Controller) - { - Pointer = InValue.Pointer; - return *this; - } - - if (Controller != nullptr) - { - Controller->ReleaseWeakReference(); - } - - Pointer = InValue.Pointer; - Controller = InValue.Controller; - - if (Controller != nullptr) - { - Controller->AddWeakReference(); - } - - return *this; - } + FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return Helper::CopyWeakReference(*this, InValue); } /** Replaces the managed object with the one managed by 'InValue'. */ template requires (CConvertibleTo && !CArray) - FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return *this = *reinterpret_cast(&InValue); } + FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return Helper::CopyWeakReference(*this, InValue); } /** Replaces the managed object with the one managed by 'InValue'. */ - TWeakPtr& operator=(TWeakPtr&& InValue) - { - if (&InValue == this) UNLIKELY return *this; - - if (Controller != nullptr) - { - Controller->ReleaseWeakReference(); - } - - Pointer = Exchange(InValue.Pointer, nullptr); - Controller = Exchange(InValue.Controller, nullptr); - - return *this; - } + FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return Helper::MoveWeakReference(*this, MoveTemp(InValue)); } /** Replaces the managed object with the one managed by 'InValue'. */ template requires (CConvertibleTo && !CArray) - FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return *this = MoveTemp(*reinterpret_cast(&InValue)); } + FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return Helper::MoveWeakReference(*this, MoveTemp(InValue)); } /** Assignment operator sets this weak pointer from a shared reference. */ template requires (CConvertibleTo && !CArray) - FORCEINLINE TWeakPtr& operator=(const TSharedRef& InValue) - { - if (Controller != nullptr) - { - Controller->ReleaseWeakReference(); - } - - Pointer = InValue.Pointer; - Controller = InValue.Controller; - - Controller->AddWeakReference(); - - return *this; - } + FORCEINLINE TWeakPtr& operator=(const TSharedRef& InValue) { return Helper::CopyWeakReference(*this, InValue); } /** Assignment operator sets this weak pointer from a shared pointer. */ template requires (CConvertibleTo && !CArray) - FORCEINLINE TWeakPtr& operator=(const TSharedPtr& InValue) - { - if (Controller != nullptr) - { - Controller->ReleaseWeakReference(); - } - - Pointer = InValue.Pointer; - Controller = InValue.Controller; - - if (Controller != nullptr) - { - Controller->AddWeakReference(); - } - - return *this; - } + FORCEINLINE TWeakPtr& operator=(const TSharedPtr& InValue) { return Helper::CopyWeakReference(*this, InValue); } /** Effectively the same as calling Reset(). */ FORCEINLINE TWeakPtr& operator=(nullptr_t) { Reset(); return *this; } @@ -1682,12 +1621,18 @@ private: template requires (CObject && !CBoundedArray) friend class TSharedPtr; template requires (CObject && !CBoundedArray) friend class TWeakPtr; + friend struct NAMESPACE_PRIVATE::FSharedHelper; + }; /** TWeakPtr is a smart pointer that holds a non-owning ("weak") reference to an array that is managed by shared pointer. */ template class TWeakPtr final { +private: + + using Helper = NAMESPACE_PRIVATE::FSharedHelper; + public: using ElementType = T; @@ -1699,8 +1644,7 @@ public: FORCEINLINE constexpr TWeakPtr(nullptr_t) : TWeakPtr() { } /** Constructs new TWeakPtr which shares an array managed by 'InValue'. */ - FORCEINLINE TWeakPtr(const TWeakPtr& InValue) - : Pointer(InValue.Pointer), Controller(InValue.Controller) + FORCEINLINE TWeakPtr(const TWeakPtr& InValue) : Pointer(InValue.Pointer), Controller(InValue.Controller) { if (Controller != nullptr) { @@ -1710,14 +1654,20 @@ public: /** Constructs new TWeakPtr which shares an array managed by 'InValue'. */ template requires (CConvertibleTo(*)[], T(*)[]> && CArray) - FORCEINLINE constexpr TWeakPtr(const TWeakPtr& InValue) : TWeakPtr(*reinterpret_cast(&InValue)) { } + FORCEINLINE constexpr TWeakPtr(const TWeakPtr& InValue) : Pointer(InValue.Pointer), Controller(InValue.Controller) + { + if (Controller != nullptr) + { + Controller->AddWeakReference(); + } + } /** Move constructors. Moves a TWeakPtr instance from 'InValue' into this. */ FORCEINLINE TWeakPtr(TWeakPtr&& InValue) : Pointer(Exchange(InValue.Pointer, nullptr)), Controller(Exchange(InValue.Controller, nullptr)) { } /** Move constructors. Moves a TWeakPtr instance from 'InValue' into this. */ template requires (CConvertibleTo(*)[], T(*)[]> && CArray) - FORCEINLINE constexpr TWeakPtr(TWeakPtr&& InValue) : TWeakPtr(MoveTemp(*reinterpret_cast(&InValue))) { } + FORCEINLINE constexpr TWeakPtr(TWeakPtr&& InValue) : Pointer(Exchange(InValue.Pointer, nullptr)), Controller(Exchange(InValue.Controller, nullptr)) { } /** Constructs a weak pointer from a shared reference. */ template requires (CConvertibleTo(*)[], T(*)[]> && CArray) @@ -1740,90 +1690,26 @@ public: FORCEINLINE ~TWeakPtr() { if (Controller != nullptr) Controller->ReleaseWeakReference(); } /** Replaces the managed array with the one managed by 'InValue'. */ - TWeakPtr& operator=(const TWeakPtr& InValue) - { - if (Controller == InValue.Controller) - { - Pointer = InValue.Pointer; - return *this; - } - - if (Controller != nullptr) - { - Controller->ReleaseWeakReference(); - } - - Pointer = InValue.Pointer; - Controller = InValue.Controller; - - if (Controller != nullptr) - { - Controller->AddWeakReference(); - } - - return *this; - } + FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return Helper::CopyWeakReference(*this, InValue); } /** Replaces the managed array with the one managed by 'InValue'. */ template requires (CConvertibleTo(*)[], T(*)[]> && CArray) - FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return *this = *reinterpret_cast(&InValue); } + FORCEINLINE TWeakPtr& operator=(const TWeakPtr& InValue) { return Helper::CopyWeakReference(*this, InValue); } /** Replaces the managed array with the one managed by 'InValue'. */ - TWeakPtr& operator=(TWeakPtr&& InValue) - { - if (&InValue == this) UNLIKELY return *this; - - if (Controller != nullptr) - { - Controller->ReleaseWeakReference(); - } - - Pointer = Exchange(InValue.Pointer, nullptr); - Controller = Exchange(InValue.Controller, nullptr); - - return *this; - } + FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return Helper::MoveWeakReference(*this, MoveTemp(InValue)); } /** Replaces the managed array with the one managed by 'InValue'. */ template requires (CConvertibleTo(*)[], T(*)[]> && CArray) - FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return *this = MoveTemp(*reinterpret_cast(&InValue)); } + FORCEINLINE TWeakPtr& operator=(TWeakPtr&& InValue) { return Helper::MoveWeakReference(*this, MoveTemp(InValue)); } /** Assignment operator sets this weak pointer from a shared reference. */ template requires (CConvertibleTo(*)[], T(*)[]> && CArray) - FORCEINLINE TWeakPtr& operator=(const TSharedRef& InValue) - { - if (Controller != nullptr) - { - Controller->ReleaseWeakReference(); - } - - Pointer = InValue.Pointer; - Controller = InValue.Controller; - - Controller->AddWeakReference(); - - return *this; - } + FORCEINLINE TWeakPtr& operator=(const TSharedRef& InValue) { return Helper::CopyWeakReference(*this, InValue); } /** Assignment operator sets this weak pointer from a shared pointer. */ template requires (CConvertibleTo(*)[], T(*)[]> && CArray) - FORCEINLINE TWeakPtr& operator=(const TSharedPtr& InValue) - { - if (Controller != nullptr) - { - Controller->ReleaseWeakReference(); - } - - Pointer = InValue.Pointer; - Controller = InValue.Controller; - - if (Controller != nullptr) - { - Controller->AddWeakReference(); - } - - return *this; - } + FORCEINLINE TWeakPtr& operator=(const TSharedPtr& InValue) { return Helper::CopyWeakReference(*this, InValue); } /** Effectively the same as calling Reset(). */ FORCEINLINE TWeakPtr& operator=(nullptr_t) { Reset(); return *this; } @@ -1869,6 +1755,8 @@ private: template requires (CObject && !CBoundedArray) friend class TSharedPtr; template requires (CObject && !CBoundedArray) friend class TWeakPtr; + friend struct NAMESPACE_PRIVATE::FSharedHelper; + }; /** Constructs an object of type T and wraps it in a TSharedRef or TSharedPtr. Without initialization. */