From eeef55e9b45871e8559942add39f7186da0db467 Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Thu, 12 May 2022 23:36:32 +0800 Subject: [PATCH] refactor(*): remove FTypeInfo and replace it with the native std::type_info --- .../Private/Testing/MiscellaneousTesting.cpp | 31 -- .../Private/Testing/TemplatesTesting.cpp | 17 +- .../Source/Public/Concepts/Comparable.h | 2 +- .../Source/Public/Memory/MemoryOperator.h | 18 +- .../Public/Miscellaneous/CoreMiscDefines.h | 8 + .../Source/Public/Miscellaneous/TypeInfo.h | 319 ------------------ .../Source/Public/Templates/Any.h | 167 +++++---- .../Source/Public/Templates/TypeHash.h | 6 + .../Source/Public/Templates/Variant.h | 177 +++++----- .../Public/Testing/MiscellaneousTesting.h | 1 - .../Public/TypeTraits/BitwiseOperations.h | 11 +- 11 files changed, 229 insertions(+), 528 deletions(-) delete mode 100644 Redcraft.Utility/Source/Public/Miscellaneous/TypeInfo.h diff --git a/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp b/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp index 59b559e..a0dc7cf 100644 --- a/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp +++ b/Redcraft.Utility/Source/Private/Testing/MiscellaneousTesting.cpp @@ -1,7 +1,6 @@ #include "Testing/MiscellaneousTesting.h" #include "Miscellaneous/AssertionMacros.h" -#include "Miscellaneous/TypeInfo.h" #include "Miscellaneous/Compare.h" NAMESPACE_REDCRAFT_BEGIN @@ -14,7 +13,6 @@ void TestMiscellaneous() { TestAssertionMacros(); TestCompare(); - TestTypeInfo(); } NAMESPACE_UNNAMED_BEGIN @@ -219,35 +217,6 @@ void TestCompare() always_check(SynthThreeWayCompare(FTestSynth( 0), FTestSynth(-1)) == weak_ordering::greater); } -NAMESPACE_UNNAMED_BEGIN - -template -struct TTestTemplateType { }; - -NAMESPACE_UNNAMED_END - -void TestTypeInfo() -{ - const FTypeInfo& TempA = Typeid(void); - const FTypeInfo& TempB = Typeid(void); - - always_check(TempA == TempB); - always_check(TempA == Typeid(void)); - - const FTypeInfo& TempC(Typeid(TTestTemplateType)); - const FTypeInfo& TempD = Typeid(TTestTemplateType); - - 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); -} - NAMESPACE_END(Testing) NAMESPACE_MODULE_END(Utility) diff --git a/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp b/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp index 995727a..cd2c0e2 100644 --- a/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp +++ b/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp @@ -339,11 +339,13 @@ void TestVariant() const TVariant TempRD = TempLC; auto ReturnRD = MoveTemp(TempRD).Visit(TestQualifiers); always_check((TIsSame::Value)); - + } + + { always_check(GetTypeHash(TVariant(114)) == GetTypeHash(TVariant(114))); always_check(GetTypeHash(TVariant(114)) != GetTypeHash(TVariant(514))); } - + { TVariant TempA = Invalid; TVariant TempB = static_cast(16); @@ -561,6 +563,11 @@ void TestAny() TempZ = FTracker(); } + { + always_check(GetTypeHash(FAny(114)) == GetTypeHash(FAny(114))); + always_check(GetTypeHash(FAny(114)) != GetTypeHash(FAny(514))); + } + { FAny TempA = Invalid; FAny TempB = static_cast(16); @@ -1087,8 +1094,8 @@ void TestFunction() always_check(TempC() == 0xEE); always_check(TempD() == 0xFF); - always_check(TempC.TargetType() == Typeid(FFunctor)); - always_check(TempD.TargetType() == Typeid(FFunctor)); + always_check(TempC.TargetType() == typeid(FFunctor)); + always_check(TempD.TargetType() == typeid(FFunctor)); } { @@ -1203,7 +1210,7 @@ void TestFunction() { TFunction Identity = [](bool In) { return In; }; TFunction NotIdentity = NotFn(Identity); - + always_check(Identity(true)); always_check(NotIdentity(false)); } diff --git a/Redcraft.Utility/Source/Public/Concepts/Comparable.h b/Redcraft.Utility/Source/Public/Concepts/Comparable.h index d23340f..2d5fa09 100644 --- a/Redcraft.Utility/Source/Public/Concepts/Comparable.h +++ b/Redcraft.Utility/Source/Public/Concepts/Comparable.h @@ -11,7 +11,7 @@ NAMESPACE_MODULE_BEGIN(Utility) template concept CWeaklyEqualityComparableWith = - requires(const TRemoveReference::Type & A, const TRemoveReference::Type & B) + requires(const TRemoveReference::Type& A, const TRemoveReference::Type& B) { { A == B } -> CBooleanTestable; { A != B } -> CBooleanTestable; diff --git a/Redcraft.Utility/Source/Public/Memory/MemoryOperator.h b/Redcraft.Utility/Source/Public/Memory/MemoryOperator.h index 37c9a40..fbf1d95 100644 --- a/Redcraft.Utility/Source/Public/Memory/MemoryOperator.h +++ b/Redcraft.Utility/Source/Public/Memory/MemoryOperator.h @@ -13,7 +13,7 @@ NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_BEGIN(Memory) template - requires (TIsDefaultConstructible::Value || TIsZeroConstructible::Value) + requires TIsDefaultConstructible::Value FORCEINLINE void DefaultConstruct(ElementType* Address, size_t Count = 1) { if constexpr (TIsZeroConstructible::Value) @@ -33,7 +33,7 @@ FORCEINLINE void DefaultConstruct(ElementType* Address, size_t Count = 1) } template - requires (TIsConstructible::Value || TIsBitwiseConstructible::Value) + requires TIsConstructible::Value FORCEINLINE void Construct(DestinationElementType* Destination, const SourceElementType* Source, size_t Count = 1) { if constexpr (TIsBitwiseConstructible::Value) @@ -53,7 +53,7 @@ FORCEINLINE void Construct(DestinationElementType* Destination, const SourceElem } template - requires (TIsCopyConstructible::Value) + requires TIsCopyConstructible::Value FORCEINLINE void CopyConstruct(ElementType* Destination, const ElementType* Source, size_t Count = 1) { if constexpr (TIsTriviallyCopyConstructible::Value) @@ -73,7 +73,7 @@ FORCEINLINE void CopyConstruct(ElementType* Destination, const ElementType* Sour } template - requires (TIsMoveConstructible::Value) + requires TIsMoveConstructible::Value FORCEINLINE void MoveConstruct(ElementType* Destination, ElementType* Source, size_t Count = 1) { if constexpr (TIsTriviallyMoveConstructible::Value) @@ -93,7 +93,7 @@ FORCEINLINE void MoveConstruct(ElementType* Destination, ElementType* Source, si } template - requires ((TIsConstructible::Value && TIsDestructible::Value) || TIsBitwiseRelocatable::Value) + requires TIsConstructible::Value && TIsDestructible::Value FORCEINLINE void RelocateConstruct(DestinationElementType* Destination, SourceElementType* Source, size_t Count = 1) { if constexpr (TIsBitwiseRelocatable::Value) @@ -115,7 +115,7 @@ FORCEINLINE void RelocateConstruct(DestinationElementType* Destination, SourceEl } template - requires (TIsDestructible::Value) + requires TIsDestructible::Value FORCEINLINE void Destruct(ElementType* Element, size_t Count = 1) { if constexpr (!TIsTriviallyDestructible::Value) @@ -132,7 +132,7 @@ FORCEINLINE void Destruct(ElementType* Element, size_t Count = 1) } template - requires (TIsCopyAssignable::Value) + requires TIsCopyAssignable::Value FORCEINLINE void CopyAssign(ElementType* Destination, const ElementType* Source, size_t Count = 1) { if constexpr (TIsTriviallyCopyAssignable::Value) @@ -152,7 +152,7 @@ FORCEINLINE void CopyAssign(ElementType* Destination, const ElementType* Source, } template - requires (TIsMoveAssignable::Value) + requires TIsMoveAssignable::Value FORCEINLINE void MoveAssign(ElementType* Destination, ElementType* Source, size_t Count = 1) { if constexpr (TIsTriviallyCopyConstructible::Value) @@ -172,7 +172,7 @@ FORCEINLINE void MoveAssign(ElementType* Destination, ElementType* Source, size_ } template - requires (CEqualityComparable || TIsBitwiseComparable::Value) + requires CEqualityComparable FORCEINLINE bool Compare(const ElementType* LHS, const ElementType* RHS, size_t Count = 1) { if constexpr (TIsBitwiseComparable::Value) diff --git a/Redcraft.Utility/Source/Public/Miscellaneous/CoreMiscDefines.h b/Redcraft.Utility/Source/Public/Miscellaneous/CoreMiscDefines.h index 4ee256a..41c38a8 100644 --- a/Redcraft.Utility/Source/Public/Miscellaneous/CoreMiscDefines.h +++ b/Redcraft.Utility/Source/Public/Miscellaneous/CoreMiscDefines.h @@ -2,6 +2,9 @@ #include "Miscellaneous/CoreDefines.h" +#include +#include + NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) @@ -35,6 +38,11 @@ template struct TInPlaceIndex { explicit TInPlaceIndex() = default; template inline constexpr TInPlaceType InPlaceType{ }; template inline constexpr TInPlaceIndex InPlaceIndex{ }; +using type_info = NAMESPACE_STD::type_info; + +template +using initializer_list = NAMESPACE_STD::initializer_list; + NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Miscellaneous/TypeInfo.h b/Redcraft.Utility/Source/Public/Miscellaneous/TypeInfo.h deleted file mode 100644 index 0689b30..0000000 --- a/Redcraft.Utility/Source/Public/Miscellaneous/TypeInfo.h +++ /dev/null @@ -1,319 +0,0 @@ -#pragma once - -#include "CoreTypes.h" -#include "Concepts/Concepts.h" -#include "Templates/Utility.h" -#include "Templates/TypeHash.h" -#include "Miscellaneous/Compare.h" -#include "TypeTraits/TypeTraits.h" -#include "Memory/MemoryOperator.h" - -#include - -NAMESPACE_REDCRAFT_BEGIN -NAMESPACE_MODULE_BEGIN(Redcraft) -NAMESPACE_MODULE_BEGIN(Utility) - -struct FTypeInfo; - -NAMESPACE_PRIVATE_BEGIN - -struct FTypeInfoStatic -{ - template - static constexpr FTypeInfo Value = { InPlaceType }; -}; - -NAMESPACE_PRIVATE_END - -struct FTypeInfo -{ - FTypeInfo() = delete; - FTypeInfo(FTypeInfo&&) = delete; - FTypeInfo(const FTypeInfo&) = delete; - FTypeInfo& operator=(FTypeInfo&&) = delete; - FTypeInfo& operator=(const FTypeInfo&) = delete; - - constexpr const std::type_info& GetNative() const { return Native; }; - - FORCEINLINE size_t GetTypeHash() const { return GetNative().hash_code(); } - FORCEINLINE const char* GetName() const { return GetNative().name(); } - - constexpr size_t GetTypeSize() const { return TypeSize; } - constexpr size_t GetTypeAlignment() const { return TypeAlignment; } - - constexpr bool IsZeroConstructible () const { return bIsZeroConstructible; } - constexpr bool IsBitwiseConstructible () const { return bIsBitwiseConstructible; } - constexpr bool IsBitwiseRelocatable () const { return bIsBitwiseRelocatable; } - constexpr bool IsBitwiseComparable () const { return bIsBitwiseComparable; } - - constexpr bool IsArithmetic () const { return bIsArithmetic; } - constexpr bool IsFundamental () const { return bIsFundamental; } - constexpr bool IsObject () const { return bIsObject; } - constexpr bool IsScalar () const { return bIsScalar; } - constexpr bool IsCompound () const { return bIsCompound; } - constexpr bool IsMemberPointer () const { return bIsMemberPointer; } - - constexpr bool IsVoid () const { return bIsVoid; } - constexpr bool IsNullPointer () const { return bIsNullPointer; } - constexpr bool IsIntegral () const { return bIsIntegral; } - constexpr bool IsFloatingPoint () const { return bIsFloatingPoint; } - constexpr bool IsArray () const { return bIsArray; } - constexpr bool IsPointer () const { return bIsPointer; } - constexpr bool IsMemberObjectPointer () const { return bIsMemberObjectPointer; } - constexpr bool IsMemberFunctionPointer () const { return bIsMemberFunctionPointer; } - constexpr bool IsEnum () const { return bIsEnum; } - constexpr bool IsUnion () const { return bIsUnion; } - constexpr bool IsClass () const { return bIsClass; } - constexpr bool IsFunction () const { return bIsFunction; } - - constexpr bool IsDefaultConstructible () const { return bIsDefaultConstructible; } - constexpr bool IsCopyConstructible () const { return bIsCopyConstructible; } - constexpr bool IsMoveConstructible () const { return bIsMoveConstructible; } - constexpr bool IsCopyAssignable () const { return bIsCopyAssignable; } - constexpr bool IsMoveAssignable () const { return bIsMoveAssignable; } - constexpr bool IsDestructible () const { return bIsDestructible; } - constexpr bool IsTriviallyDefaultConstructible () const { return bIsTriviallyDefaultConstructible; } - constexpr bool IsTriviallyCopyConstructible () const { return bIsTriviallyCopyConstructible; } - constexpr bool IsTriviallyMoveConstructible () const { return bIsTriviallyMoveConstructible; } - constexpr bool IsTriviallyCopyAssignable () const { return bIsTriviallyCopyAssignable; } - constexpr bool IsTriviallyMoveAssignable () const { return bIsTriviallyMoveAssignable; } - constexpr bool IsTriviallyDestructible () const { return bIsTriviallyDestructible; } - constexpr bool HasVirtualDestructor () const { return bHasVirtualDestructor; } - - constexpr bool IsTrivial () const { return bIsTrivial; } - constexpr bool IsTriviallyCopyable () const { return bIsTriviallyCopyable; } - constexpr bool IsStandardLayout () const { return bIsStandardLayout; } - constexpr bool HasUniqueObjectRepresentations () const { return bHasUniqueObjectRepresentations; } - constexpr bool IsEmpty () const { return bIsEmpty; } - constexpr bool IsPolymorphic () const { return bIsPolymorphic; } - constexpr bool IsAbstract () const { return bIsAbstract; } - constexpr bool IsFinal () const { return bIsFinal; } - constexpr bool IsAggregate () const { return bIsAggregate; } - constexpr bool IsSigned () const { return bIsSigned; } - constexpr bool IsUnsigned () const { return bIsUnsigned; } - constexpr bool IsBoundedArray () const { return bIsBoundedArray; } - constexpr bool IsUnboundedArray () const { return bIsUnboundedArray; } - constexpr bool IsScopedEnum () const { return bIsScopedEnum; } - - constexpr bool IsEqualityComparable () const { return bIsEqualityComparable; } - constexpr bool IsTotallyOrdered () const { return bIsTotallyOrdered; } - constexpr bool IsThreeWayComparable () const { return bIsThreeWayComparable; } - constexpr bool IsHashable () const { return bIsHashable; } - constexpr bool IsSwappable () const { return bIsSwappable; } - - FORCEINLINE void DefaultConstruct (void* Address ) const { return DefaultConstructImpl (Address ); } - FORCEINLINE void CopyConstruct (void* Destination, const void* Source) const { return CopyConstructImpl (Destination, Source); } - FORCEINLINE void MoveConstruct (void* Destination, void* Source) const { return MoveConstructImpl (Destination, Source); } - FORCEINLINE void RelocateConstruct (void* Destination, void* Source) const { return RelocateConstructImpl (Destination, Source); } - FORCEINLINE void CopyAssign (void* Destination, const void* Source) const { return CopyAssignImpl (Destination, Source); } - FORCEINLINE void MoveAssign (void* Destination, void* Source) const { return MoveAssignImpl (Destination, Source); } - FORCEINLINE void Destroy (void* Element ) const { return DestroyImpl (Element ); } - - FORCEINLINE bool EqualityCompare (const void* LHS, const void* RHS) const { return EqualityCompareImpl (LHS, RHS); } - FORCEINLINE partial_ordering SynthThreeWayCompare (const void* LHS, const void* RHS) const { return SynthThreeWayCompareImpl (LHS, RHS); } - FORCEINLINE partial_ordering ThreeWayCompare (const void* LHS, const void* RHS) const { return ThreeWayCompareImpl (LHS, RHS); } - FORCEINLINE size_t HashItem (const void* A ) const { return HashItemImpl (A ); } - FORCEINLINE void SwapItem ( void* A, void* B ) const { return SwapItemImpl (A, B ); } - -private: - - const std::type_info& Native; - - const size_t TypeSize; - const size_t TypeAlignment; - - const uint8 bIsZeroConstructible : 1; - const uint8 bIsBitwiseConstructible : 1; - const uint8 bIsBitwiseRelocatable : 1; - const uint8 bIsBitwiseComparable : 1; - - const uint8 bIsArithmetic : 1; - const uint8 bIsFundamental : 1; - const uint8 bIsObject : 1; - const uint8 bIsScalar : 1; - const uint8 bIsCompound : 1; - const uint8 bIsMemberPointer : 1; - - const uint8 bIsVoid : 1; - const uint8 bIsNullPointer : 1; - const uint8 bIsIntegral : 1; - const uint8 bIsFloatingPoint : 1; - const uint8 bIsArray : 1; - const uint8 bIsPointer : 1; - const uint8 bIsMemberObjectPointer : 1; - const uint8 bIsMemberFunctionPointer : 1; - const uint8 bIsEnum : 1; - const uint8 bIsUnion : 1; - const uint8 bIsClass : 1; - const uint8 bIsFunction : 1; - - const uint8 bIsDefaultConstructible : 1; - const uint8 bIsCopyConstructible : 1; - const uint8 bIsMoveConstructible : 1; - const uint8 bIsCopyAssignable : 1; - const uint8 bIsMoveAssignable : 1; - const uint8 bIsDestructible : 1; - const uint8 bIsTriviallyDefaultConstructible : 1; - const uint8 bIsTriviallyCopyConstructible : 1; - const uint8 bIsTriviallyMoveConstructible : 1; - const uint8 bIsTriviallyCopyAssignable : 1; - const uint8 bIsTriviallyMoveAssignable : 1; - const uint8 bIsTriviallyDestructible : 1; - const uint8 bHasVirtualDestructor : 1; - - const uint8 bIsTrivial : 1; - const uint8 bIsTriviallyCopyable : 1; - const uint8 bIsStandardLayout : 1; - const uint8 bHasUniqueObjectRepresentations : 1; - const uint8 bIsEmpty : 1; - const uint8 bIsPolymorphic : 1; - const uint8 bIsAbstract : 1; - const uint8 bIsFinal : 1; - const uint8 bIsAggregate : 1; - const uint8 bIsSigned : 1; - const uint8 bIsUnsigned : 1; - const uint8 bIsBoundedArray : 1; - const uint8 bIsUnboundedArray : 1; - const uint8 bIsScopedEnum : 1; - - const uint8 bIsEqualityComparable : 1; - const uint8 bIsTotallyOrdered : 1; - const uint8 bIsThreeWayComparable : 1; - const uint8 bIsHashable : 1; - const uint8 bIsSwappable : 1; - - using FDefaultConstruct = void(*)(void* ); - using FCopyConstruct = void(*)(void*, const void*); - using FMoveConstruct = void(*)(void*, void*); - using FRelocateConstruct = void(*)(void*, void*); - using FCopyAssign = void(*)(void*, const void*); - using FMoveAssign = void(*)(void*, void*); - using FDestroy = void(*)(void* ); - - using FEqualityCompare = bool (*)(const void*, const void*); - using FSynthThreeWayCompare = partial_ordering (*)(const void*, const void*); - using FThreeWayCompare = partial_ordering (*)(const void*, const void*); - using FHashItem = size_t (*)(const void* ); - using FSwapItem = void (*)( void*, void*); - - const FDefaultConstruct DefaultConstructImpl; - const FCopyConstruct CopyConstructImpl; - const FMoveConstruct MoveConstructImpl; - const FRelocateConstruct RelocateConstructImpl; - const FCopyAssign CopyAssignImpl; - const FMoveAssign MoveAssignImpl; - const FDestroy DestroyImpl; - - const FEqualityCompare EqualityCompareImpl; - const FSynthThreeWayCompare SynthThreeWayCompareImpl; - const FThreeWayCompare ThreeWayCompareImpl; - const FHashItem HashItemImpl; - const FSwapItem SwapItemImpl; - - template - constexpr FTypeInfo(TInPlaceType) : Native(typeid(T)) - - , TypeSize (!TIsVoid::Value ? sizeof (typename TConditional::Value, int, T>::Type) : INDEX_NONE) - , TypeAlignment (!TIsVoid::Value ? alignof(typename TConditional::Value, int, T>::Type) : INDEX_NONE) - - , bIsZeroConstructible (TIsZeroConstructible::Value) - , bIsBitwiseConstructible (TIsBitwiseConstructible::Value) - , bIsBitwiseRelocatable (TIsBitwiseRelocatable::Value) - , bIsBitwiseComparable (TIsBitwiseComparable::Value) - - , bIsArithmetic (TIsArithmetic::Value) - , bIsFundamental (TIsFundamental::Value) - , bIsObject (TIsObject::Value) - , bIsScalar (TIsScalar::Value) - , bIsCompound (TIsCompound::Value) - , bIsMemberPointer (TIsMemberPointer::Value) - - , bIsVoid (TIsVoid::Value) - , bIsNullPointer (TIsNullPointer::Value) - , bIsIntegral (TIsIntegral::Value) - , bIsFloatingPoint (TIsFloatingPoint::Value) - , bIsArray (TIsArray::Value) - , bIsPointer (TIsPointer::Value) - , bIsMemberObjectPointer (TIsMemberObjectPointer::Value) - , bIsMemberFunctionPointer (TIsMemberFunctionPointer::Value) - , bIsEnum (TIsEnum::Value) - , bIsUnion (TIsUnion::Value) - , bIsClass (TIsClass::Value) - , bIsFunction (TIsFunction::Value) - - , bIsDefaultConstructible (TIsDefaultConstructible::Value) - , bIsCopyConstructible (TIsCopyConstructible::Value) - , bIsMoveConstructible (TIsMoveConstructible::Value) - , bIsCopyAssignable (TIsCopyAssignable::Value) - , bIsMoveAssignable (TIsMoveAssignable::Value) - , bIsDestructible (TIsDestructible::Value) - , bIsTriviallyDefaultConstructible (TIsTriviallyDefaultConstructible::Value) - , bIsTriviallyCopyConstructible (TIsTriviallyCopyConstructible::Value) - , bIsTriviallyMoveConstructible (TIsTriviallyMoveConstructible::Value) - , bIsTriviallyCopyAssignable (TIsTriviallyCopyAssignable::Value) - , bIsTriviallyMoveAssignable (TIsTriviallyMoveAssignable::Value) - , bIsTriviallyDestructible (TIsTriviallyDestructible::Value) - , bHasVirtualDestructor (THasVirtualDestructor::Value) - - , bIsTrivial (TIsTrivial::Value) - , bIsTriviallyCopyable (TIsTriviallyCopyable::Value) - , bIsStandardLayout (TIsStandardLayout::Value) - , bHasUniqueObjectRepresentations (THasUniqueObjectRepresentations::Value) - , bIsEmpty (TIsEmpty::Value) - , bIsPolymorphic (TIsPolymorphic::Value) - , bIsAbstract (TIsAbstract::Value) - , bIsFinal (TIsFinal::Value) - , bIsAggregate (TIsAggregate::Value) - , bIsSigned (TIsSigned::Value) - , bIsUnsigned (TIsUnsigned::Value) - , bIsBoundedArray (TIsBoundedArray::Value) - , bIsUnboundedArray (TIsUnboundedArray::Value) - , bIsScopedEnum (TIsScopedEnum::Value) - - , bIsEqualityComparable (CEqualityComparable) - , bIsTotallyOrdered (CTotallyOrdered) - , bIsThreeWayComparable (CThreeWayComparable) - , bIsHashable (CHashable) - , bIsSwappable (CSwappable) - - , DefaultConstructImpl ([](void* A ) -> void { if constexpr (requires(T* A ) { Memory::DefaultConstruct (A ); }) Memory::DefaultConstruct (reinterpret_cast(A) ); else check_no_entry(); }) - , CopyConstructImpl ([](void* A, const void* B) -> void { if constexpr (requires(T* A, const T* B) { Memory::CopyConstruct (A, B); }) Memory::CopyConstruct (reinterpret_cast(A), reinterpret_cast(B)); else check_no_entry(); }) - , MoveConstructImpl ([](void* A, void* B) -> void { if constexpr (requires(T* A, T* B) { Memory::MoveConstruct (A, B); }) Memory::MoveConstruct (reinterpret_cast(A), reinterpret_cast< T*>(B)); else check_no_entry(); }) - , RelocateConstructImpl ([](void* A, void* B) -> void { if constexpr (requires(T* A, T* B) { Memory::RelocateConstruct (A, B); }) Memory::RelocateConstruct (reinterpret_cast(A), reinterpret_cast< T*>(B)); else check_no_entry(); }) - , CopyAssignImpl ([](void* A, const void* B) -> void { if constexpr (requires(T* A, const T* B) { Memory::CopyAssign (A, B); }) Memory::CopyAssign (reinterpret_cast(A), reinterpret_cast(B)); else check_no_entry(); }) - , MoveAssignImpl ([](void* A, void* B) -> void { if constexpr (requires(T* A, T* B) { Memory::MoveAssign (A, B); }) Memory::MoveAssign (reinterpret_cast(A), reinterpret_cast< T*>(B)); else check_no_entry(); }) - , DestroyImpl ([](void* A ) -> void { if constexpr (requires(T* A ) { Memory::Destruct (A ); }) Memory::Destruct (reinterpret_cast(A) ); else check_no_entry(); }) - - , EqualityCompareImpl ([](const void* A, const void* B) -> bool { if constexpr (CEqualityComparable ) return (*reinterpret_cast(A) == *reinterpret_cast(B)); else return false; }) - , SynthThreeWayCompareImpl ([](const void* A, const void* B) -> partial_ordering { if constexpr (CSynthThreeWayComparable) return NAMESPACE_REDCRAFT::SynthThreeWayCompare (*reinterpret_cast(A), *reinterpret_cast(B)); else return partial_ordering::unordered; }) - , ThreeWayCompareImpl ([](const void* A, const void* B) -> partial_ordering { if constexpr (CThreeWayComparable ) return (*reinterpret_cast(A) <=> *reinterpret_cast(B)); else return partial_ordering::unordered; }) - , HashItemImpl ([](const void* A ) -> size_t { if constexpr (CHashable ) return NAMESPACE_REDCRAFT::GetTypeHash (*reinterpret_cast(A) ); else return 1080551797; }) - , SwapItemImpl ([]( void* A, void* B) -> void { if constexpr (CSwappable ) NAMESPACE_REDCRAFT::Swap (*reinterpret_cast< T*>(A), *reinterpret_cast< T*>(B)); else check_no_entry(); }) - - { } - - friend FORCEINLINE bool operator==(const FTypeInfo& LHS, const FTypeInfo& RHS) { return &LHS != &RHS ? LHS.GetNative() == RHS.GetNative() : true; } - friend FORCEINLINE bool operator< (const FTypeInfo& LHS, const FTypeInfo& RHS) { return LHS.GetNative().before(RHS.GetNative()); } - 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 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; - } - -public: - - friend NAMESPACE_PRIVATE::FTypeInfoStatic; - -}; - -// NOTE: Unlike the standard typeid, this version only supports type and not expression -#define Typeid(...) (NAMESPACE_PRIVATE::FTypeInfoStatic::Value::Type>) - -NAMESPACE_MODULE_END(Utility) -NAMESPACE_MODULE_END(Redcraft) -NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Templates/Any.h b/Redcraft.Utility/Source/Public/Templates/Any.h index fb7e625..be06850 100644 --- a/Redcraft.Utility/Source/Public/Templates/Any.h +++ b/Redcraft.Utility/Source/Public/Templates/Any.h @@ -5,8 +5,8 @@ #include "Memory/Alignment.h" #include "Templates/Utility.h" #include "Templates/TypeHash.h" +#include "Memory/MemoryOperator.h" #include "TypeTraits/TypeTraits.h" -#include "Miscellaneous/TypeInfo.h" #include "Miscellaneous/AssertionMacros.h" // NOTE: Disable alignment limit warning @@ -16,18 +16,6 @@ NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) -NAMESPACE_PRIVATE_BEGIN - -enum class EAnyRepresentation : uint8 -{ - Trivial, // Trivial -// Inline, // InlineAllocation - Small, // Trivial & Inline - Big, // HeapAllocation -}; - -NAMESPACE_PRIVATE_END - inline constexpr size_t ANY_DEFAULT_INLINE_SIZE = 64 - sizeof(uintptr); inline constexpr size_t ANY_DEFAULT_INLINE_ALIGNMENT = 16; @@ -45,15 +33,15 @@ struct alignas(InlineAlignment) TAny switch (GetRepresentation()) { - case NAMESPACE_PRIVATE::EAnyRepresentation::Trivial: + case EAnyRepresentation::Trivial: Memory::Memcpy(InlineAllocation, InValue.InlineAllocation); break; - case NAMESPACE_PRIVATE::EAnyRepresentation::Small: - GetTypeInfo().CopyConstruct(GetAllocation(), InValue.GetAllocation()); + case EAnyRepresentation::Small: + GetTypeInfoImpl().CopyConstructImpl(GetAllocation(), InValue.GetAllocation()); break; - case NAMESPACE_PRIVATE::EAnyRepresentation::Big: - HeapAllocation = Memory::Malloc(GetTypeInfo().GetTypeSize(), GetTypeInfo().GetTypeAlignment()); - GetTypeInfo().CopyConstruct(GetAllocation(), InValue.GetAllocation()); + case EAnyRepresentation::Big: + HeapAllocation = Memory::Malloc(GetTypeInfoImpl().TypeSize, GetTypeInfoImpl().TypeAlignment); + GetTypeInfoImpl().CopyConstructImpl(GetAllocation(), InValue.GetAllocation()); break; default: check_no_entry(); } @@ -66,13 +54,13 @@ struct alignas(InlineAlignment) TAny switch (GetRepresentation()) { - case NAMESPACE_PRIVATE::EAnyRepresentation::Trivial: + case EAnyRepresentation::Trivial: Memory::Memcpy(InlineAllocation, InValue.InlineAllocation); break; - case NAMESPACE_PRIVATE::EAnyRepresentation::Small: - GetTypeInfo().MoveConstruct(GetAllocation(), InValue.GetAllocation()); + case EAnyRepresentation::Small: + GetTypeInfoImpl().MoveConstructImpl(GetAllocation(), InValue.GetAllocation()); break; - case NAMESPACE_PRIVATE::EAnyRepresentation::Big: + case EAnyRepresentation::Big: HeapAllocation = InValue.HeapAllocation; InValue.TypeInfo = 0; break; @@ -112,12 +100,12 @@ struct alignas(InlineAlignment) TAny { switch (GetRepresentation()) { - case NAMESPACE_PRIVATE::EAnyRepresentation::Trivial: + case EAnyRepresentation::Trivial: Memory::Memcpy(InlineAllocation, InValue.InlineAllocation); break; - case NAMESPACE_PRIVATE::EAnyRepresentation::Small: - case NAMESPACE_PRIVATE::EAnyRepresentation::Big: - GetTypeInfo().CopyAssign(GetAllocation(), InValue.GetAllocation()); + case EAnyRepresentation::Small: + case EAnyRepresentation::Big: + GetTypeInfoImpl().CopyAssignImpl(GetAllocation(), InValue.GetAllocation()); break; default: check_no_entry(); } @@ -130,15 +118,15 @@ struct alignas(InlineAlignment) TAny switch (GetRepresentation()) { - case NAMESPACE_PRIVATE::EAnyRepresentation::Trivial: + case EAnyRepresentation::Trivial: Memory::Memcpy(InlineAllocation, InValue.InlineAllocation); break; - case NAMESPACE_PRIVATE::EAnyRepresentation::Small: - GetTypeInfo().CopyConstruct(GetAllocation(), InValue.GetAllocation()); + case EAnyRepresentation::Small: + GetTypeInfoImpl().CopyConstructImpl(GetAllocation(), InValue.GetAllocation()); break; - case NAMESPACE_PRIVATE::EAnyRepresentation::Big: - HeapAllocation = Memory::Malloc(GetTypeInfo().GetTypeSize(), GetTypeInfo().GetTypeAlignment()); - GetTypeInfo().CopyConstruct(GetAllocation(), InValue.GetAllocation()); + case EAnyRepresentation::Big: + HeapAllocation = Memory::Malloc(GetTypeInfoImpl().TypeSize, GetTypeInfoImpl().TypeAlignment); + GetTypeInfoImpl().CopyConstructImpl(GetAllocation(), InValue.GetAllocation()); break; default: check_no_entry(); } @@ -159,13 +147,13 @@ struct alignas(InlineAlignment) TAny { switch (GetRepresentation()) { - case NAMESPACE_PRIVATE::EAnyRepresentation::Trivial: + case EAnyRepresentation::Trivial: Memory::Memcpy(InlineAllocation, InValue.InlineAllocation); break; - case NAMESPACE_PRIVATE::EAnyRepresentation::Small: - GetTypeInfo().MoveAssign(GetAllocation(), InValue.GetAllocation()); + case EAnyRepresentation::Small: + GetTypeInfoImpl().MoveAssignImpl(GetAllocation(), InValue.GetAllocation()); break; - case NAMESPACE_PRIVATE::EAnyRepresentation::Big: + case EAnyRepresentation::Big: ResetImpl(); HeapAllocation = InValue.HeapAllocation; InValue.TypeInfo = 0; @@ -181,13 +169,13 @@ struct alignas(InlineAlignment) TAny switch (GetRepresentation()) { - case NAMESPACE_PRIVATE::EAnyRepresentation::Trivial: + case EAnyRepresentation::Trivial: Memory::Memcpy(InlineAllocation, InValue.InlineAllocation); break; - case NAMESPACE_PRIVATE::EAnyRepresentation::Small: - GetTypeInfo().MoveConstruct(GetAllocation(), InValue.GetAllocation()); + case EAnyRepresentation::Small: + GetTypeInfoImpl().MoveConstructImpl(GetAllocation(), InValue.GetAllocation()); break; - case NAMESPACE_PRIVATE::EAnyRepresentation::Big: + case EAnyRepresentation::Big: HeapAllocation = InValue.HeapAllocation; InValue.TypeInfo = 0; break; @@ -230,12 +218,12 @@ struct alignas(InlineAlignment) TAny return GetValue(); } - constexpr const FTypeInfo& GetTypeInfo() const { return IsValid() ? *reinterpret_cast(TypeInfo & ~RepresentationMask) : Typeid(void); } + constexpr const type_info& GetTypeInfo() const { return IsValid() ? *GetTypeInfoImpl().TypeInfo : typeid(void); } constexpr bool IsValid() const { return TypeInfo != 0; } constexpr explicit operator bool() const { return TypeInfo != 0; } - template constexpr bool HoldsAlternative() const { return IsValid() ? GetTypeInfo() == Typeid(T) : false; } + template constexpr bool HoldsAlternative() const { return IsValid() ? GetTypeInfo() == typeid(T) : false; } template requires TIsSame::Type>::Value && TIsObject::Type>::Value && (!TIsArray::Type>::Value) && TIsDestructible::Type>::Value constexpr T& GetValue() & { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast< T*>(GetAllocation()); } @@ -263,8 +251,9 @@ struct alignas(InlineAlignment) TAny FORCEINLINE size_t GetTypeHash() const { + using NAMESPACE_REDCRAFT::GetTypeHash; if (!IsValid()) return 20090007; - return HashCombine(GetTypeInfo().GetTypeHash(), GetTypeInfo().HashItem(GetAllocation())); + return HashCombine(GetTypeHash(GetTypeInfo()), GetTypeInfoImpl().HashImpl(GetAllocation())); } FORCEINLINE void Swap(TAny& InValue) @@ -287,7 +276,7 @@ struct alignas(InlineAlignment) TAny if (GetTypeInfo() == InValue.GetTypeInfo()) { - GetTypeInfo().SwapItem(GetAllocation(), InValue.GetAllocation()); + GetTypeInfoImpl().SwapImpl(GetAllocation(), InValue.GetAllocation()); return; } @@ -300,6 +289,64 @@ private: static constexpr uintptr_t RepresentationMask = 3; + enum class EAnyRepresentation : uint8 + { + Trivial, // Trivial + // Inline, // InlineAllocation + Small, // Trivial & Inline + Big, // HeapAllocation + }; + + struct FTypeInfoImpl + { + const type_info* TypeInfo; + + const size_t TypeSize; + const size_t TypeAlignment; + + using FCopyConstructImpl = void(*)(void*, const void*); + using FMoveConstructImpl = void(*)(void*, void*); + using FCopyAssignImpl = void(*)(void*, const void*); + using FMoveAssignImpl = void(*)(void*, void*); + using FDestroyImpl = void(*)(void* ); + + using FEqualityCompareImpl = bool (*)(const void*, const void*); + using FSynthThreeWayCompareImpl = partial_ordering (*)(const void*, const void*); + using FHashImpl = size_t (*)(const void* ); + using FSwapImpl = void (*)( void*, void*); + + const FCopyConstructImpl CopyConstructImpl; + const FMoveConstructImpl MoveConstructImpl; + const FCopyAssignImpl CopyAssignImpl; + const FMoveAssignImpl MoveAssignImpl; + const FDestroyImpl DestroyImpl; + + const FEqualityCompareImpl EqualityCompareImpl; + const FSynthThreeWayCompareImpl SynthThreeWayCompareImpl; + const FHashImpl HashImpl; + const FSwapImpl SwapImpl; + + template + constexpr FTypeInfoImpl(TInPlaceType) + + : TypeInfo (&typeid(T)) + , TypeSize ( sizeof(T)) + , TypeAlignment (alignof(T)) + + , CopyConstructImpl ([](void* A, const void* B) { if constexpr (requires(T* A, const T* B) { Memory::CopyConstruct (A, B); }) Memory::CopyConstruct (reinterpret_cast(A), reinterpret_cast(B)); else checkf(false, TEXT("The type '%s' is not copy constructible."), typeid(Types).name()); }) + , MoveConstructImpl ([](void* A, void* B) { if constexpr (requires(T* A, T* B) { Memory::MoveConstruct (A, B); }) Memory::MoveConstruct (reinterpret_cast(A), reinterpret_cast< T*>(B)); else checkf(false, TEXT("The type '%s' is not move constructible."), typeid(Types).name()); }) + , CopyAssignImpl ([](void* A, const void* B) { if constexpr (requires(T* A, const T* B) { Memory::CopyAssign (A, B); }) Memory::CopyAssign (reinterpret_cast(A), reinterpret_cast(B)); else checkf(false, TEXT("The type '%s' is not copy assignable."), typeid(Types).name()); }) + , MoveAssignImpl ([](void* A, void* B) { if constexpr (requires(T* A, T* B) { Memory::MoveAssign (A, B); }) Memory::MoveAssign (reinterpret_cast(A), reinterpret_cast< T*>(B)); else checkf(false, TEXT("The type '%s' is not move assignable."), typeid(Types).name()); }) + , DestroyImpl ([](void* A ) { if constexpr (requires(T* A ) { Memory::Destruct (A ); }) Memory::Destruct (reinterpret_cast(A) ); else checkf(false, TEXT("The type '%s' is not destructible."), typeid(Types).name()); }) + + , EqualityCompareImpl ([](const void* A, const void* B) -> bool { if constexpr (CEqualityComparable ) return (*reinterpret_cast(A) == *reinterpret_cast(B)); else checkf(false, TEXT("The type '%s' is not equality comparable."), typeid(T).name()); return false; }) + , SynthThreeWayCompareImpl ([](const void* A, const void* B) -> partial_ordering { if constexpr (CSynthThreeWayComparable) return NAMESPACE_REDCRAFT::SynthThreeWayCompare (*reinterpret_cast(A), *reinterpret_cast(B)); else checkf(false, TEXT("The type '%s' is not synth three-way comparable."), typeid(T).name()); return partial_ordering::unordered; }) + , HashImpl ([](const void* A ) -> size_t { if constexpr (CHashable ) return NAMESPACE_REDCRAFT::GetTypeHash (*reinterpret_cast(A) ); else checkf(false, TEXT("The type '%s' is not hashable."), typeid(T).name()); return 1080551797; }) + , SwapImpl ([]( void* A, void* B) -> void { if constexpr (CSwappable ) NAMESPACE_REDCRAFT::Swap (*reinterpret_cast< T*>(A), *reinterpret_cast< T*>(B)); else checkf(false, TEXT("The type '%s' is not swappable."), typeid(T).name()); }) + + { } + }; + union { TAlignedStorage::Type InlineAllocation; @@ -308,15 +355,17 @@ private: uintptr TypeInfo; - constexpr NAMESPACE_PRIVATE::EAnyRepresentation GetRepresentation() const { return static_cast(TypeInfo & RepresentationMask); } + constexpr EAnyRepresentation GetRepresentation() const { return static_cast(TypeInfo & RepresentationMask); } + constexpr const FTypeInfoImpl& GetTypeInfoImpl() const { return *reinterpret_cast(TypeInfo & ~RepresentationMask); } - constexpr void* GetAllocation() { return GetRepresentation() == NAMESPACE_PRIVATE::EAnyRepresentation::Trivial || GetRepresentation() == NAMESPACE_PRIVATE::EAnyRepresentation::Small ? &InlineAllocation : HeapAllocation; } - constexpr const void* GetAllocation() const { return GetRepresentation() == NAMESPACE_PRIVATE::EAnyRepresentation::Trivial || GetRepresentation() == NAMESPACE_PRIVATE::EAnyRepresentation::Small ? &InlineAllocation : HeapAllocation; } + constexpr void* GetAllocation() { return GetRepresentation() == EAnyRepresentation::Trivial || GetRepresentation() == EAnyRepresentation::Small ? &InlineAllocation : HeapAllocation; } + constexpr const void* GetAllocation() const { return GetRepresentation() == EAnyRepresentation::Trivial || GetRepresentation() == EAnyRepresentation::Small ? &InlineAllocation : HeapAllocation; } template FORCEINLINE void EmplaceImpl(Types&&... Args) { - TypeInfo = reinterpret_cast(&Typeid(SelectedType)); + static constexpr const FTypeInfoImpl SelectedTypeInfo(InPlaceType); + TypeInfo = reinterpret_cast(&SelectedTypeInfo); constexpr bool bIsInlineStorable = sizeof(SelectedType) <= InlineSize && alignof(SelectedType) <= InlineAlignment; constexpr bool bIsTriviallyStorable = bIsInlineStorable && TIsTrivial::Value && TIsTriviallyCopyable::Value; @@ -324,17 +373,17 @@ private: if constexpr (bIsTriviallyStorable) { new(&InlineAllocation) SelectedType(Forward(Args)...); - TypeInfo |= static_cast(NAMESPACE_PRIVATE::EAnyRepresentation::Trivial); + TypeInfo |= static_cast(EAnyRepresentation::Trivial); } else if constexpr (bIsInlineStorable) { new(&InlineAllocation) SelectedType(Forward(Args)...); - TypeInfo |= static_cast(NAMESPACE_PRIVATE::EAnyRepresentation::Small); + TypeInfo |= static_cast(EAnyRepresentation::Small); } else { HeapAllocation = new SelectedType(Forward(Args)...); - TypeInfo |= static_cast(NAMESPACE_PRIVATE::EAnyRepresentation::Big); + TypeInfo |= static_cast(EAnyRepresentation::Big); } } @@ -344,13 +393,13 @@ private: switch (GetRepresentation()) { - case NAMESPACE_PRIVATE::EAnyRepresentation::Trivial: + case EAnyRepresentation::Trivial: break; - case NAMESPACE_PRIVATE::EAnyRepresentation::Small: - GetTypeInfo().Destroy(GetAllocation()); + case EAnyRepresentation::Small: + GetTypeInfoImpl().DestroyImpl(GetAllocation()); break; - case NAMESPACE_PRIVATE::EAnyRepresentation::Big: - GetTypeInfo().Destroy(GetAllocation()); + case EAnyRepresentation::Big: + GetTypeInfoImpl().DestroyImpl(GetAllocation()); Memory::Free(HeapAllocation); break; default: check_no_entry(); @@ -361,14 +410,14 @@ private: { if (LHS.GetTypeInfo() != RHS.GetTypeInfo()) return false; if (LHS.IsValid() == false) return true; - return LHS.GetTypeInfo().EqualityCompare(LHS.GetAllocation(), RHS.GetAllocation()); + return LHS.GetTypeInfoImpl().EqualityCompareImpl(LHS.GetAllocation(), RHS.GetAllocation()); } friend FORCEINLINE partial_ordering operator<=>(const TAny& LHS, const TAny& RHS) { if (LHS.GetTypeInfo() != RHS.GetTypeInfo()) return partial_ordering::unordered; if (LHS.IsValid() == false) return partial_ordering::equivalent; - return LHS.GetTypeInfo().SynthThreeWayCompare(LHS.GetAllocation(), RHS.GetAllocation());; + return LHS.GetTypeInfoImpl().SynthThreeWayCompareImpl(LHS.GetAllocation(), RHS.GetAllocation());; } }; diff --git a/Redcraft.Utility/Source/Public/Templates/TypeHash.h b/Redcraft.Utility/Source/Public/Templates/TypeHash.h index 4077bc9..cb93e24 100644 --- a/Redcraft.Utility/Source/Public/Templates/TypeHash.h +++ b/Redcraft.Utility/Source/Public/Templates/TypeHash.h @@ -93,6 +93,12 @@ constexpr size_t GetTypeHash(const T& A) return GetTypeHash(A.GetTypeHash()); } +template requires requires(const T& A) { { GetTypeHash(A.hash_code()) } -> CSameAs; } +constexpr size_t GetTypeHash(const T& A) +{ + return GetTypeHash(A.hash_code()); +} + template concept CHashable = requires(const T& A) { { GetTypeHash(A) } -> CSameAs; }; diff --git a/Redcraft.Utility/Source/Public/Templates/Variant.h b/Redcraft.Utility/Source/Public/Templates/Variant.h index efd71ad..af47adf 100644 --- a/Redcraft.Utility/Source/Public/Templates/Variant.h +++ b/Redcraft.Utility/Source/Public/Templates/Variant.h @@ -5,8 +5,8 @@ #include "Templates/Utility.h" #include "Templates/TypeHash.h" #include "TypeTraits/TypeTraits.h" +#include "Memory/MemoryOperator.h" #include "Miscellaneous/Compare.h" -#include "Miscellaneous/TypeInfo.h" #include "Miscellaneous/AssertionMacros.h" NAMESPACE_REDCRAFT_BEGIN @@ -76,55 +76,6 @@ struct TVariantSelectedType using Type = void; }; -template -constexpr R VariantVisitLValue(F&& Func, void* Arg) -{ - if constexpr(TIsVoid::Value) Invoke(Forward(Func), *reinterpret_cast(Arg)); - else return InvokeResult(Forward(Func), *reinterpret_cast(Arg)); -} - -template -using FVariantVisitLValueFunc = R(*)(F&&, void*); - -template -constexpr R VariantVisitRValue(F&& Func, void* Arg) -{ - if constexpr (TIsVoid::Value) Invoke(Forward(Func), MoveTemp(*reinterpret_cast(Arg))); - else return InvokeResult(Forward(Func), MoveTemp(*reinterpret_cast(Arg))); -} - -template -using FVariantVisitRValueFunc = R(*)(F&&, void*); - -template -constexpr R VariantVisitConstLValue(F&& Func, const void* Arg) -{ - if constexpr (TIsVoid::Value) Invoke(Forward(Func), *reinterpret_cast(Arg)); - else return InvokeResult(Forward(Func), *reinterpret_cast(Arg)); -} - -template -using FVariantVisitConstLValueFunc = R(*)(F&&, const void*); - -template -constexpr R VariantVisitConstRValue(F&& Func, const void* Arg) -{ - if constexpr (TIsVoid::Value) Invoke(Forward(Func), MoveTemp(*reinterpret_cast(Arg))); - else return InvokeResult(Forward(Func), MoveTemp(*reinterpret_cast(Arg))); -} - -template -using FVariantVisitConstRValueFunc = R(*)(F&&, const void*); - -template -struct TVariantVisitHelper -{ - static constexpr FVariantVisitLValueFunc VisitLValueFuncs[] = { VariantVisitLValue... }; - static constexpr FVariantVisitRValueFunc VisitRValueFuncs[] = { VariantVisitRValue... }; - static constexpr FVariantVisitConstLValueFunc VisitConstLValueFuncs[] = { VariantVisitConstLValue... }; - static constexpr FVariantVisitConstRValueFunc VisitConstRValueFuncs[] = { VariantVisitConstRValue... }; -}; - NAMESPACE_PRIVATE_END template requires (true && ... && (TIsObject::Value && !TIsArray::Value && TIsDestructible::Value)) && (sizeof...(Types) < 0xFF) @@ -142,13 +93,13 @@ struct TVariant constexpr TVariant(const TVariant& InValue) requires (true && ... && TIsCopyConstructible::Value) : TypeIndex(static_cast(InValue.GetIndex())) { - if (IsValid()) TypeInfos[InValue.GetIndex()]->CopyConstruct(&Value, &InValue.Value); + if (IsValid()) CopyConstructImpl[InValue.GetIndex()](&Value, &InValue.Value); } constexpr TVariant(TVariant&& InValue) requires (true && ... && TIsMoveConstructible::Value) : TypeIndex(static_cast(InValue.GetIndex())) { - if (IsValid()) TypeInfos[InValue.GetIndex()]->MoveConstruct(&Value, &InValue.Value); + if (IsValid()) MoveConstructImpl[InValue.GetIndex()](&Value, &InValue.Value); } template requires (I < AlternativeSize) @@ -187,11 +138,11 @@ struct TVariant return *this; } - if (GetIndex() == InValue.GetIndex()) TypeInfos[InValue.GetIndex()]->CopyAssign(&Value, &InValue.Value); + if (GetIndex() == InValue.GetIndex()) CopyAssignImpl[InValue.GetIndex()](&Value, &InValue.Value); else { Reset(); - TypeInfos[InValue.GetIndex()]->CopyConstruct(&Value, &InValue.Value); + CopyConstructImpl[InValue.GetIndex()](&Value, &InValue.Value); TypeIndex = static_cast(InValue.GetIndex()); } @@ -208,11 +159,11 @@ struct TVariant return *this; } - if (GetIndex() == InValue.GetIndex()) TypeInfos[InValue.GetIndex()]->MoveAssign(&Value, &InValue.Value); + if (GetIndex() == InValue.GetIndex()) MoveAssignImpl[InValue.GetIndex()](&Value, &InValue.Value); else { Reset(); - TypeInfos[InValue.GetIndex()]->MoveConstruct(&Value, &InValue.Value); + MoveConstructImpl[InValue.GetIndex()](&Value, &InValue.Value); TypeIndex = static_cast(InValue.GetIndex()); } @@ -255,7 +206,7 @@ struct TVariant return Emplace::Value>(Forward(Args)...); } - constexpr const FTypeInfo& GetTypeInfo() const { return IsValid() ? *TypeInfos[GetIndex()] : Typeid(void); } + constexpr const type_info& GetTypeInfo() const { return IsValid() ? *TypeInfos[GetIndex()] : typeid(void); } constexpr size_t GetIndex() const { return TypeIndex != 0xFF ? TypeIndex : INDEX_NONE; } constexpr bool IsValid() const { return TypeIndex != 0xFF; } @@ -281,64 +232,68 @@ struct TVariant template requires (TAlternativeIndex::Value != INDEX_NONE) constexpr const T& Get(const T& DefaultValue) const& { return HoldsAlternative() ? GetValue() : DefaultValue; } template requires (true && ... && TIsInvocable::Value) - constexpr auto Visit(F&& Func) & + FORCEINLINE decltype(auto) Visit(F&& Func) & { - using ReturnType = typename TCommonType::Type...>::Type; checkf(IsValid(), TEXT("It is an error to call Visit() on an wrong TVariant. Please either check IsValid().")); - return ReturnType(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitLValueFuncs[GetIndex()](Forward(Func), &Value)); + + using ReturnType = typename TCommonType::Type...>::Type; + + using FInvokeImpl = ReturnType(*)(F&&, void*); + static constexpr FInvokeImpl InvokeImpl[] = { [](F&& Func, void* This) -> ReturnType { return InvokeResult(Forward(Func), *reinterpret_cast(This)); }... }; + + return InvokeImpl[GetIndex()](Forward(Func), &Value); } template requires (true && ... && TIsInvocable::Value) - constexpr auto Visit(F&& Func) && + FORCEINLINE decltype(auto) Visit(F&& Func) && { - using ReturnType = typename TCommonType::Type...>::Type; checkf(IsValid(), TEXT("It is an error to call Visit() on an wrong TVariant. Please either check IsValid().")); - return ReturnType(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitRValueFuncs[GetIndex()](Forward(Func), &Value)); + + using ReturnType = typename TCommonType::Type...>::Type; + + using FInvokeImpl = ReturnType(*)(F&&, void*); + static constexpr FInvokeImpl InvokeImpl[] = { [](F&& Func, void* This) -> ReturnType { return InvokeResult(Forward(Func), MoveTemp(*reinterpret_cast(This))); }... }; + + return InvokeImpl[GetIndex()](Forward(Func), &Value); } template requires (true && ... && TIsInvocable::Value) - constexpr auto Visit(F&& Func) const& + FORCEINLINE decltype(auto) Visit(F&& Func) const& { - using ReturnType = typename TCommonType::Type...>::Type; checkf(IsValid(), TEXT("It is an error to call Visit() on an wrong TVariant. Please either check IsValid().")); - return ReturnType(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitConstLValueFuncs[GetIndex()](Forward(Func), &Value)); + + using ReturnType = typename TCommonType::Type...>::Type; + + using FInvokeImpl = ReturnType(*)(F&&, const void*); + static constexpr FInvokeImpl InvokeImpl[] = { [](F&& Func, const void* This) -> ReturnType { return InvokeResult(Forward(Func), *reinterpret_cast(This)); }... }; + + return InvokeImpl[GetIndex()](Forward(Func), &Value); } template requires (true && ... && TIsInvocable::Value) - constexpr auto Visit(F&& Func) const&& + FORCEINLINE decltype(auto) Visit(F&& Func) const&& { + checkf(IsValid(), TEXT("It is an error to call Visit() on an wrong TVariant. Please either check IsValid().")); + using ReturnType = typename TCommonType::Type...>::Type; - checkf(IsValid(), TEXT("It is an error to call Visit() on an wrong TVariant. Please either check IsValid().")); - return ReturnType(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitConstRValueFuncs[GetIndex()](Forward(Func), &Value)); + + using FInvokeImpl = ReturnType(*)(F&&, const void*); + static constexpr FInvokeImpl InvokeImpl[] = { [](F&& Func, const void* This) -> ReturnType { return InvokeResult(Forward(Func), MoveTemp(*reinterpret_cast(This))); }... }; + + return InvokeImpl[GetIndex()](Forward(Func), &Value); } template requires (true && ... && TIsInvocableResult::Value) - constexpr R Visit(F&& Func) & - { - checkf(IsValid(), TEXT("It is an error to call Visit() on an wrong TVariant. Please either check IsValid().")); - return R(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitLValueFuncs[GetIndex()](Forward(Func), &Value)); - } + FORCEINLINE R Visit(F&& Func) & { return Visit(Forward(Func)); } template requires (true && ... && TIsInvocableResult::Value) - constexpr R Visit(F&& Func) && - { - checkf(IsValid(), TEXT("It is an error to call Visit() on an wrong TVariant. Please either check IsValid().")); - return R(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitRValueFuncs[GetIndex()](Forward(Func), &Value)); - } + FORCEINLINE R Visit(F&& Func) && { return MoveTemp(*this).Visit(Forward(Func)); } template requires (true && ... && TIsInvocableResult::Value) - constexpr R Visit(F&& Func) const& - { - checkf(IsValid(), TEXT("It is an error to call Visit() on an wrong TVariant. Please either check IsValid().")); - return R(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitConstLValueFuncs[GetIndex()](Forward(Func), &Value)); - } + FORCEINLINE R Visit(F&& Func) const& { return Visit(Forward(Func)); } template requires (true && ... && TIsInvocableResult::Value) - constexpr R Visit(F&& Func) const&& - { - checkf(IsValid(), TEXT("It is an error to call Visit() on an wrong TVariant. Please either check IsValid().")); - return R(NAMESPACE_PRIVATE::TVariantVisitHelper::VisitConstRValueFuncs[GetIndex()](Forward(Func), &Value)); - } + FORCEINLINE R Visit(F&& Func) const&& { return MoveTemp(*this).Visit(Forward(Func)); } constexpr void Reset() { @@ -346,7 +301,7 @@ struct TVariant if constexpr (!(true && ... && TIsTriviallyDestructible::Value)) { - TypeInfos[GetIndex()]->Destroy(&Value); + DestroyImpl[GetIndex()](&Value); } TypeIndex = static_cast(INDEX_NONE); @@ -355,7 +310,13 @@ struct TVariant constexpr size_t GetTypeHash() const requires (true && ... && CHashable) { if (!IsValid()) return 114514; - return HashCombine(NAMESPACE_REDCRAFT::GetTypeHash(GetIndex()), TypeInfos[GetIndex()]->HashItem(&Value)); + + using NAMESPACE_REDCRAFT::GetTypeHash; + + using FHashImpl = size_t(*)(const void*); + constexpr FHashImpl HashImpl[] = { [](const void* This) -> size_t { return GetTypeHash(*reinterpret_cast(This)); }... }; + + return HashCombine(GetTypeHash(GetIndex()), HashImpl[GetIndex()](&Value)); } constexpr void Swap(TVariant& InValue) requires (true && ... && (TIsMoveConstructible::Value && TIsSwappable::Value)) @@ -378,7 +339,13 @@ struct TVariant if (GetIndex() == InValue.GetIndex()) { - TypeInfos[GetIndex()]->SwapItem(&Value, &InValue.Value); + using NAMESPACE_REDCRAFT::Swap; + + using FSwapImpl = void(*)(void*, void*); + constexpr FSwapImpl SwapImpl[] = { [](void* A, void* B) { Swap(*reinterpret_cast(A), *reinterpret_cast(B)); }... }; + + SwapImpl[GetIndex()](&Value, &InValue.Value); + return; } @@ -389,7 +356,19 @@ struct TVariant private: - static constexpr const FTypeInfo* TypeInfos[] = { &Typeid(Types)... }; + static constexpr const type_info* TypeInfos[] = { &typeid(Types)... }; + + using FCopyConstructImpl = void(*)(void*, const void*); + using FMoveConstructImpl = void(*)(void*, void*); + using FCopyAssignImpl = void(*)(void*, const void*); + using FMoveAssignImpl = void(*)(void*, void*); + using FDestroyImpl = void(*)(void* ); + + static constexpr FCopyConstructImpl CopyConstructImpl[] = { [](void* A, const void* B) { if constexpr (requires(Types* A, const Types* B) { Memory::CopyConstruct (A, B); }) Memory::CopyConstruct (reinterpret_cast(A), reinterpret_cast(B)); else checkf(false, TEXT("The type '%s' is not copy constructible."), typeid(Types).name()); }... }; + static constexpr FMoveConstructImpl MoveConstructImpl[] = { [](void* A, void* B) { if constexpr (requires(Types* A, Types* B) { Memory::MoveConstruct (A, B); }) Memory::MoveConstruct (reinterpret_cast(A), reinterpret_cast< Types*>(B)); else checkf(false, TEXT("The type '%s' is not move constructible."), typeid(Types).name()); }... }; + static constexpr FCopyAssignImpl CopyAssignImpl[] = { [](void* A, const void* B) { if constexpr (requires(Types* A, const Types* B) { Memory::CopyAssign (A, B); }) Memory::CopyAssign (reinterpret_cast(A), reinterpret_cast(B)); else checkf(false, TEXT("The type '%s' is not copy assignable."), typeid(Types).name()); }... }; + static constexpr FMoveAssignImpl MoveAssignImpl[] = { [](void* A, void* B) { if constexpr (requires(Types* A, Types* B) { Memory::MoveAssign (A, B); }) Memory::MoveAssign (reinterpret_cast(A), reinterpret_cast< Types*>(B)); else checkf(false, TEXT("The type '%s' is not move assignable."), typeid(Types).name()); }... }; + static constexpr FDestroyImpl DestroyImpl[] = { [](void* A ) { if constexpr (requires(Types* A ) { Memory::Destruct (A ); }) Memory::Destruct (reinterpret_cast(A) ); else checkf(false, TEXT("The type '%s' is not destructible."), typeid(Types).name()); }... }; TAlignedUnion<1, Types...>::Type Value; uint8 TypeIndex; @@ -398,14 +377,22 @@ private: { if (LHS.GetIndex() != RHS.GetIndex()) return false; if (LHS.IsValid() == false) return true; - return TypeInfos[LHS.GetIndex()]->EqualityCompare(&LHS.Value, &RHS.Value); + + using FCompareImpl = bool(*)(const void*, const void*); + constexpr FCompareImpl CompareImpl[] = { [](const void* LHS, const void* RHS) -> bool { return *reinterpret_cast(LHS) == *reinterpret_cast(RHS); }... }; + + return CompareImpl[LHS.GetIndex()](&LHS.Value, &RHS.Value); } friend constexpr partial_ordering operator<=>(const TVariant& LHS, const TVariant& RHS) requires (true && ... && CSynthThreeWayComparable) { if (LHS.GetIndex() != RHS.GetIndex()) return partial_ordering::unordered; if (LHS.IsValid() == false) return partial_ordering::equivalent; - return TypeInfos[LHS.GetIndex()]->SynthThreeWayCompare(&LHS.Value, &RHS.Value); + + using FCompareImpl = partial_ordering(*)(const void*, const void*); + constexpr FCompareImpl CompareImpl[] = { [](const void* LHS, const void* RHS) -> partial_ordering { return SynthThreeWayCompare(*reinterpret_cast(LHS), *reinterpret_cast(RHS)); }...}; + + return CompareImpl[LHS.GetIndex()](&LHS.Value, &RHS.Value); } }; diff --git a/Redcraft.Utility/Source/Public/Testing/MiscellaneousTesting.h b/Redcraft.Utility/Source/Public/Testing/MiscellaneousTesting.h index f4ea2da..a11c3b4 100644 --- a/Redcraft.Utility/Source/Public/Testing/MiscellaneousTesting.h +++ b/Redcraft.Utility/Source/Public/Testing/MiscellaneousTesting.h @@ -11,7 +11,6 @@ NAMESPACE_BEGIN(Testing) REDCRAFTUTILITY_API void TestMiscellaneous(); REDCRAFTUTILITY_API void TestAssertionMacros(); REDCRAFTUTILITY_API void TestCompare(); -REDCRAFTUTILITY_API void TestTypeInfo(); NAMESPACE_END(Testing) diff --git a/Redcraft.Utility/Source/Public/TypeTraits/BitwiseOperations.h b/Redcraft.Utility/Source/Public/TypeTraits/BitwiseOperations.h index a087239..3583801 100644 --- a/Redcraft.Utility/Source/Public/TypeTraits/BitwiseOperations.h +++ b/Redcraft.Utility/Source/Public/TypeTraits/BitwiseOperations.h @@ -14,8 +14,8 @@ NAMESPACE_MODULE_BEGIN(Utility) // Assume that all operands of bitwise operations have the same size // This type traits is allowed to be specialised. -template struct TIsZeroConstructible : TBoolConstant::Value || TIsArithmetic::Value || TIsPointer::Value> { }; - +template struct TIsZeroConstructible : TBoolConstant::Value && (TIsEnum::Value || TIsArithmetic::Value || TIsPointer::Value)> { }; + // This type traits is allowed to be specialised. template struct TIsBitwiseConstructible; @@ -48,11 +48,6 @@ template <> struct TIsBitwiseConstructible< int32, uint32> : FTrue { }; template <> struct TIsBitwiseConstructible : FTrue { }; template <> struct TIsBitwiseConstructible< int64, uint64> : FTrue { }; -template struct TIsBitwiseConstructible : FTrue { }; -template struct TIsBitwiseConstructible : FTrue { }; -template struct TIsBitwiseConstructible< intptr, T*> : FTrue { }; -template struct TIsBitwiseConstructible : FTrue { }; - // It is usually only necessary to specialize TIsBitwiseConstructible and not recommended to specialize TIsBitwiseRelocatable. template struct TIsBitwiseRelocatable; @@ -72,7 +67,7 @@ template struct TIsBitwiseRelocatable struct TIsBitwiseRelocatable : TIsBitwiseRelocatable { }; template struct TIsBitwiseRelocatable : TIsBitwiseRelocatable { }; -template struct TIsBitwiseRelocatable : TBoolConstant::Value> { }; +template struct TIsBitwiseRelocatable : TBoolConstant::Value> { }; template struct TIsBitwiseRelocatable : TBoolConstant::Value && TIsTriviallyDestructible::Value> { };