refactor(templates): make FTypeInfo behave more like std::type_info and optimize TAny

This commit is contained in:
_Redstone_c_ 2022-04-05 17:00:33 +08:00
parent 2a3a5aec35
commit a539f70535
4 changed files with 60 additions and 65 deletions

View File

@ -237,22 +237,23 @@ NAMESPACE_UNNAMED_END
void TestTypeInfo()
{
FTypeInfo TempA;
FTypeInfo TempB(Invalid);
const FTypeInfo& TempA = Typeid(void);
const FTypeInfo& TempB = Typeid(void);
always_check(TempA == TempB);
always_check(TempA == Typeid(void));
FTypeInfo TempC(Typeid(TTestTemplateType<int8, int16>));
FTypeInfo TempD = Typeid(TTestTemplateType<int8, int32>);
const FTypeInfo& TempC(Typeid(TTestTemplateType<int8, int16>));
const FTypeInfo& TempD = Typeid(TTestTemplateType<int8, int32>);
FTypeInfo TempE, TempF;
TempE = TempC;
TempF = MoveTemp(TempD);
const FTypeInfo& TempE = TempC;
const FTypeInfo& TempF = TempD;
always_check(TempE != TempF);
always_check((TempE < TempF) == (TempF > TempE));
always_check((TempE > TempF) == (TempF < TempE));
always_check((TempE <= TempF) == (TempF >= TempE));
always_check((TempE >= TempF) == (TempF <= TempE));
always_check((TempE <=> TempF) != 0);
}

View File

@ -11,31 +11,24 @@ NAMESPACE_MODULE_BEGIN(Utility)
struct FTypeInfo
{
constexpr FTypeInfo() : FTypeInfo(typeid(void)) { }
FTypeInfo() = delete;
FTypeInfo(FTypeInfo&&) = delete;
FTypeInfo(const FTypeInfo&) = delete;
FTypeInfo& operator=(FTypeInfo&&) = delete;
FTypeInfo& operator=(const FTypeInfo&) = delete;
constexpr FTypeInfo(FInvalid) : FTypeInfo() { }
constexpr FTypeInfo(const std::type_info& InTypeInfo) : Ptr(&InTypeInfo) { }
size_t GetTypeHash() const { return Ptr->hash_code(); }
const char* GetName() const { return Ptr->name(); }
FORCEINLINE size_t GetTypeHash() const { return reinterpret_cast<const std::type_info*>(this)->hash_code(); }
FORCEINLINE const char* GetName() const { return reinterpret_cast<const std::type_info*>(this)->name(); }
private:
const std::type_info* Ptr;
friend FORCEINLINE bool operator==(const FTypeInfo& LHS, const FTypeInfo& RHS) { return &LHS != &RHS ? *reinterpret_cast<const std::type_info*>(&LHS) == *reinterpret_cast<const std::type_info*>(&RHS) : true; }
friend FORCEINLINE bool operator< (const FTypeInfo& LHS, const FTypeInfo& RHS) { return reinterpret_cast<const std::type_info*>(&LHS)->before(*reinterpret_cast<const std::type_info*>(&RHS)); }
friend FORCEINLINE bool operator<=(const FTypeInfo& LHS, const FTypeInfo& RHS) { return LHS == RHS || LHS < RHS; }
friend FORCEINLINE bool operator>=(const FTypeInfo& LHS, const FTypeInfo& RHS) { return LHS == RHS || LHS > RHS; }
friend FORCEINLINE bool operator> (const FTypeInfo& LHS, const FTypeInfo& RHS) { return !(LHS < RHS); }
friend bool operator==(FTypeInfo LHS, FTypeInfo RHS) { return *LHS.Ptr == *RHS.Ptr; }
friend bool operator<(FTypeInfo LHS, FTypeInfo RHS) { return LHS.Ptr->before(*RHS.Ptr); }
friend bool operator<=(FTypeInfo LHS, FTypeInfo RHS) { return LHS == RHS || LHS.Ptr->before(*RHS.Ptr); }
friend bool operator>=(FTypeInfo LHS, FTypeInfo RHS) { return LHS == RHS || !LHS.Ptr->before(*RHS.Ptr); }
friend bool operator>(FTypeInfo LHS, FTypeInfo RHS) { return !LHS.Ptr->before(*RHS.Ptr); }
friend strong_ordering operator<=>(FTypeInfo LHS, FTypeInfo RHS)
friend FORCEINLINE strong_ordering operator<=>(const FTypeInfo& LHS, const FTypeInfo& RHS)
{
if (LHS == RHS) return strong_ordering::equal;
return LHS < RHS ? strong_ordering::less : strong_ordering::greater;
@ -43,7 +36,7 @@ private:
};
#define Typeid(...) (FTypeInfo(typeid(__VA_ARGS__)))
#define Typeid(...) (*reinterpret_cast<const FTypeInfo*>(&typeid(__VA_ARGS__)))
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)

