fix(memory): support for creating TUniqueRef object from MakeUnique()

This commit is contained in:
_Redstone_c_ 2023-02-14 23:53:34 +08:00
parent fb0d1e978d
commit c4e0528d93
3 changed files with 110 additions and 30 deletions

View File

@ -274,7 +274,7 @@ NAMESPACE_UNNAMED_END
void TestUniquePointer()
{
{
TUniqueRef<int32> Temp(new int32);
TUniqueRef<int32> Temp = MakeUnique<int32>();
*Temp = 15;
always_check(*Temp.Get() = 15);
}
@ -327,7 +327,7 @@ void TestUniquePointer()
always_check(FDeleter::Num == 4);
{
TUniqueRef<int32[]> Temp(new int32[4]);
TUniqueRef<int32[]> Temp = MakeUnique<int32[]>(4);
Temp[0] = 15;
always_check(Temp.Get()[0] = 15);
}

View File

@ -435,22 +435,6 @@ public:
: Pointer(InPtr), Controller(InController)
{ }
template <typename U> requires (CArray<T> == CArray<U> && ((!CArray<U> && CConvertibleTo<T(*)[], U(*)[]>)
|| (CArray<U> && CConvertibleTo<TRemoveExtent<T>(*)[], TRemoveExtent<U>(*)[]>)))
NODISCARD FORCEINLINE operator TSharedRef<U>() &&
{
check_code({ return TSharedRef<U>(Pointer, Exchange(Controller, nullptr)); });
return TSharedRef<U>(Pointer, Controller);
}
template <typename U> requires (CArray<T> == CArray<U> && ((!CArray<U> && CConvertibleTo<T(*)[], U(*)[]>)
|| (CArray<U> && CConvertibleTo<TRemoveExtent<T>(*)[], TRemoveExtent<U>(*)[]>)))
NODISCARD FORCEINLINE operator TSharedPtr<U>() &&
{
check_code({ return TSharedPtr<U>(Pointer, Exchange(Controller, nullptr)); });
return TSharedPtr<U>(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<T>* Pointer;
FSharedController* Controller;
template <typename U> requires (CObject<U> && !CBoundedArray<U>) friend class NAMESPACE_REDCRAFT::TSharedRef;
template <typename U> requires (CObject<U> && !CBoundedArray<U>) friend class NAMESPACE_REDCRAFT::TSharedPtr;
template <typename U> requires (CObject<U> && !CBoundedArray<U>) friend class NAMESPACE_REDCRAFT::TWeakPtr;
};
struct FSharedPtrConstructor { explicit FSharedPtrConstructor() = default; };
@ -714,6 +702,15 @@ public:
Swap(A.Controller, B.Controller);
}
public:
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
FORCEINLINE TSharedRef(NAMESPACE_PRIVATE::TSharedProxy<U>&& InValue)
: Pointer(InValue.Pointer), Controller(InValue.Controller)
{
check_code({ InValue.Controller = nullptr; });
}
private:
T* Pointer;
@ -755,8 +752,6 @@ private:
template <typename U> requires (CObject<U> && !CBoundedArray<U>) friend class TSharedPtr;
template <typename U> requires (CObject<U> && !CBoundedArray<U>) friend class TWeakPtr;
template <typename U> friend class NAMESPACE_PRIVATE::TSharedProxy;
friend struct NAMESPACE_PRIVATE::FSharedHelper;
};
@ -932,6 +927,15 @@ public:
Swap(A.Controller, B.Controller);
}
public:
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
FORCEINLINE TSharedRef(NAMESPACE_PRIVATE::TSharedProxy<U>&& InValue)
: Pointer(InValue.Pointer), Controller(InValue.Controller)
{
check_code({ InValue.Controller = nullptr; });
}
private:
T* Pointer;
@ -958,8 +962,6 @@ private:
template <typename U> requires (CObject<U> && !CBoundedArray<U>) friend class TSharedPtr;
template <typename U> requires (CObject<U> && !CBoundedArray<U>) friend class TWeakPtr;
template <typename U> friend class NAMESPACE_PRIVATE::TSharedProxy;
friend struct NAMESPACE_PRIVATE::FSharedHelper;
};
@ -1185,6 +1187,15 @@ public:
Swap(A.Controller, B.Controller);
}
public:
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U>)
FORCEINLINE TSharedPtr(NAMESPACE_PRIVATE::TSharedProxy<U>&& InValue)
: Pointer(InValue.Pointer), Controller(InValue.Controller)
{
check_code({ InValue.Controller = nullptr; });
}
private:
T* Pointer;
@ -1224,8 +1235,6 @@ private:
template <typename U> requires (CObject<U> && !CBoundedArray<U>) friend class TSharedPtr;
template <typename U> requires (CObject<U> && !CBoundedArray<U>) friend class TWeakPtr;
template <typename U> friend class NAMESPACE_PRIVATE::TSharedProxy;
friend struct NAMESPACE_PRIVATE::FSharedHelper;
};
@ -1453,6 +1462,15 @@ public:
Swap(A.Controller, B.Controller);
}
public:
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U>)
FORCEINLINE TSharedPtr(NAMESPACE_PRIVATE::TSharedProxy<U>&& InValue)
: Pointer(InValue.Pointer), Controller(InValue.Controller)
{
check_code({ InValue.Controller = nullptr; });
}
private:
T* Pointer;
@ -1477,8 +1495,6 @@ private:
template <typename U> requires (CObject<U> && !CBoundedArray<U>) friend class TSharedPtr;
template <typename U> requires (CObject<U> && !CBoundedArray<U>) friend class TWeakPtr;
template <typename U> friend class NAMESPACE_PRIVATE::TSharedProxy;
friend struct NAMESPACE_PRIVATE::FSharedHelper;
};

