From 59d3a9eac20cc25093c2073ec586bff716d616a0 Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Sat, 30 Apr 2022 23:03:29 +0800 Subject: [PATCH] feat(miscellaneous): add type traits and memory operations support to FTypeInfo --- .../Source/Public/Miscellaneous/TypeInfo.h | 286 +++++++++++++++++- 1 file changed, 281 insertions(+), 5 deletions(-) diff --git a/Redcraft.Utility/Source/Public/Miscellaneous/TypeInfo.h b/Redcraft.Utility/Source/Public/Miscellaneous/TypeInfo.h index 3497fdb..0689b30 100644 --- a/Redcraft.Utility/Source/Public/Miscellaneous/TypeInfo.h +++ b/Redcraft.Utility/Source/Public/Miscellaneous/TypeInfo.h @@ -1,7 +1,12 @@ #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 @@ -9,6 +14,18 @@ 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; @@ -17,13 +34,267 @@ struct FTypeInfo FTypeInfo& operator=(FTypeInfo&&) = delete; FTypeInfo& operator=(const FTypeInfo&) = delete; - FORCEINLINE size_t GetTypeHash() const { return reinterpret_cast(this)->hash_code(); } - FORCEINLINE const char* GetName() const { return reinterpret_cast(this)->name(); } + 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: - 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)); } + 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); } @@ -34,9 +305,14 @@ private: return LHS < RHS ? strong_ordering::less : strong_ordering::greater; } +public: + + friend NAMESPACE_PRIVATE::FTypeInfoStatic; + }; -#define Typeid(...) (*reinterpret_cast(&typeid(__VA_ARGS__))) +// 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)