From a539f70535882132bcb65915547c92a4e7e3401b Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Tue, 5 Apr 2022 17:00:33 +0800 Subject: [PATCH] refactor(templates): make FTypeInfo behave more like std::type_info and optimize TAny --- .../Private/Testing/MiscellaneousTesting.cpp | 15 ++-- .../Source/Public/Miscellaneous/TypeInfo.h | 35 ++++----- .../Source/Public/Templates/Any.h | 71 ++++++++++--------- .../Source/Public/Templates/Noncopyable.h | 4 +- 4 files changed, 60 insertions(+), 65 deletions(-) diff --git a/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp b/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp index 403086e..49a536f 100644 --- a/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp +++ b/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp @@ -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)); - FTypeInfo TempD = Typeid(TTestTemplateType); + const FTypeInfo& TempC(Typeid(TTestTemplateType)); + const FTypeInfo& TempD = Typeid(TTestTemplateType); - 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); } diff --git a/Redcraft.Utility/Source/Public/Miscellaneous/TypeInfo.h b/Redcraft.Utility/Source/Public/Miscellaneous/TypeInfo.h index a25e012..3497fdb 100644 --- a/Redcraft.Utility/Source/Public/Miscellaneous/TypeInfo.h +++ b/Redcraft.Utility/Source/Public/Miscellaneous/TypeInfo.h @@ -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(this)->hash_code(); } + FORCEINLINE const char* GetName() const { return reinterpret_cast(this)->name(); } private: - const std::type_info* Ptr; + friend FORCEINLINE bool operator==(const FTypeInfo& LHS, const FTypeInfo& RHS) { return &LHS != &RHS ? *reinterpret_cast(&LHS) == *reinterpret_cast(&RHS) : true; } + friend FORCEINLINE bool operator< (const FTypeInfo& LHS, const FTypeInfo& RHS) { return reinterpret_cast(&LHS)->before(*reinterpret_cast(&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(&typeid(__VA_ARGS__))) NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) diff --git a/Redcraft.Utility/Source/Public/Templates/Any.h b/Redcraft.Utility/Source/Public/Templates/Any.h index 3e8349a..ac29222 100644 --- a/Redcraft.Utility/Source/Public/Templates/Any.h +++ b/Redcraft.Utility/Source/Public/Templates/Any.h @@ -135,11 +135,11 @@ struct TAny template struct TIsTriviallyStorable : TBoolConstant::Value && TIsTrivial::Value && TIsTriviallyCopyable::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 requires TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value && TIsConstructible::Type, Types...>::Value - explicit TAny(TInPlaceType, Types&&... Args) + FORCEINLINE explicit TAny(TInPlaceType, Types&&... Args) { using SelectedType = typename TDecay::Type; EmplaceImpl(Forward(Args)...); @@ -175,15 +175,15 @@ struct TAny template requires (!TIsSame::Type, TAny>::Value) && (!TIsTInPlaceType::Type>::Value) && TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value && TIsConstructible::Type, T&&>::Value - TAny(T&& InValue) : TAny(InPlaceType::Type>, Forward(InValue)) + FORCEINLINE TAny(T&& InValue) : TAny(InPlaceType::Type>, Forward(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 requires (!TIsSame::Type, TAny>::Value) && (!TIsTInPlaceType::Type>::Value) && TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value && TIsConstructible::Type, T&&>::Value - TAny& operator=(T&& InValue) + FORCEINLINE TAny& operator=(T&& InValue) { using SelectedType = typename TDecay::Type; - if (TypeInfo == Typeid(SelectedType)) + if (HoldsAlternative()) { if constexpr (TIsTriviallyStorable::Value) Memory::Memcpy(&InlineValue, &InValue, sizeof(SelectedType)); @@ -270,22 +270,23 @@ struct TAny template requires TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value && TIsConstructible::Type, T&&>::Value - typename TDecay::Type& Emplace(Types&&... Args) + FORCEINLINE typename TDecay::Type& Emplace(Types&&... Args) { - Reset(); + ResetImpl(); using SelectedType = typename TDecay::Type; EmplaceImpl(Forward(Args)...); return GetValue(); } - 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 constexpr bool HoldsAlternative() const { return IsValid() ? TypeInfo == Typeid(T) : false; } + template 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 requires TIsSame::Type>::Value&& TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value constexpr const T& Get(const T& DefaultValue) const& { return HoldsAlternative() ? GetValue() : 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 FORCEINLINE void EmplaceImpl(Types&&... Args) { - TypeInfo = Typeid(SelectedType); + TypeInfo = &Typeid(SelectedType); if constexpr (TIsTriviallyStorable::Value) { @@ -354,6 +348,13 @@ private: } } + FORCEINLINE void ResetImpl() + { + if (!IsValid() || IsTrivial()) return; + else if (IsInline()) RTTI->Destroy(&InlineValue); + else RTTI->Delete(DynamicValue); + } + }; template diff --git a/Redcraft.Utility/Source/Public/Templates/Noncopyable.h b/Redcraft.Utility/Source/Public/Templates/Noncopyable.h index 0ddb0a5..36346ff 100644 --- a/Redcraft.Utility/Source/Public/Templates/Noncopyable.h +++ b/Redcraft.Utility/Source/Public/Templates/Noncopyable.h @@ -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 { };