refactor(templates): refactor GetTypeHash into a member function
This commit is contained in:
		| @@ -3,6 +3,7 @@ | |||||||
| #include "CoreTypes.h" | #include "CoreTypes.h" | ||||||
| #include "Memory/Memory.h" | #include "Memory/Memory.h" | ||||||
| #include "Templates/Utility.h" | #include "Templates/Utility.h" | ||||||
|  | #include "Templates/TypeHash.h" | ||||||
| #include "TypeTraits/TypeTraits.h" | #include "TypeTraits/TypeTraits.h" | ||||||
| #include "Miscellaneous/TypeInfo.h" | #include "Miscellaneous/TypeInfo.h" | ||||||
| #include "Miscellaneous/AssertionMacros.h" | #include "Miscellaneous/AssertionMacros.h" | ||||||
| @@ -91,14 +92,33 @@ void AnyMoveAssign(void* Target, void* Source) | |||||||
|  |  | ||||||
| using FAnyMoveAssignFunc = void(*)(void*, void*); | using FAnyMoveAssignFunc = void(*)(void*, void*); | ||||||
|  |  | ||||||
| template <typename T> | //template <typename T> | ||||||
| void AnySwap(void* A, void* B) | //constexpr bool AnyEqualityOperator(const void* LHS, const void* RHS) | ||||||
| { | //{ | ||||||
| 	if constexpr (TIsSwappable<T>::Value) Swap(*reinterpret_cast<T*>(A), *reinterpret_cast<T*>(B)); | //	if constexpr (!CEqualityComparable<T>) check_no_entry(); | ||||||
| 	else check_no_entry(); | //	else return *reinterpret_cast<const T*>(LHS) == *reinterpret_cast<const T*>(RHS); | ||||||
| } | //	return false; | ||||||
|  | //} | ||||||
| using FAnySwapFunc = void(*)(void*, void*); | // | ||||||
|  | //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 | struct FAnyRTTI | ||||||
| { | { | ||||||
| @@ -111,7 +131,9 @@ struct FAnyRTTI | |||||||
| 	FAnyMoveConstructFunc      MoveConstruct; | 	FAnyMoveConstructFunc      MoveConstruct; | ||||||
| 	FAnyCopyAssignFunc         CopyAssign; | 	FAnyCopyAssignFunc         CopyAssign; | ||||||
| 	FAnyMoveAssignFunc         MoveAssign; | 	FAnyMoveAssignFunc         MoveAssign; | ||||||
| 	FAnySwapFunc               SwapObject; | //	FAnyEqualityOperatorFunc   EqualityOperator; | ||||||
|  | //	FAnySwapFunc               SwapObject; | ||||||
|  | //	FAnyTypeHashFunc           TypeHash; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| template <typename T, bool bInIsInline> | template <typename T, bool bInIsInline> | ||||||
| @@ -128,7 +150,9 @@ struct TAnyRTTIHelper | |||||||
| 		AnyMoveConstruct<T>, | 		AnyMoveConstruct<T>, | ||||||
| 		AnyCopyAssign<T>, | 		AnyCopyAssign<T>, | ||||||
| 		AnyMoveAssign<T>, | 		AnyMoveAssign<T>, | ||||||
| 		AnySwap<T>, | //		AnyEqualityOperator<T>, | ||||||
|  | //		AnySwap<T>, | ||||||
|  | //		AnyTypeHash<T>, | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -326,34 +350,40 @@ struct TAny | |||||||
| 		ResetImpl(); | 		ResetImpl(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	constexpr void Swap(TAny& InValue) | //	constexpr size_t GetTypeHash() const | ||||||
| 	{ | //	{ | ||||||
| 		if (!IsValid() && !InValue.IsValid()) return; | //		if (!IsValid()) return 20090007; | ||||||
|  | //		return HashCombine(NAMESPACE_REDCRAFT::GetTypeHash(GetTypeInfo()), RTTI->TypeHash(GetData())); | ||||||
| 		if (IsValid() && !InValue.IsValid()) | //	} | ||||||
| 		{ | // | ||||||
| 			InValue = MoveTemp(*this); | //	constexpr void Swap(TAny& InValue) | ||||||
| 			Reset(); | //	{ | ||||||
| 			return; | //		if (!IsValid() && !InValue.IsValid()) return; | ||||||
| 		} | // | ||||||
|  | //		if (IsValid() && !InValue.IsValid()) | ||||||
| 		if (InValue.IsValid() && !IsValid()) | //		{ | ||||||
| 		{ | //			InValue = MoveTemp(*this); | ||||||
| 			*this = MoveTemp(InValue); | //			Reset(); | ||||||
| 			InValue.Reset(); | //			return; | ||||||
| 			return; | //		} | ||||||
| 		} | // | ||||||
|  | //		if (InValue.IsValid() && !IsValid()) | ||||||
| 		if (GetTypeInfo() == InValue.GetTypeInfo()) | //		{ | ||||||
| 		{ | //			*this = MoveTemp(InValue); | ||||||
| 			RTTI->SwapObject(GetData(), InValue.GetData()); | //			InValue.Reset(); | ||||||
| 			return; | //			return; | ||||||
| 		} | //		} | ||||||
| 		 | // | ||||||
| 		TAny Temp = MoveTemp(*this); | //		if (GetTypeInfo() == InValue.GetTypeInfo()) | ||||||
| 		*this = MoveTemp(InValue); | //		{ | ||||||
| 		InValue = MoveTemp(Temp); | //			RTTI->SwapObject(GetData(), InValue.GetData()); | ||||||
| 	} | //			return; | ||||||
|  | //		} | ||||||
|  | //		 | ||||||
|  | //		TAny Temp = MoveTemp(*this); | ||||||
|  | //		*this = MoveTemp(InValue); | ||||||
|  | //		InValue = MoveTemp(Temp); | ||||||
|  | //	} | ||||||
|  |  | ||||||
| private: | private: | ||||||
|  |  | ||||||
| @@ -395,6 +425,13 @@ private: | |||||||
| 		else RTTI->Delete(DynamicValue); | 		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> | template <typename T, size_t InlineSize, size_t InlineAlignment> | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ | |||||||
| #include "Templates/Tuple.h" | #include "Templates/Tuple.h" | ||||||
| #include "Templates/Invoke.h" | #include "Templates/Invoke.h" | ||||||
| #include "Templates/Utility.h" | #include "Templates/Utility.h" | ||||||
|  | #include "Templates/TypeHash.h" | ||||||
| #include "Templates/Container.h" | #include "Templates/Container.h" | ||||||
| #include "Concepts/Comparable.h" | #include "Concepts/Comparable.h" | ||||||
| #include "Concepts/Convertible.h" | #include "Concepts/Convertible.h" | ||||||
| @@ -434,7 +435,6 @@ constexpr bool operator==(const TUniqueFunction<F>& LHS, nullptr_t) | |||||||
| 	return !LHS; | 	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(TFunction<void()>)       == 64, "The byte size of TFunction is unexpected"); | ||||||
| static_assert(sizeof(TUniqueFunction<void()>) == 64, "The byte size of TUniqueFunction is unexpected"); | static_assert(sizeof(TUniqueFunction<void()>) == 64, "The byte size of TUniqueFunction is unexpected"); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -208,12 +208,6 @@ public: | |||||||
| 	constexpr       OptionalType& Get(      OptionalType& DefaultValue) &      { return IsValid() ? GetValue() : DefaultValue;  } | 	constexpr       OptionalType& Get(      OptionalType& DefaultValue) &      { return IsValid() ? GetValue() : DefaultValue;  } | ||||||
| 	constexpr const OptionalType& Get(const OptionalType& DefaultValue) const& { 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() | 	constexpr void Reset() | ||||||
| 	{ | 	{ | ||||||
| 		if (bIsValid) | 		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 | 	template <typename T> requires TIsMoveConstructible<OptionalType>::Value && TIsSwappable<OptionalType>::Value | ||||||
| 	constexpr void Swap(TOptional& InValue) | 	constexpr void Swap(TOptional& InValue) | ||||||
| 	{ | 	{ | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "CoreTypes.h" | #include "CoreTypes.h" | ||||||
|  | #include "Templates/Invoke.h" | ||||||
| #include "Templates/Utility.h" | #include "Templates/Utility.h" | ||||||
| #include "Templates/TypeHash.h" | #include "Templates/TypeHash.h" | ||||||
| #include "TypeTraits/TypeTraits.h" | #include "TypeTraits/TypeTraits.h" | ||||||
| #include "Templates/IntegerSequence.h" | #include "Templates/IntegerSequence.h" | ||||||
| #include "Templates/ReferenceWrapper.h" | #include "Templates/ReferenceWrapper.h" | ||||||
| #include "Templates/Invoke.h" |  | ||||||
|  |  | ||||||
| #include <tuple> | #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() 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()       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)); } | 	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)) | 	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)...); | 	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(Utility) | ||||||
| NAMESPACE_MODULE_END(Redcraft) | NAMESPACE_MODULE_END(Redcraft) | ||||||
| NAMESPACE_REDCRAFT_END | NAMESPACE_REDCRAFT_END | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ | |||||||
|  |  | ||||||
| #include "CoreTypes.h" | #include "CoreTypes.h" | ||||||
| #include "Concepts/Same.h" | #include "Concepts/Same.h" | ||||||
|  | #include "Templates/Utility.h" | ||||||
| #include "TypeTraits/PrimaryType.h" | #include "TypeTraits/PrimaryType.h" | ||||||
| #include "TypeTraits/Miscellaneous.h" | #include "TypeTraits/Miscellaneous.h" | ||||||
|  |  | ||||||
| @@ -9,9 +10,21 @@ NAMESPACE_REDCRAFT_BEGIN | |||||||
| NAMESPACE_MODULE_BEGIN(Redcraft) | NAMESPACE_MODULE_BEGIN(Redcraft) | ||||||
| NAMESPACE_MODULE_BEGIN(Utility) | 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) | 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 -= B; A -= C; A ^= (C >> 13); | 	A -= B; A -= C; A ^= (C >> 13); | ||||||
| @@ -27,14 +40,24 @@ constexpr size_t HashCombine(size_t A, size_t C) | |||||||
| 	return 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 | template <typename T> requires TIsIntegral<T>::Value | ||||||
| constexpr size_t GetTypeHash(T A) | constexpr size_t GetTypeHash(T A) | ||||||
| { | { | ||||||
| 	static_assert(sizeof(T) <= 16, "GetTypeHash only works with T up to 128 bits."); | 	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) <= sizeof(size_t)) return static_cast<size_t>(A); | ||||||
| 	if constexpr (sizeof(T) == 16) return static_cast<size_t>(A ^ (A >> 64)); | 	if constexpr (sizeof(T) ==  8) return GetTypeHash(static_cast<uint32>(A)) ^ GetTypeHash(static_cast<uint32>(A >> 32)); | ||||||
| 	else return INDEX_NONE; | 	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 | 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) ==  4) return GetTypeHash(*reinterpret_cast<uint32*>(&A)); | ||||||
| 	if constexpr (sizeof(T) ==  8) return GetTypeHash(*reinterpret_cast<uint64*>(&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)); | 	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 | 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)); | 	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) | template <typename T> requires requires(const T& A) { { GetTypeHash(A.GetTypeHash()) } -> CSameAs<size_t>; } | ||||||
| { | constexpr size_t GetTypeHash(const T& 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) |  | ||||||
| { | { | ||||||
| 	return GetTypeHash(A.GetTypeHash()); | 	return GetTypeHash(A.GetTypeHash()); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename T> | 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(Utility) | ||||||
| NAMESPACE_MODULE_END(Redcraft) | NAMESPACE_MODULE_END(Redcraft) | ||||||
|   | |||||||
| @@ -2,8 +2,8 @@ | |||||||
|  |  | ||||||
| #include "CoreTypes.h" | #include "CoreTypes.h" | ||||||
| #include "Templates/Invoke.h" | #include "Templates/Invoke.h" | ||||||
| #include "Templates/TypeHash.h" |  | ||||||
| #include "Templates/Utility.h" | #include "Templates/Utility.h" | ||||||
|  | #include "Templates/TypeHash.h" | ||||||
| #include "TypeTraits/TypeTraits.h" | #include "TypeTraits/TypeTraits.h" | ||||||
| #include "Miscellaneous/AssertionMacros.h" | #include "Miscellaneous/AssertionMacros.h" | ||||||
|  |  | ||||||
| @@ -204,7 +204,7 @@ struct TVariantVisitHelper | |||||||
|  |  | ||||||
| NAMESPACE_PRIVATE_END | 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 | struct TVariant | ||||||
| { | { | ||||||
| 	static constexpr size_t AlternativeSize = sizeof...(Types); | 	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 <size_t I>   struct TAlternativeType  : NAMESPACE_PRIVATE::TVariantAlternativeType<I, Types...>  { }; | ||||||
| 	template <typename T> struct TAlternativeIndex : NAMESPACE_PRIVATE::TVariantAlternativeIndex<T, 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(FInvalid) : TVariant() { }; | ||||||
|  |  | ||||||
| 	constexpr TVariant(const TVariant& InValue) requires (true && ... && TIsCopyConstructible<Types>::Value) | 	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) | 	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) | 	template <size_t I, typename... ArgTypes> requires (I < AlternativeSize) | ||||||
| @@ -269,7 +269,7 @@ struct TVariant | |||||||
| 		{	 | 		{	 | ||||||
| 			Reset(); | 			Reset(); | ||||||
| 			FHelper::CopyConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); | 			FHelper::CopyConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); | ||||||
| 			TypeIndex = InValue.GetIndex(); | 			TypeIndex = static_cast<uint8>(InValue.GetIndex()); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		return *this; | 		return *this; | ||||||
| @@ -290,7 +290,7 @@ struct TVariant | |||||||
| 		{ | 		{ | ||||||
| 			Reset(); | 			Reset(); | ||||||
| 			FHelper::MoveConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); | 			FHelper::MoveConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); | ||||||
| 			TypeIndex = InValue.GetIndex(); | 			TypeIndex = static_cast<uint8>(InValue.GetIndex()); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		return *this; | 		return *this; | ||||||
| @@ -332,9 +332,9 @@ struct TVariant | |||||||
| 		return Emplace<TAlternativeIndex<T>::Value>(Forward<ArgTypes>(Args)...); | 		return Emplace<TAlternativeIndex<T>::Value>(Forward<ArgTypes>(Args)...); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	constexpr size_t GetIndex()        const { return TypeIndex; } | 	constexpr size_t GetIndex()        const { return TypeIndex != 0xFF ? TypeIndex : INDEX_NONE; } | ||||||
| 	constexpr bool IsValid()           const { return GetIndex() != INDEX_NONE; } | 	constexpr bool IsValid()           const { return TypeIndex != 0xFF; } | ||||||
| 	constexpr explicit operator bool() const { return GetIndex() != INDEX_NONE; } | 	constexpr explicit operator bool() const { return TypeIndex != 0xFF; } | ||||||
|  |  | ||||||
| 	template <size_t   I> constexpr bool HoldsAlternative() const { return IsValid() ? GetIndex() == I                           : false; } | 	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; } | 	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)); | 		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() | 	constexpr void Reset() | ||||||
| 	{ | 	{ | ||||||
| 		if (GetIndex() == INDEX_NONE) return; | 		if (GetIndex() == INDEX_NONE) return; | ||||||
| @@ -433,9 +427,15 @@ struct TVariant | |||||||
| 			FHelper::DestroyFuncs[GetIndex()](&Value); | 			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)) | 	constexpr void Swap(TVariant& InValue) requires (true && ... && (TIsMoveConstructible<Types>::Value && TIsSwappable<Types>::Value)) | ||||||
| 	{ | 	{ | ||||||
| 		if (!IsValid() && !InValue.IsValid()) return; | 		if (!IsValid() && !InValue.IsValid()) return; | ||||||
| @@ -470,7 +470,7 @@ private: | |||||||
| 	using FHelper = NAMESPACE_PRIVATE::TVariantHelper<Types...>; | 	using FHelper = NAMESPACE_PRIVATE::TVariantHelper<Types...>; | ||||||
|  |  | ||||||
| 	TAlignedUnion<1, Types...>::Type Value; | 	TAlignedUnion<1, Types...>::Type Value; | ||||||
| 	size_t TypeIndex; | 	uint8 TypeIndex; | ||||||
|  |  | ||||||
| 	friend constexpr bool operator==(const TVariant& LHS, const TVariant& RHS) requires (true && ... && CEqualityComparable<Types>) | 	friend constexpr bool operator==(const TVariant& LHS, const TVariant& RHS) requires (true && ... && CEqualityComparable<Types>) | ||||||
| 	{ | 	{ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user