fix(templates): fix TFunction incorrectly calling copy constructor in move constructor

This commit is contained in:
_Redstone_c_ 2022-12-13 23:18:36 +08:00
parent ca67769796
commit cbc4e3f926

View File

@ -104,7 +104,7 @@ public:
FORCEINLINE constexpr TFunctionStorage() = default; FORCEINLINE constexpr TFunctionStorage() = default;
FORCEINLINE TFunctionStorage(const TFunctionStorage& InValue) requires (!bIsUnique) FORCEINLINE TFunctionStorage(const TFunctionStorage& InValue) requires (!bIsUnique)
: TypeInfo(InValue.TypeInfo) : RTTI(InValue.RTTI)
{ {
if (!IsValid()) return; if (!IsValid()) return;
@ -118,18 +118,18 @@ public:
Memory::Memcpy(InternalStorage, InValue.InternalStorage); Memory::Memcpy(InternalStorage, InValue.InternalStorage);
break; break;
case ERepresentation::Small: case ERepresentation::Small:
GetTypeInfo().CopyConstruct(GetStorage(), InValue.GetStorage()); GetRTTI().CopyConstruct(GetStorage(), InValue.GetStorage());
break; break;
case ERepresentation::Big: case ERepresentation::Big:
ExternalStorage = Memory::Malloc(GetTypeInfo().TypeSize, GetTypeInfo().TypeAlignment); ExternalStorage = Memory::Malloc(GetRTTI().TypeSize, GetRTTI().TypeAlignment);
GetTypeInfo().CopyConstruct(GetStorage(), InValue.GetStorage()); GetRTTI().CopyConstruct(GetStorage(), InValue.GetStorage());
break; break;
default: check_no_entry(); default: check_no_entry();
} }
} }
FORCEINLINE TFunctionStorage(TFunctionStorage&& InValue) FORCEINLINE TFunctionStorage(TFunctionStorage&& InValue)
: TypeInfo(InValue.TypeInfo) : RTTI(InValue.RTTI)
{ {
if (!IsValid()) return; if (!IsValid()) return;
@ -143,7 +143,7 @@ public:
Memory::Memcpy(InternalStorage, InValue.InternalStorage); Memory::Memcpy(InternalStorage, InValue.InternalStorage);
break; break;
case ERepresentation::Small: case ERepresentation::Small:
GetTypeInfo().MoveConstruct(GetStorage(), InValue.GetStorage()); GetRTTI().MoveConstruct(GetStorage(), InValue.GetStorage());
break; break;
case ERepresentation::Big: case ERepresentation::Big:
ExternalStorage = InValue.ExternalStorage; ExternalStorage = InValue.ExternalStorage;
@ -171,7 +171,7 @@ public:
{ {
Destroy(); Destroy();
TypeInfo = InValue.TypeInfo; RTTI = InValue.RTTI;
Callable = InValue.Callable; Callable = InValue.Callable;
switch (GetRepresentation()) switch (GetRepresentation())
@ -182,11 +182,11 @@ public:
Memory::Memcpy(InternalStorage, InValue.InternalStorage); Memory::Memcpy(InternalStorage, InValue.InternalStorage);
break; break;
case ERepresentation::Small: case ERepresentation::Small:
GetTypeInfo().CopyConstruct(GetStorage(), InValue.GetStorage()); GetRTTI().CopyConstruct(GetStorage(), InValue.GetStorage());
break; break;
case ERepresentation::Big: case ERepresentation::Big:
ExternalStorage = Memory::Malloc(GetTypeInfo().TypeSize, GetTypeInfo().TypeAlignment); ExternalStorage = Memory::Malloc(GetRTTI().TypeSize, GetRTTI().TypeAlignment);
GetTypeInfo().CopyConstruct(GetStorage(), InValue.GetStorage()); GetRTTI().CopyConstruct(GetStorage(), InValue.GetStorage());
break; break;
default: check_no_entry(); default: check_no_entry();
} }
@ -208,7 +208,7 @@ public:
{ {
Destroy(); Destroy();
TypeInfo = InValue.TypeInfo; RTTI = InValue.RTTI;
Callable = InValue.Callable; Callable = InValue.Callable;
switch (GetRepresentation()) switch (GetRepresentation())
@ -219,7 +219,7 @@ public:
Memory::Memcpy(InternalStorage, InValue.InternalStorage); Memory::Memcpy(InternalStorage, InValue.InternalStorage);
break; break;
case ERepresentation::Small: case ERepresentation::Small:
GetTypeInfo().MoveConstruct(GetStorage(), InValue.GetStorage()); GetRTTI().MoveConstruct(GetStorage(), InValue.GetStorage());
break; break;
case ERepresentation::Big: case ERepresentation::Big:
ExternalStorage = InValue.ExternalStorage; ExternalStorage = InValue.ExternalStorage;
@ -235,7 +235,7 @@ public:
FORCEINLINE constexpr uintptr GetValuePtr() const { return reinterpret_cast<uintptr>(GetStorage()); } FORCEINLINE constexpr uintptr GetValuePtr() const { return reinterpret_cast<uintptr>(GetStorage()); }
FORCEINLINE constexpr uintptr GetCallable() const { return Callable; } FORCEINLINE constexpr uintptr GetCallable() const { return Callable; }
FORCEINLINE constexpr bool IsValid() const { return TypeInfo != 0; } FORCEINLINE constexpr bool IsValid() const { return RTTI != 0; }
// Use Invalidate() to invalidate the storage or use Emplace<T>() to emplace a new object after destruction. // Use Invalidate() to invalidate the storage or use Emplace<T>() to emplace a new object after destruction.
FORCEINLINE void Destroy() FORCEINLINE void Destroy()
@ -248,10 +248,10 @@ public:
case ERepresentation::Trivial: case ERepresentation::Trivial:
break; break;
case ERepresentation::Small: case ERepresentation::Small:
GetTypeInfo().Destruct(GetStorage()); GetRTTI().Destruct(GetStorage());
break; break;
case ERepresentation::Big: case ERepresentation::Big:
GetTypeInfo().Destruct(GetStorage()); GetRTTI().Destruct(GetStorage());
Memory::Free(ExternalStorage); Memory::Free(ExternalStorage);
break; break;
default: check_no_entry(); default: check_no_entry();
@ -259,7 +259,7 @@ public:
} }
// Make sure you call this function after you have destroyed the held object using Destroy(). // Make sure you call this function after you have destroyed the held object using Destroy().
FORCEINLINE constexpr void Invalidate() { TypeInfo = 0; } FORCEINLINE constexpr void Invalidate() { RTTI = 0; }
// Make sure you call this function after you have destroyed the held object using Destroy(). // Make sure you call this function after you have destroyed the held object using Destroy().
template <typename T, typename... Ts> template <typename T, typename... Ts>
@ -269,8 +269,8 @@ public:
using DecayedType = TDecay<T>; using DecayedType = TDecay<T>;
static constexpr const FTypeInfo SelectedTypeInfo(InPlaceType<DecayedType>); static constexpr const FRTTI SelectedRTTI(InPlaceType<DecayedType>);
TypeInfo = reinterpret_cast<uintptr>(&SelectedTypeInfo); RTTI = reinterpret_cast<uintptr>(&SelectedRTTI);
if constexpr (CEmpty<DecayedType>) return; if constexpr (CEmpty<DecayedType>) return;
@ -280,17 +280,17 @@ public:
if constexpr (bIsTriviallyStorable) if constexpr (bIsTriviallyStorable)
{ {
new (&InternalStorage) DecayedType(Forward<Ts>(Args)...); new (&InternalStorage) DecayedType(Forward<Ts>(Args)...);
TypeInfo |= static_cast<uintptr>(ERepresentation::Trivial); RTTI |= static_cast<uintptr>(ERepresentation::Trivial);
} }
else if constexpr (bIsInlineStorable) else if constexpr (bIsInlineStorable)
{ {
new (&InternalStorage) DecayedType(Forward<Ts>(Args)...); new (&InternalStorage) DecayedType(Forward<Ts>(Args)...);
TypeInfo |= static_cast<uintptr>(ERepresentation::Small); RTTI |= static_cast<uintptr>(ERepresentation::Small);
} }
else else
{ {
ExternalStorage = new DecayedType(Forward<Ts>(Args)...); ExternalStorage = new DecayedType(Forward<Ts>(Args)...);
TypeInfo |= static_cast<uintptr>(ERepresentation::Big); RTTI |= static_cast<uintptr>(ERepresentation::Big);
} }
} }
@ -327,10 +327,10 @@ private:
void* ExternalStorage; void* ExternalStorage;
}; };
uintptr TypeInfo; uintptr RTTI;
uintptr Callable; uintptr Callable;
struct FMovableTypeInfo struct FMovableRTTI
{ {
const size_t TypeSize; const size_t TypeSize;
const size_t TypeAlignment; const size_t TypeAlignment;
@ -342,12 +342,12 @@ private:
const FDestruct Destruct; const FDestruct Destruct;
template <typename T> template <typename T>
FORCEINLINE constexpr FMovableTypeInfo(TInPlaceType<T>) FORCEINLINE constexpr FMovableRTTI(TInPlaceType<T>)
: TypeSize(sizeof(T)), TypeAlignment(alignof(T)) : TypeSize(sizeof(T)), TypeAlignment(alignof(T))
, MoveConstruct( , MoveConstruct(
[](void* A, void* B) [](void* A, void* B)
{ {
new (A) T(*reinterpret_cast<T*>(B)); new (A) T(MoveTemp(*reinterpret_cast<T*>(B)));
} }
) )
, Destruct( , Destruct(
@ -359,15 +359,15 @@ private:
{ } { }
}; };
struct FCopyableTypeInfo : public FMovableTypeInfo struct FCopyableRTTI : public FMovableRTTI
{ {
using FCopyConstruct = void(*)(void*, const void*); using FCopyConstruct = void(*)(void*, const void*);
const FCopyConstruct CopyConstruct; const FCopyConstruct CopyConstruct;
template <typename T> template <typename T>
FORCEINLINE constexpr FCopyableTypeInfo(TInPlaceType<T>) FORCEINLINE constexpr FCopyableRTTI(TInPlaceType<T>)
: FMovableTypeInfo(InPlaceType<T>) : FMovableRTTI(InPlaceType<T>)
, CopyConstruct( , CopyConstruct(
[](void* A, const void* B) [](void* A, const void* B)
{ {
@ -377,9 +377,9 @@ private:
{ } { }
}; };
using FTypeInfo = TConditional<bIsUnique, FMovableTypeInfo, FCopyableTypeInfo>; using FRTTI = TConditional<bIsUnique, FMovableRTTI, FCopyableRTTI>;
static_assert(alignof(FTypeInfo) >= 4); static_assert(alignof(FRTTI) >= 4);
static constexpr uintptr_t RepresentationMask = 3; static constexpr uintptr_t RepresentationMask = 3;
@ -391,8 +391,8 @@ private:
Big = 3, // ExternalStorage Big = 3, // ExternalStorage
}; };
FORCEINLINE constexpr ERepresentation GetRepresentation() const { return static_cast<ERepresentation>(TypeInfo & RepresentationMask); } FORCEINLINE constexpr ERepresentation GetRepresentation() const { return static_cast<ERepresentation>(RTTI & RepresentationMask); }
FORCEINLINE constexpr const FTypeInfo& GetTypeInfo() const { return *reinterpret_cast<const FTypeInfo*>(TypeInfo & ~RepresentationMask); } FORCEINLINE constexpr const FRTTI& GetRTTI() const { return *reinterpret_cast<const FRTTI*>(RTTI & ~RepresentationMask); }
FORCEINLINE constexpr void* GetStorage() { return GetRepresentation() == ERepresentation::Trivial || GetRepresentation() == ERepresentation::Small ? InternalStorage : ExternalStorage; } FORCEINLINE constexpr void* GetStorage() { return GetRepresentation() == ERepresentation::Trivial || GetRepresentation() == ERepresentation::Small ? InternalStorage : ExternalStorage; }
FORCEINLINE constexpr const void* GetStorage() const { return GetRepresentation() == ERepresentation::Trivial || GetRepresentation() == ERepresentation::Small ? InternalStorage : ExternalStorage; } FORCEINLINE constexpr const void* GetStorage() const { return GetRepresentation() == ERepresentation::Trivial || GetRepresentation() == ERepresentation::Small ? InternalStorage : ExternalStorage; }