diff --git a/Redcraft.Utility/Source/Public/Templates/Any.h b/Redcraft.Utility/Source/Public/Templates/Any.h index 4d56346..cf0f37e 100644 --- a/Redcraft.Utility/Source/Public/Templates/Any.h +++ b/Redcraft.Utility/Source/Public/Templates/Any.h @@ -3,6 +3,7 @@ #include "CoreTypes.h" #include "Memory/Memory.h" #include "Templates/Utility.h" +#include "Templates/TypeHash.h" #include "TypeTraits/TypeTraits.h" #include "Miscellaneous/TypeInfo.h" #include "Miscellaneous/AssertionMacros.h" @@ -91,14 +92,33 @@ void AnyMoveAssign(void* Target, void* Source) using FAnyMoveAssignFunc = void(*)(void*, void*); -template <typename T> -void AnySwap(void* A, void* B) -{ - if constexpr (TIsSwappable<T>::Value) Swap(*reinterpret_cast<T*>(A), *reinterpret_cast<T*>(B)); - else check_no_entry(); -} - -using FAnySwapFunc = void(*)(void*, void*); +//template <typename T> +//constexpr bool AnyEqualityOperator(const void* LHS, const void* RHS) +//{ +// if constexpr (!CEqualityComparable<T>) check_no_entry(); +// else return *reinterpret_cast<const T*>(LHS) == *reinterpret_cast<const T*>(RHS); +// return false; +//} +// +//using FAnyEqualityOperatorFunc = bool(*)(const void*, const void*); +// +//template <typename T> +//void AnySwap(void* A, void* B) +//{ +// if constexpr (TIsSwappable<T>::Value) Swap(*reinterpret_cast<T*>(A), *reinterpret_cast<T*>(B)); +// else check_no_entry(); +//} +// +//using FAnySwapFunc = void(*)(void*, void*); +// +//template <typename T> +//size_t AnyTypeHash(const void* InValue) +//{ +// if constexpr (CHashable<T>) return GetTypeHash(*reinterpret_cast<const T*>(InValue)); +// else return 3516520171; +//} +// +//using FAnyTypeHashFunc = size_t(*)(const void*); struct FAnyRTTI { @@ -111,7 +131,9 @@ struct FAnyRTTI FAnyMoveConstructFunc MoveConstruct; FAnyCopyAssignFunc CopyAssign; FAnyMoveAssignFunc MoveAssign; - FAnySwapFunc SwapObject; +// FAnyEqualityOperatorFunc EqualityOperator; +// FAnySwapFunc SwapObject; +// FAnyTypeHashFunc TypeHash; }; template <typename T, bool bInIsInline> @@ -128,7 +150,9 @@ struct TAnyRTTIHelper AnyMoveConstruct<T>, AnyCopyAssign<T>, AnyMoveAssign<T>, - AnySwap<T>, +// AnyEqualityOperator<T>, +// AnySwap<T>, +// AnyTypeHash<T>, }; }; @@ -326,34 +350,40 @@ struct TAny ResetImpl(); } - constexpr void Swap(TAny& InValue) - { - if (!IsValid() && !InValue.IsValid()) return; - - if (IsValid() && !InValue.IsValid()) - { - InValue = MoveTemp(*this); - Reset(); - return; - } - - if (InValue.IsValid() && !IsValid()) - { - *this = MoveTemp(InValue); - InValue.Reset(); - return; - } - - if (GetTypeInfo() == InValue.GetTypeInfo()) - { - RTTI->SwapObject(GetData(), InValue.GetData()); - return; - } - - TAny Temp = MoveTemp(*this); - *this = MoveTemp(InValue); - InValue = MoveTemp(Temp); - } +// constexpr size_t GetTypeHash() const +// { +// if (!IsValid()) return 20090007; +// return HashCombine(NAMESPACE_REDCRAFT::GetTypeHash(GetTypeInfo()), RTTI->TypeHash(GetData())); +// } +// +// constexpr void Swap(TAny& InValue) +// { +// if (!IsValid() && !InValue.IsValid()) return; +// +// if (IsValid() && !InValue.IsValid()) +// { +// InValue = MoveTemp(*this); +// Reset(); +// return; +// } +// +// if (InValue.IsValid() && !IsValid()) +// { +// *this = MoveTemp(InValue); +// InValue.Reset(); +// return; +// } +// +// if (GetTypeInfo() == InValue.GetTypeInfo()) +// { +// RTTI->SwapObject(GetData(), InValue.GetData()); +// return; +// } +// +// TAny Temp = MoveTemp(*this); +// *this = MoveTemp(InValue); +// InValue = MoveTemp(Temp); +// } private: @@ -395,6 +425,13 @@ private: else RTTI->Delete(DynamicValue); } +// friend FORCEINLINE bool operator==(const TAny& LHS, const TAny& RHS) +// { +// if (LHS.GetTypeInfo() != RHS.GetTypeInfo()) return false; +// if (LHS.IsValid() == false) return true; +// return LHS.RTTI->EqualityOperator(LHS.GetData(), RHS.GetData()); +// } + }; template <typename T, size_t InlineSize, size_t InlineAlignment> diff --git a/Redcraft.Utility/Source/Public/Templates/Function.h b/Redcraft.Utility/Source/Public/Templates/Function.h index f1461f2..8647c48 100644 --- a/Redcraft.Utility/Source/Public/Templates/Function.h +++ b/Redcraft.Utility/Source/Public/Templates/Function.h @@ -7,6 +7,7 @@ #include "Templates/Tuple.h" #include "Templates/Invoke.h" #include "Templates/Utility.h" +#include "Templates/TypeHash.h" #include "Templates/Container.h" #include "Concepts/Comparable.h" #include "Concepts/Convertible.h" @@ -434,7 +435,6 @@ constexpr bool operator==(const TUniqueFunction<F>& LHS, nullptr_t) return !LHS; } -static_assert(sizeof(TFunctionRef<void()>) == 16, "The byte size of TFunctionRef is unexpected"); static_assert(sizeof(TFunction<void()>) == 64, "The byte size of TFunction is unexpected"); static_assert(sizeof(TUniqueFunction<void()>) == 64, "The byte size of TUniqueFunction is unexpected"); diff --git a/Redcraft.Utility/Source/Public/Templates/Optional.h b/Redcraft.Utility/Source/Public/Templates/Optional.h index 5f7d901..f235a61 100644 --- a/Redcraft.Utility/Source/Public/Templates/Optional.h +++ b/Redcraft.Utility/Source/Public/Templates/Optional.h @@ -208,12 +208,6 @@ public: constexpr OptionalType& Get( OptionalType& DefaultValue) & { return IsValid() ? GetValue() : DefaultValue; } constexpr const OptionalType& Get(const OptionalType& DefaultValue) const& { return IsValid() ? GetValue() : DefaultValue; } - constexpr size_t GetTypeHash() const requires CHashable<OptionalType> - { - if (!IsValid()) return NAMESPACE_REDCRAFT::GetTypeHash(nullptr); - return NAMESPACE_REDCRAFT::GetTypeHash(GetValue()); - } - constexpr void Reset() { if (bIsValid) @@ -225,6 +219,12 @@ public: } } + constexpr size_t GetTypeHash() const requires CHashable<OptionalType> + { + if (!IsValid()) return 2824517378; + return NAMESPACE_REDCRAFT::GetTypeHash(GetValue()); + } + template <typename T> requires TIsMoveConstructible<OptionalType>::Value && TIsSwappable<OptionalType>::Value constexpr void Swap(TOptional& InValue) { diff --git a/Redcraft.Utility/Source/Public/Templates/Tuple.h b/Redcraft.Utility/Source/Public/Templates/Tuple.h index 62a6b55..36a582d 100644 --- a/Redcraft.Utility/Source/Public/Templates/Tuple.h +++ b/Redcraft.Utility/Source/Public/Templates/Tuple.h @@ -1,12 +1,12 @@ #pragma once #include "CoreTypes.h" +#include "Templates/Invoke.h" #include "Templates/Utility.h" #include "Templates/TypeHash.h" #include "TypeTraits/TypeTraits.h" #include "Templates/IntegerSequence.h" #include "Templates/ReferenceWrapper.h" -#include "Templates/Invoke.h" #include <tuple> @@ -373,8 +373,11 @@ public: template <typename T> requires TIsConstructible<T, Types...>::Value constexpr T Construct() const && { return Super::template Construct<T>(static_cast<const TTuple&&>(*this)); } template <typename T> requires TIsConstructible<T, Types...>::Value constexpr T Construct() volatile&& { return Super::template Construct<T>(static_cast< volatile TTuple&&>(*this)); } template <typename T> requires TIsConstructible<T, Types...>::Value constexpr T Construct() const volatile&& { return Super::template Construct<T>(static_cast<const volatile TTuple&&>(*this)); } - - constexpr size_t GetTypeHash() const requires (true && ... && CHashable<Types>); + + constexpr size_t GetTypeHash() const requires (true && ... && CHashable<Types>) + { + return [this]<size_t... Indices>(TIndexSequence<Indices...>) -> size_t { return HashCombine(NAMESPACE_REDCRAFT::GetTypeHash(GetValue<Indices>())...); } (TMakeIndexSequence<ElementSize>()); + } constexpr void Swap(TTuple& InValue) requires (true && ... && (TIsMoveConstructible<Types>::Value&& TIsSwappable<Types>::Value)) { @@ -584,14 +587,6 @@ constexpr void VisitTuple(F&& Func, FirstTupleType&& FirstTuple, TupleTypes&&... NAMESPACE_PRIVATE::TTupleVisitImpl<TMakeIndexSequence<TTupleElementSize<FirstTupleType>::Value>>::F(Forward<F>(Func), Forward<FirstTupleType>(FirstTuple), Forward<TupleTypes>(Tuples)...); } -template <typename... Types> -constexpr size_t TTuple<Types...>::GetTypeHash() const requires (true && ... && CHashable<Types>) -{ - size_t Result = 0; - VisitTuple([&Result](auto&& A) { Result = HashCombine(Result, NAMESPACE_REDCRAFT::GetTypeHash(A)); }, *this); - return Result; -} - NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Templates/TypeHash.h b/Redcraft.Utility/Source/Public/Templates/TypeHash.h index f017369..4077bc9 100644 --- a/Redcraft.Utility/Source/Public/Templates/TypeHash.h +++ b/Redcraft.Utility/Source/Public/Templates/TypeHash.h @@ -2,6 +2,7 @@ #include "CoreTypes.h" #include "Concepts/Same.h" +#include "Templates/Utility.h" #include "TypeTraits/PrimaryType.h" #include "TypeTraits/Miscellaneous.h" @@ -9,9 +10,21 @@ NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) +constexpr size_t HashCombine() +{ + return 0; +} + +constexpr size_t HashCombine(size_t A) +{ + return A; +} + constexpr size_t HashCombine(size_t A, size_t C) { - size_t B = 0x9E3779B97F4A7C16; + + size_t B = static_cast<size_t>(0x9E3779B97F4A7C16); + A += B; A -= B; A -= C; A ^= (C >> 13); @@ -27,14 +40,24 @@ constexpr size_t HashCombine(size_t A, size_t C) return C; } +template <typename... Ts> requires (true && ... && TIsConvertible<Ts, size_t>::Value) +constexpr size_t HashCombine(size_t A, size_t C, Ts... InOther) +{ + size_t B = HashCombine(A, C); + return HashCombine(B, InOther...); +} + template <typename T> requires TIsIntegral<T>::Value constexpr size_t GetTypeHash(T A) { static_assert(sizeof(T) <= 16, "GetTypeHash only works with T up to 128 bits."); - if constexpr (sizeof(T) <= 8) return static_cast<size_t>(A); - if constexpr (sizeof(T) == 16) return static_cast<size_t>(A ^ (A >> 64)); - else return INDEX_NONE; + if constexpr (sizeof(T) <= sizeof(size_t)) return static_cast<size_t>(A); + if constexpr (sizeof(T) == 8) return GetTypeHash(static_cast<uint32>(A)) ^ GetTypeHash(static_cast<uint32>(A >> 32)); + if constexpr (sizeof(T) == 16) return GetTypeHash(static_cast<uint64>(A)) ^ GetTypeHash(static_cast<uint64>(A >> 64)); + else check_no_entry(); + + return INDEX_NONE; } template <typename T> requires TIsFloatingPoint<T>::Value @@ -47,7 +70,9 @@ constexpr size_t GetTypeHash(T A) if constexpr (sizeof(T) == 4) return GetTypeHash(*reinterpret_cast<uint32*>(&A)); if constexpr (sizeof(T) == 8) return GetTypeHash(*reinterpret_cast<uint64*>(&A)); if constexpr (sizeof(T) == 16) return GetTypeHash(*reinterpret_cast<uint64*>(&A) + *(reinterpret_cast<uint64*>(&A) + 1)); - else return INDEX_NONE; + else check_no_entry(); + + return INDEX_NONE; } template <typename T> requires TIsEnum<T>::Value @@ -56,24 +81,20 @@ constexpr size_t GetTypeHash(T A) return GetTypeHash(static_cast<typename TUnderlyingType<T>::Type>(A)); } -constexpr size_t GetTypeHash(nullptr_t) +template <typename T> requires TIsPointer<T>::Value || TIsSame<T, nullptr_t>::Value +constexpr size_t GetTypeHash(T A) { - return GetTypeHash(2.7182818284590452353602874713527); + return GetTypeHash(reinterpret_cast<intptr>(A)); } -constexpr size_t GetTypeHash(const void* A) -{ - return GetTypeHash(reinterpret_cast<intptr_t>(A)); -} - -template <typename T> requires requires(T&& A) { { GetTypeHash(A.GetTypeHash()) } -> CSameAs<size_t>; } -constexpr size_t GetTypeHash(T&& A) +template <typename T> requires requires(const T& A) { { GetTypeHash(A.GetTypeHash()) } -> CSameAs<size_t>; } +constexpr size_t GetTypeHash(const T& A) { return GetTypeHash(A.GetTypeHash()); } template <typename T> -concept CHashable = requires(T&& A) { { GetTypeHash(A) } -> CSameAs<size_t>; }; +concept CHashable = requires(const T& A) { { GetTypeHash(A) } -> CSameAs<size_t>; }; NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) diff --git a/Redcraft.Utility/Source/Public/Templates/Variant.h b/Redcraft.Utility/Source/Public/Templates/Variant.h index ef5704a..893f738 100644 --- a/Redcraft.Utility/Source/Public/Templates/Variant.h +++ b/Redcraft.Utility/Source/Public/Templates/Variant.h @@ -2,8 +2,8 @@ #include "CoreTypes.h" #include "Templates/Invoke.h" -#include "Templates/TypeHash.h" #include "Templates/Utility.h" +#include "Templates/TypeHash.h" #include "TypeTraits/TypeTraits.h" #include "Miscellaneous/AssertionMacros.h" @@ -204,7 +204,7 @@ struct TVariantVisitHelper NAMESPACE_PRIVATE_END -template <typename... Types> requires (true && ... && (TIsObject<Types>::Value && !TIsArray<Types>::Value && TIsDestructible<Types>::Value)) +template <typename... Types> requires (true && ... && (TIsObject<Types>::Value && !TIsArray<Types>::Value && TIsDestructible<Types>::Value)) && (sizeof...(Types) < 0xFF) struct TVariant { static constexpr size_t AlternativeSize = sizeof...(Types); @@ -212,20 +212,20 @@ struct TVariant template <size_t I> struct TAlternativeType : NAMESPACE_PRIVATE::TVariantAlternativeType<I, Types...> { }; template <typename T> struct TAlternativeIndex : NAMESPACE_PRIVATE::TVariantAlternativeIndex<T, Types...> { }; - constexpr TVariant() : TypeIndex(INDEX_NONE) { }; + constexpr TVariant() : TypeIndex(0xFF) { }; constexpr TVariant(FInvalid) : TVariant() { }; constexpr TVariant(const TVariant& InValue) requires (true && ... && TIsCopyConstructible<Types>::Value) - : TypeIndex(InValue.GetIndex()) + : TypeIndex(static_cast<uint8>(InValue.GetIndex())) { - if (GetIndex() != INDEX_NONE) FHelper::CopyConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); + if (IsValid()) FHelper::CopyConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); } constexpr TVariant(TVariant&& InValue) requires (true && ... && TIsMoveConstructible<Types>::Value) - : TypeIndex(InValue.GetIndex()) + : TypeIndex(static_cast<uint8>(InValue.GetIndex())) { - if (GetIndex() != INDEX_NONE) FHelper::MoveConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); + if (IsValid()) FHelper::MoveConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); } template <size_t I, typename... ArgTypes> requires (I < AlternativeSize) @@ -269,7 +269,7 @@ struct TVariant { Reset(); FHelper::CopyConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); - TypeIndex = InValue.GetIndex(); + TypeIndex = static_cast<uint8>(InValue.GetIndex()); } return *this; @@ -290,7 +290,7 @@ struct TVariant { Reset(); FHelper::MoveConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); - TypeIndex = InValue.GetIndex(); + TypeIndex = static_cast<uint8>(InValue.GetIndex()); } return *this; @@ -332,9 +332,9 @@ struct TVariant return Emplace<TAlternativeIndex<T>::Value>(Forward<ArgTypes>(Args)...); } - constexpr size_t GetIndex() const { return TypeIndex; } - constexpr bool IsValid() const { return GetIndex() != INDEX_NONE; } - constexpr explicit operator bool() const { return GetIndex() != INDEX_NONE; } + constexpr size_t GetIndex() const { return TypeIndex != 0xFF ? TypeIndex : INDEX_NONE; } + constexpr bool IsValid() const { return TypeIndex != 0xFF; } + constexpr explicit operator bool() const { return TypeIndex != 0xFF; } template <size_t I> constexpr bool HoldsAlternative() const { return IsValid() ? GetIndex() == I : false; } template <typename T> constexpr bool HoldsAlternative() const { return IsValid() ? GetIndex() == TAlternativeIndex<T>::Value : false; } @@ -418,12 +418,6 @@ struct TVariant return R(NAMESPACE_PRIVATE::TVariantVisitHelper<R, F, Types...>::VisitConstRValueFuncs[GetIndex()](Forward<F>(Func), &Value)); } - constexpr size_t GetTypeHash() const requires (true && ... && CHashable<Types>) - { - if (!IsValid()) return NAMESPACE_REDCRAFT::GetTypeHash(nullptr); - return Visit([](auto&& A) { return NAMESPACE_REDCRAFT::GetTypeHash(A); }); - } - constexpr void Reset() { if (GetIndex() == INDEX_NONE) return; @@ -433,9 +427,15 @@ struct TVariant FHelper::DestroyFuncs[GetIndex()](&Value); } - TypeIndex = INDEX_NONE; + TypeIndex = static_cast<uint8>(INDEX_NONE); } - + + constexpr size_t GetTypeHash() const requires (true && ... && CHashable<Types>) + { + if (!IsValid()) return 114514; + return HashCombine(NAMESPACE_REDCRAFT::GetTypeHash(GetIndex()), Visit([](const auto& A) { return NAMESPACE_REDCRAFT::GetTypeHash(A); })); + } + constexpr void Swap(TVariant& InValue) requires (true && ... && (TIsMoveConstructible<Types>::Value && TIsSwappable<Types>::Value)) { if (!IsValid() && !InValue.IsValid()) return; @@ -470,7 +470,7 @@ private: using FHelper = NAMESPACE_PRIVATE::TVariantHelper<Types...>; TAlignedUnion<1, Types...>::Type Value; - size_t TypeIndex; + uint8 TypeIndex; friend constexpr bool operator==(const TVariant& LHS, const TVariant& RHS) requires (true && ... && CEqualityComparable<Types>) {