refactor(templates): refactor GetTypeHash into a member function

This commit is contained in:
_Redstone_c_ 2022-04-22 22:28:44 +08:00
parent 63b63ef0b4
commit 04d713cd93
6 changed files with 145 additions and 92 deletions

View File

@ -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>

View File

@ -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");

View File

@ -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)
{ {

View File

@ -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

View File

@ -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)

View File

@ -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>)
{ {