View File

@ -145,6 +145,34 @@ concept CTUniqueRef = NAMESPACE_PRIVATE::TIsTUniqueRef<TRemoveCV<T>>::Value;
template <typename T>
concept CTUniquePtr = NAMESPACE_PRIVATE::TIsTUniquePtr<TRemoveCV<T>>::Value;
NAMESPACE_PRIVATE_BEGIN
template <typename T>
class TUniqueProxy : private FSingleton
{
public:
FORCEINLINE TUniqueProxy(TRemoveExtent<T>* InPtr)
: Pointer(InPtr)
{ }
# if DO_CHECK
FORCEINLINE ~TUniqueProxy() { checkf(Pointer == nullptr, TEXT("The return value from MakeUnique() is incorrectly ignored.")); }
# endif
private:
TRemoveExtent<T>* Pointer;
template <typename U, CInvocable<TRemoveExtent<U>*> E> requires (CObject<U> && !CBoundedArray<U> && (CDestructible<E> || CLValueReference<E>)) friend class NAMESPACE_REDCRAFT::TUniqueRef;
template <typename U, CInvocable<TRemoveExtent<U>*> E> requires (CObject<U> && !CBoundedArray<U> && (CDestructible<E> || CLValueReference<E>)) friend class NAMESPACE_REDCRAFT::TUniquePtr;
};
NAMESPACE_PRIVATE_END
/** This is essentially a reference version of TUniquePtr. */
template <typename T, CInvocable<TRemoveExtent<T>*> E> requires (CObject<T> && !CBoundedArray<T> && (CDestructible<E> || CLValueReference<E>))
class TUniqueRef final : private FSingleton
@ -256,6 +284,15 @@ public:
Swap(A.Storage.GetDeleter(), B.Storage.GetDeleter());
}
public:
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U> && CSameAs<E, TDefaultDelete<T>>)
FORCEINLINE TUniqueRef(NAMESPACE_PRIVATE::TUniqueProxy<U>&& InValue)
: Storage(InValue.Pointer)
{
check_code({ InValue.Pointer = nullptr; });
}
private:
NAMESPACE_PRIVATE::TUniqueStorage<T, E> Storage;
@ -381,6 +418,15 @@ public:
Swap(A.Storage.GetDeleter(), B.Storage.GetDeleter());
}
public:
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U> && CSameAs<E, TDefaultDelete<T[]>>)
FORCEINLINE TUniqueRef(NAMESPACE_PRIVATE::TUniqueProxy<U>&& InValue)
: Storage(InValue.Pointer)
{
check_code({ InValue.Pointer = nullptr; });
}
private:
NAMESPACE_PRIVATE::TUniqueStorage<T, E> Storage;
@ -512,6 +558,15 @@ public:
Swap(A.Storage.GetDeleter(), B.Storage.GetDeleter());
}
public:
template <typename U> requires (CConvertibleTo<U*, T*> && !CArray<U> && CSameAs<E, TDefaultDelete<T>>)
FORCEINLINE TUniquePtr(NAMESPACE_PRIVATE::TUniqueProxy<U>&& InValue)
: Storage(InValue.Pointer)
{
check_code({ InValue.Pointer = nullptr; });
}
private:
NAMESPACE_PRIVATE::TUniqueStorage<T, E> Storage;
@ -654,6 +709,15 @@ public:
Swap(A.Storage.GetDeleter(), B.Storage.GetDeleter());
}
public:
template <typename U> requires (CConvertibleTo<TRemoveExtent<U>(*)[], T(*)[]> && CArray<U> && CSameAs<E, TDefaultDelete<T[]>>)
FORCEINLINE TUniquePtr(NAMESPACE_PRIVATE::TUniqueProxy<U>&& InValue)
: Storage(InValue.Pointer)
{
check_code({ InValue.Pointer = nullptr; });
}
private:
NAMESPACE_PRIVATE::TUniqueStorage<T, E> Storage;
@ -665,21 +729,21 @@ private:
/** Constructs an object of type T and wraps it in a TUniquePtr. */
template <typename T, typename... Ts> requires (CObject<T> && !CArray<T> && CConstructibleFrom<T, Ts...> && CDestructible<T>)
NODISCARD FORCEINLINE constexpr TUniquePtr<T> MakeUnique(Ts&&... Args)
NODISCARD FORCEINLINE constexpr NAMESPACE_PRIVATE::TUniqueProxy<T> MakeUnique(Ts&&... Args)
{
if constexpr (sizeof...(Ts) == 0)
{
return TUniquePtr<T>(new T);
return NAMESPACE_PRIVATE::TUniqueProxy<T>(new T);
}
else
{
return TUniquePtr<T>(new T(Forward<Ts>(Args)...));
return NAMESPACE_PRIVATE::TUniqueProxy<T>(new T(Forward<Ts>(Args)...));
}
}
/** Constructs an array of type T and wraps it in a TUniquePtr. */
template <typename T> requires (CUnboundedArray<T> && CDefaultConstructible<TRemoveExtent<T>> && CDestructible<TRemoveExtent<T>>)
NODISCARD FORCEINLINE constexpr TUniquePtr<T> MakeUnique(size_t N) { return TUniquePtr<T>(new TRemoveExtent<T>[N]); }
NODISCARD FORCEINLINE constexpr NAMESPACE_PRIVATE::TUniqueProxy<T> MakeUnique(size_t N) { return NAMESPACE_PRIVATE::TUniqueProxy<T>(new TRemoveExtent<T>[N]); }
/** Construction of arrays of known bound is disallowed. */
template <typename T, typename... Ts> requires (CBoundedArray<T>)