fix(templates): fix TFunction incorrectly calling copy constructor in move constructor
This commit is contained in:
parent
ca67769796
commit
cbc4e3f926
@ -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; }
|
||||||
|
Loading…
Reference in New Issue
Block a user