From c4e0528d93005ffeb9d8cc54a3f5f97897e1b7bd Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Tue, 14 Feb 2023 23:53:34 +0800 Subject: [PATCH] fix(memory): support for creating TUniqueRef object from MakeUnique() --- .../Source/Private/Testing/MemoryTesting.cpp | 4 +- .../Source/Public/Memory/SharedPointer.h | 64 ++++++++++------- .../Source/Public/Memory/UniquePointer.h | 72 +++++++++++++++++-- 3 files changed, 110 insertions(+), 30 deletions(-) diff --git a/Redcraft.Utility/Source/Private/Testing/MemoryTesting.cpp b/Redcraft.Utility/Source/Private/Testing/MemoryTesting.cpp index 805f523..8f0cc00 100644 --- a/Redcraft.Utility/Source/Private/Testing/MemoryTesting.cpp +++ b/Redcraft.Utility/Source/Private/Testing/MemoryTesting.cpp @@ -274,7 +274,7 @@ NAMESPACE_UNNAMED_END void TestUniquePointer() { { - TUniqueRef Temp(new int32); + TUniqueRef Temp = MakeUnique(); *Temp = 15; always_check(*Temp.Get() = 15); } @@ -327,7 +327,7 @@ void TestUniquePointer() always_check(FDeleter::Num == 4); { - TUniqueRef Temp(new int32[4]); + TUniqueRef Temp = MakeUnique(4); Temp[0] = 15; always_check(Temp.Get()[0] = 15); } diff --git a/Redcraft.Utility/Source/Public/Memory/SharedPointer.h b/Redcraft.Utility/Source/Public/Memory/SharedPointer.h index 2374f9a..6b11ef0 100644 --- a/Redcraft.Utility/Source/Public/Memory/SharedPointer.h +++ b/Redcraft.Utility/Source/Public/Memory/SharedPointer.h @@ -435,22 +435,6 @@ public: : Pointer(InPtr), Controller(InController) { } - template requires (CArray == CArray && ((!CArray && CConvertibleTo) - || (CArray && CConvertibleTo(*)[], TRemoveExtent(*)[]>))) - NODISCARD FORCEINLINE operator TSharedRef() && - { - check_code({ return TSharedRef(Pointer, Exchange(Controller, nullptr)); }); - return TSharedRef(Pointer, Controller); - } - - template requires (CArray == CArray && ((!CArray && CConvertibleTo) - || (CArray && CConvertibleTo(*)[], TRemoveExtent(*)[]>))) - NODISCARD FORCEINLINE operator TSharedPtr() && - { - check_code({ return TSharedPtr(Pointer, Exchange(Controller, nullptr)); }); - return TSharedPtr(Pointer, Controller); - } - # if DO_CHECK FORCEINLINE ~TSharedProxy() { checkf(Controller == nullptr, TEXT("The return value from MakeShared() is incorrectly ignored.")); } @@ -462,6 +446,10 @@ private: TRemoveExtent* Pointer; FSharedController* Controller; + template requires (CObject && !CBoundedArray) friend class NAMESPACE_REDCRAFT::TSharedRef; + template requires (CObject && !CBoundedArray) friend class NAMESPACE_REDCRAFT::TSharedPtr; + template requires (CObject && !CBoundedArray) friend class NAMESPACE_REDCRAFT::TWeakPtr; + }; struct FSharedPtrConstructor { explicit FSharedPtrConstructor() = default; }; @@ -714,6 +702,15 @@ public: Swap(A.Controller, B.Controller); } +public: + + template requires (CConvertibleTo && !CArray) + FORCEINLINE TSharedRef(NAMESPACE_PRIVATE::TSharedProxy&& InValue) + : Pointer(InValue.Pointer), Controller(InValue.Controller) + { + check_code({ InValue.Controller = nullptr; }); + } + private: T* Pointer; @@ -755,8 +752,6 @@ private: template requires (CObject && !CBoundedArray) friend class TSharedPtr; template requires (CObject && !CBoundedArray) friend class TWeakPtr; - template friend class NAMESPACE_PRIVATE::TSharedProxy; - friend struct NAMESPACE_PRIVATE::FSharedHelper; }; @@ -932,6 +927,15 @@ public: Swap(A.Controller, B.Controller); } +public: + + template requires (CConvertibleTo(*)[], T(*)[]> && CArray) + FORCEINLINE TSharedRef(NAMESPACE_PRIVATE::TSharedProxy&& InValue) + : Pointer(InValue.Pointer), Controller(InValue.Controller) + { + check_code({ InValue.Controller = nullptr; }); + } + private: T* Pointer; @@ -958,8 +962,6 @@ private: template requires (CObject && !CBoundedArray) friend class TSharedPtr; template requires (CObject && !CBoundedArray) friend class TWeakPtr; - template friend class NAMESPACE_PRIVATE::TSharedProxy; - friend struct NAMESPACE_PRIVATE::FSharedHelper; }; @@ -1185,6 +1187,15 @@ public: Swap(A.Controller, B.Controller); } +public: + + template requires (CConvertibleTo && !CArray) + FORCEINLINE TSharedPtr(NAMESPACE_PRIVATE::TSharedProxy&& InValue) + : Pointer(InValue.Pointer), Controller(InValue.Controller) + { + check_code({ InValue.Controller = nullptr; }); + } + private: T* Pointer; @@ -1224,8 +1235,6 @@ private: template requires (CObject && !CBoundedArray) friend class TSharedPtr; template requires (CObject && !CBoundedArray) friend class TWeakPtr; - template friend class NAMESPACE_PRIVATE::TSharedProxy; - friend struct NAMESPACE_PRIVATE::FSharedHelper; }; @@ -1453,6 +1462,15 @@ public: Swap(A.Controller, B.Controller); } +public: + + template requires (CConvertibleTo(*)[], T(*)[]> && CArray) + FORCEINLINE TSharedPtr(NAMESPACE_PRIVATE::TSharedProxy&& InValue) + : Pointer(InValue.Pointer), Controller(InValue.Controller) + { + check_code({ InValue.Controller = nullptr; }); + } + private: T* Pointer; @@ -1477,8 +1495,6 @@ private: template requires (CObject && !CBoundedArray) friend class TSharedPtr; template requires (CObject && !CBoundedArray) friend class TWeakPtr; - template friend class NAMESPACE_PRIVATE::TSharedProxy; - friend struct NAMESPACE_PRIVATE::FSharedHelper; }; diff --git a/Redcraft.Utility/Source/Public/Memory/UniquePointer.h b/Redcraft.Utility/Source/Public/Memory/UniquePointer.h index f1d1cbd..57bd86c 100644 --- a/Redcraft.Utility/Source/Public/Memory/UniquePointer.h +++ b/Redcraft.Utility/Source/Public/Memory/UniquePointer.h @@ -145,6 +145,34 @@ concept CTUniqueRef = NAMESPACE_PRIVATE::TIsTUniqueRef>::Value; template concept CTUniquePtr = NAMESPACE_PRIVATE::TIsTUniquePtr>::Value; +NAMESPACE_PRIVATE_BEGIN + +template +class TUniqueProxy : private FSingleton +{ +public: + + FORCEINLINE TUniqueProxy(TRemoveExtent* InPtr) + : Pointer(InPtr) + { } + +# if DO_CHECK + + FORCEINLINE ~TUniqueProxy() { checkf(Pointer == nullptr, TEXT("The return value from MakeUnique() is incorrectly ignored.")); } + +# endif + +private: + + TRemoveExtent* Pointer; + + template *> E> requires (CObject && !CBoundedArray && (CDestructible || CLValueReference)) friend class NAMESPACE_REDCRAFT::TUniqueRef; + template *> E> requires (CObject && !CBoundedArray && (CDestructible || CLValueReference)) friend class NAMESPACE_REDCRAFT::TUniquePtr; + +}; + +NAMESPACE_PRIVATE_END + /** This is essentially a reference version of TUniquePtr. */ template *> E> requires (CObject && !CBoundedArray && (CDestructible || CLValueReference)) class TUniqueRef final : private FSingleton @@ -256,6 +284,15 @@ public: Swap(A.Storage.GetDeleter(), B.Storage.GetDeleter()); } +public: + + template requires (CConvertibleTo && !CArray && CSameAs>) + FORCEINLINE TUniqueRef(NAMESPACE_PRIVATE::TUniqueProxy&& InValue) + : Storage(InValue.Pointer) + { + check_code({ InValue.Pointer = nullptr; }); + } + private: NAMESPACE_PRIVATE::TUniqueStorage Storage; @@ -381,6 +418,15 @@ public: Swap(A.Storage.GetDeleter(), B.Storage.GetDeleter()); } +public: + + template requires (CConvertibleTo(*)[], T(*)[]> && CArray && CSameAs>) + FORCEINLINE TUniqueRef(NAMESPACE_PRIVATE::TUniqueProxy&& InValue) + : Storage(InValue.Pointer) + { + check_code({ InValue.Pointer = nullptr; }); + } + private: NAMESPACE_PRIVATE::TUniqueStorage Storage; @@ -512,6 +558,15 @@ public: Swap(A.Storage.GetDeleter(), B.Storage.GetDeleter()); } +public: + + template requires (CConvertibleTo && !CArray && CSameAs>) + FORCEINLINE TUniquePtr(NAMESPACE_PRIVATE::TUniqueProxy&& InValue) + : Storage(InValue.Pointer) + { + check_code({ InValue.Pointer = nullptr; }); + } + private: NAMESPACE_PRIVATE::TUniqueStorage Storage; @@ -654,6 +709,15 @@ public: Swap(A.Storage.GetDeleter(), B.Storage.GetDeleter()); } +public: + + template requires (CConvertibleTo(*)[], T(*)[]> && CArray && CSameAs>) + FORCEINLINE TUniquePtr(NAMESPACE_PRIVATE::TUniqueProxy&& InValue) + : Storage(InValue.Pointer) + { + check_code({ InValue.Pointer = nullptr; }); + } + private: NAMESPACE_PRIVATE::TUniqueStorage Storage; @@ -665,21 +729,21 @@ private: /** Constructs an object of type T and wraps it in a TUniquePtr. */ template requires (CObject && !CArray && CConstructibleFrom && CDestructible) -NODISCARD FORCEINLINE constexpr TUniquePtr MakeUnique(Ts&&... Args) +NODISCARD FORCEINLINE constexpr NAMESPACE_PRIVATE::TUniqueProxy MakeUnique(Ts&&... Args) { if constexpr (sizeof...(Ts) == 0) { - return TUniquePtr(new T); + return NAMESPACE_PRIVATE::TUniqueProxy(new T); } else { - return TUniquePtr(new T(Forward(Args)...)); + return NAMESPACE_PRIVATE::TUniqueProxy(new T(Forward(Args)...)); } } /** Constructs an array of type T and wraps it in a TUniquePtr. */ template requires (CUnboundedArray && CDefaultConstructible> && CDestructible>) -NODISCARD FORCEINLINE constexpr TUniquePtr MakeUnique(size_t N) { return TUniquePtr(new TRemoveExtent[N]); } +NODISCARD FORCEINLINE constexpr NAMESPACE_PRIVATE::TUniqueProxy MakeUnique(size_t N) { return NAMESPACE_PRIVATE::TUniqueProxy(new TRemoveExtent[N]); } /** Construction of arrays of known bound is disallowed. */ template requires (CBoundedArray)