View File

@ -135,11 +135,11 @@ struct TAny
template <typename T>
struct TIsTriviallyStorable : TBoolConstant<TIsInlineStorable<T>::Value && TIsTrivial<T>::Value && TIsTriviallyCopyable<T>::Value> { };
constexpr TAny() : TypeInfo(Typeid(void)), RTTI(nullptr) { }
constexpr TAny() : TypeInfo(nullptr), RTTI(nullptr) { }
constexpr TAny(FInvalid) : TAny() { }
TAny(const TAny& InValue)
FORCEINLINE TAny(const TAny& InValue)
: TypeInfo(InValue.TypeInfo), RTTI(InValue.RTTI)
{
if (!IsValid()) return;
@ -149,7 +149,7 @@ struct TAny
else DynamicValue = RTTI->CopyNew(InValue.GetData());
}
TAny(TAny&& InValue)
FORCEINLINE TAny(TAny&& InValue)
: TypeInfo(InValue.TypeInfo), RTTI(InValue.RTTI)
{
if (!IsValid()) return;
@ -159,14 +159,14 @@ struct TAny
else
{
DynamicValue = InValue.DynamicValue;
InValue.TypeInfo = Typeid(void);
InValue.TypeInfo = nullptr;
}
}
template <typename T, typename... Types> requires TIsObject<typename TDecay<T>::Type>::Value
&& (!TIsArray<typename TDecay<T>::Type>::Value) && TIsDestructible<typename TDecay<T>::Type>::Value
&& TIsConstructible<typename TDecay<T>::Type, Types...>::Value
explicit TAny(TInPlaceType<T>, Types&&... Args)
FORCEINLINE explicit TAny(TInPlaceType<T>, Types&&... Args)
{
using SelectedType = typename TDecay<T>::Type;
EmplaceImpl<SelectedType>(Forward<Types>(Args)...);
@ -175,15 +175,15 @@ struct TAny
template <typename T> requires (!TIsSame<typename TDecay<T>::Type, TAny>::Value) && (!TIsTInPlaceType<typename TDecay<T>::Type>::Value)
&& TIsObject<typename TDecay<T>::Type>::Value && (!TIsArray<typename TDecay<T>::Type>::Value) && TIsDestructible<typename TDecay<T>::Type>::Value
&& TIsConstructible<typename TDecay<T>::Type, T&&>::Value
TAny(T&& InValue) : TAny(InPlaceType<typename TDecay<T>::Type>, Forward<T>(InValue))
FORCEINLINE TAny(T&& InValue) : TAny(InPlaceType<typename TDecay<T>::Type>, Forward<T>(InValue))
{ }
~TAny()
FORCEINLINE ~TAny()
{
Reset();
ResetImpl();
}
TAny& operator=(const TAny& InValue)
FORCEINLINE TAny& operator=(const TAny& InValue)
{
if (&InValue == this) return *this;
@ -191,14 +191,14 @@ struct TAny
{
Reset();
}
else if (TypeInfo == InValue.TypeInfo)
else if (GetTypeInfo() == InValue.GetTypeInfo())
{
if (IsTrivial()) Memory::Memcpy(InlineValue, InValue.InlineValue);
else RTTI->CopyAssign(GetData(), InValue.GetData());
}
else
{
Reset();
ResetImpl();
TypeInfo = InValue.TypeInfo;
RTTI = InValue.RTTI;
@ -211,7 +211,7 @@ struct TAny
return *this;
}
TAny& operator=(TAny&& InValue)
FORCEINLINE TAny& operator=(TAny&& InValue)
{
if (&InValue == this) return *this;
@ -219,7 +219,7 @@ struct TAny
{
Reset();
}
else if (TypeInfo == InValue.TypeInfo)
else if (GetTypeInfo() == InValue.GetTypeInfo())
{
if (IsTrivial()) Memory::Memcpy(InlineValue, InValue.InlineValue);
else if (IsInline()) RTTI->MoveAssign(GetData(), InValue.GetData());
@ -227,12 +227,12 @@ struct TAny
{
RTTI->Delete(DynamicValue);
DynamicValue = InValue.DynamicValue;
InValue.TypeInfo = Typeid(void);
InValue.TypeInfo = nullptr;
}
}
else
{
Reset();
ResetImpl();
TypeInfo = InValue.TypeInfo;
RTTI = InValue.RTTI;
@ -248,11 +248,11 @@ struct TAny
template <typename T> requires (!TIsSame<typename TDecay<T>::Type, TAny>::Value) && (!TIsTInPlaceType<typename TDecay<T>::Type>::Value)
&& TIsObject<typename TDecay<T>::Type>::Value && (!TIsArray<typename TDecay<T>::Type>::Value) && TIsDestructible<typename TDecay<T>::Type>::Value
&& TIsConstructible<typename TDecay<T>::Type, T&&>::Value
TAny& operator=(T&& InValue)
FORCEINLINE TAny& operator=(T&& InValue)
{
using SelectedType = typename TDecay<T>::Type;
if (TypeInfo == Typeid(SelectedType))
if (HoldsAlternative<SelectedType>())
{
if constexpr (TIsTriviallyStorable<SelectedType>::Value)
Memory::Memcpy(&InlineValue, &InValue, sizeof(SelectedType));
@ -270,22 +270,23 @@ struct TAny
template <typename T, typename... Types> requires TIsObject<typename TDecay<T>::Type>::Value
&& (!TIsArray<typename TDecay<T>::Type>::Value) && TIsDestructible<typename TDecay<T>::Type>::Value
&& TIsConstructible<typename TDecay<T>::Type, T&&>::Value
typename TDecay<T>::Type& Emplace(Types&&... Args)
FORCEINLINE typename TDecay<T>::Type& Emplace(Types&&... Args)
{
Reset();
ResetImpl();
using SelectedType = typename TDecay<T>::Type;
EmplaceImpl<SelectedType>(Forward<Types>(Args)...);
return GetValue<SelectedType>();
}
constexpr FTypeInfo GetTypeInfo() const { return TypeInfo; }
constexpr bool IsValid() const { return TypeInfo != Typeid(void); }
constexpr explicit operator bool() const { return TypeInfo != Typeid(void); }
constexpr const FTypeInfo& GetTypeInfo() const { return TypeInfo != nullptr ? *TypeInfo : Typeid(void); }
constexpr bool IsValid() const { return TypeInfo != nullptr; }
constexpr explicit operator bool() const { return TypeInfo != nullptr; }
constexpr bool IsInline() const { return RTTI != nullptr ? RTTI->bIsInline : true; }
constexpr bool IsTrivial() const { return RTTI == nullptr; }
template <typename T> constexpr bool HoldsAlternative() const { return IsValid() ? TypeInfo == Typeid(T) : false; }
template <typename T> constexpr bool HoldsAlternative() const { return IsValid() ? GetTypeInfo() == Typeid(T) : false; }
constexpr void* GetData() { return IsInline() ? &InlineValue : DynamicValue; }
constexpr const void* GetData() const { return IsInline() ? &InlineValue : DynamicValue; }
@ -308,17 +309,10 @@ struct TAny
template <typename T> requires TIsSame<T, typename TDecay<T>::Type>::Value&& TIsObject<typename TDecay<T>::Type>::Value && (!TIsArray<typename TDecay<T>::Type>::Value) && TIsDestructible<typename TDecay<T>::Type>::Value
constexpr const T& Get(const T& DefaultValue) const& { return HoldsAlternative<T>() ? GetValue<T>() : DefaultValue; }
void Reset()
FORCEINLINE void Reset()
{
if (!IsValid()) return;
TypeInfo = Typeid(void);
if (IsTrivial());
else if (IsInline()) RTTI->Destroy(&InlineValue);
else RTTI->Delete(DynamicValue);
RTTI = nullptr;
TypeInfo = nullptr;
ResetImpl();
}
private:
@ -329,13 +323,13 @@ private:
void* DynamicValue;
};
FTypeInfo TypeInfo;
const FTypeInfo* TypeInfo;
const NAMESPACE_PRIVATE::FAnyRTTI* RTTI;
template <typename SelectedType, typename... Types>
FORCEINLINE void EmplaceImpl(Types&&... Args)
{
TypeInfo = Typeid(SelectedType);
TypeInfo = &Typeid(SelectedType);
if constexpr (TIsTriviallyStorable<SelectedType>::Value)
{
@ -354,6 +348,13 @@ private:
}
}
FORCEINLINE void ResetImpl()
{
if (!IsValid() || IsTrivial()) return;
else if (IsInline()) RTTI->Destroy(&InlineValue);
else RTTI->Delete(DynamicValue);
}
};
template <typename T, size_t InlineSize, size_t InlineAlignment>

View File

@ -16,8 +16,8 @@ struct FNoncopyable
struct FNonmovable
{
FNonmovable() = default;
FNonmovable(const FNonmovable&&) = delete;
FNonmovable& operator=(const FNonmovable&&) = delete;
FNonmovable(FNonmovable&&) = delete;
FNonmovable& operator=(FNonmovable&&) = delete;
};
struct FSingleton : public FNoncopyable, public FNonmovable { };