refactor(templates): refactor operator== and operator<=> to member or friend

This commit is contained in:
_Redstone_c_ 2022-12-18 19:11:53 +08:00
parent 6cee8a1185
commit d87d292691
6 changed files with 183 additions and 157 deletions

View File

@ -130,6 +130,8 @@ void TestOptional()
always_check(TempO == TempO);
always_check(TempO == 300);
always_check(300 == TempO);
always_check(TempO >= 200);
always_check(400 >= TempO);
int16 TempQ = 1024;
TOptional<int16> TempR = TempQ;
@ -221,6 +223,8 @@ void TestVariant()
always_check(TempO == TempO);
always_check(TempO == 300);
always_check(300 == TempO);
always_check(TempO >= 200);
always_check(400 >= TempO);
Swap(TempD, TempA);
@ -428,7 +432,7 @@ void TestAny()
int32 A;
FIntegral() { }
FIntegral(int32 InA) : A(InA) { }
bool operator==(FIntegral RHS) const { return A == RHS.A; }
bool operator==(FIntegral RHS) const& { return A == RHS.A; }
};
struct FFloating
@ -437,7 +441,7 @@ void TestAny()
uint8 Pad[64];
FFloating() { }
FFloating(double InA) : A(InA) { }
bool operator==(FFloating RHS) const { return A == RHS.A; }
bool operator==(FFloating RHS) const& { return A == RHS.A; }
};
struct FTracker
@ -474,6 +478,8 @@ void TestAny()
always_check(TempO.IsValid());
always_check(TempO == 404);
always_check(TempO >= 400);
always_check(500 >= TempO);
always_check(TempO.GetValue<int32>() == 404);
always_check(TempO.Get<int32>(500) == 404);

View File

@ -5,7 +5,6 @@
#include "Memory/Alignment.h"
#include "Templates/Utility.h"
#include "Templates/TypeHash.h"
#include "Memory/MemoryOperator.h"
#include "TypeTraits/TypeTraits.h"
#include "Miscellaneous/AssertionMacros.h"
@ -237,6 +236,20 @@ public:
return *this;
}
template <typename T> requires (!CBaseOf<FAny, TRemoveCVRef<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T>)
FORCEINLINE constexpr bool operator==(const T& InValue) const&
{
return HoldsAlternative<T>() ? GetValue<T>() == InValue : false;
}
template <typename T> requires (!CBaseOf<FAny, TRemoveCVRef<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T>)
FORCEINLINE constexpr partial_ordering operator<=>(const T& InValue) const&
{
return HoldsAlternative<T>() ? SynthThreeWayCompare(GetValue<T>(), InValue) : partial_ordering::unordered;
}
FORCEINLINE constexpr bool operator==(FInvalid) const& { return !IsValid(); }
template <typename T, typename... Ts> requires (NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, Ts&&...>)
FORCEINLINE TDecay<T>& Emplace(Ts&&... Args)
{
@ -527,17 +540,6 @@ private:
FORCEINLINE constexpr void Invalidate() { TypeInfo = 0; }
template <typename T> requires (!CBaseOf<FAny, TRemoveCVRef<T>>)
friend FORCEINLINE constexpr bool operator==(const FAny& LHS, const T& RHS)
{
return LHS.template HoldsAlternative<T>() ? LHS.template GetValue<T>() == RHS : false;
}
friend FORCEINLINE constexpr bool operator==(const FAny& LHS, FInvalid)
{
return !LHS.IsValid();
}
};
static_assert(sizeof(FAny) == 64, "The byte size of FAny is unexpected");

View File

@ -482,6 +482,8 @@ public:
FORCEINLINE ResultType operator()(Ts... Args) const& requires (CSameAs<CVRef, const int& >) { return CallImpl(Forward<Ts>(Args)...); }
FORCEINLINE ResultType operator()(Ts... Args) const&& requires (CSameAs<CVRef, const int&&>) { return CallImpl(Forward<Ts>(Args)...); }
FORCEINLINE constexpr bool operator==(nullptr_t) const& { return !IsValid(); }
FORCEINLINE constexpr bool IsValid() const { return Storage.IsValid(); }
FORCEINLINE constexpr explicit operator bool() const { return Storage.IsValid(); }
@ -573,6 +575,9 @@ public:
Impl::template Emplace<T>(Forward<T>(InValue));
}
template <typename T>
TFunctionRef(const T&& InValue) = delete;
};
template <CFunction F>
@ -732,24 +737,6 @@ public:
};
template <CFunction F>
FORCEINLINE constexpr bool operator==(const TFunctionRef<F>& LHS, nullptr_t)
{
return !LHS;
}
template <CFunction F>
FORCEINLINE constexpr bool operator==(const TFunction<F>& LHS, nullptr_t)
{
return !LHS;
}
template <CFunction F>
FORCEINLINE constexpr bool operator==(const TUniqueFunction<F>& LHS, nullptr_t)
{
return !LHS;
}
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");

View File

@ -16,6 +16,9 @@ class TOptional;
NAMESPACE_PRIVATE_BEGIN
template <typename T> struct TIsTOptional : FFalse { };
template <typename T> struct TIsTOptional<TOptional<T>> : FTrue { };
template <typename T, typename U>
concept CTOptionalAllowUnwrappable =
!(CConstructibleFrom<U, TOptional<T>& >
@ -33,6 +36,8 @@ concept CTOptionalAllowUnwrappable =
NAMESPACE_PRIVATE_END
template <typename T> concept CTOptional = NAMESPACE_PRIVATE::TIsTOptional<TRemoveCV<T>>::Value;
template <typename OptionalType> requires (CDestructible<OptionalType>)
class TOptional
{
@ -193,6 +198,36 @@ public:
return *this;
}
template <typename T = OptionalType> requires (CWeaklyEqualityComparable<OptionalType, T>)
friend FORCEINLINE constexpr bool operator==(const TOptional& LHS, const TOptional<T>& RHS)
{
if (LHS.IsValid() != RHS.IsValid()) return false;
if (LHS.IsValid() == false) return true;
return *LHS == *RHS;
}
template <typename T = OptionalType> requires (CSynthThreeWayComparable<OptionalType, T>)
friend FORCEINLINE constexpr partial_ordering operator<=>(const TOptional& LHS, const TOptional<T>& RHS)
{
if (LHS.IsValid() != RHS.IsValid()) return partial_ordering::unordered;
if (LHS.IsValid() == false) return partial_ordering::equivalent;
return SynthThreeWayCompare(*LHS, *RHS);
}
template <typename T = OptionalType> requires (!CTOptional<T>&& CWeaklyEqualityComparable<OptionalType, T>)
FORCEINLINE constexpr bool operator==(const T& InValue) const&
{
return IsValid() ? GetValue() == InValue : false;
}
template <typename T = OptionalType> requires (!CTOptional<T>&& CSynthThreeWayComparable<OptionalType, T>)
FORCEINLINE constexpr partial_ordering operator<=>(const T& InValue) const&
{
return IsValid() ? SynthThreeWayCompare(GetValue(), InValue) : partial_ordering::unordered;
}
FORCEINLINE constexpr bool operator==(FInvalid) const& { return !IsValid(); }
template <typename... ArgTypes> requires (CConstructibleFrom<OptionalType, ArgTypes...>)
FORCEINLINE constexpr OptionalType& Emplace(ArgTypes&&... Args)
{
@ -272,34 +307,6 @@ private:
template <typename T>
TOptional(T) -> TOptional<T>;
template <typename T, typename U> requires (CWeaklyEqualityComparable<T, U>)
FORCEINLINE constexpr bool operator==(const TOptional<T>& LHS, const TOptional<U>& RHS)
{
if (LHS.IsValid() != RHS.IsValid()) return false;
if (LHS.IsValid() == false) return true;
return *LHS == *RHS;
}
template <typename T, typename U> requires (CSynthThreeWayComparable<T, U>)
FORCEINLINE constexpr partial_ordering operator<=>(const TOptional<T>& LHS, const TOptional<U>& RHS)
{
if (LHS.IsValid() != RHS.IsValid()) return partial_ordering::unordered;
if (LHS.IsValid() == false) return partial_ordering::equivalent;
return SynthThreeWayCompare(*LHS, *RHS);
}
template <typename T, typename U> requires (CWeaklyEqualityComparable<T, U>)
FORCEINLINE constexpr bool operator==(const TOptional<T>& LHS, const U& RHS)
{
return LHS.IsValid() ? *LHS == RHS : false;
}
template <typename T>
FORCEINLINE constexpr bool operator==(const TOptional<T>& LHS, FInvalid)
{
return !LHS.IsValid();
}
template <typename T> requires (CDestructible<T>)
FORCEINLINE constexpr TOptional<TDecay<T>> MakeOptional(FInvalid)
{
@ -318,15 +325,6 @@ FORCEINLINE constexpr TOptional<T> MakeOptional(Ts&&... Args)
return TOptional<T>(InPlace, Forward<T>(Args)...);
}
NAMESPACE_PRIVATE_BEGIN
template <typename T> struct TIsTOptional : FFalse { };
template <typename T> struct TIsTOptional<TOptional<T>> : FTrue { };
NAMESPACE_PRIVATE_END
template <typename T> concept CTOptional = NAMESPACE_PRIVATE::TIsTOptional<TRemoveCV<T>>::Value;
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -226,6 +226,57 @@ public:
};
template <typename R, typename Indices>
struct TTupleThreeWay;
template <typename R, size_t I, size_t... Indices>
struct TTupleThreeWay<R, TIndexSequence<I, Indices...>>
{
template <typename LHSTupleType, typename RHSTupleType>
FORCEINLINE static constexpr R Do(const LHSTupleType& LHS, const RHSTupleType& RHS)
{
auto Result = SynthThreeWayCompare(LHS.template GetValue<I>(), RHS.template GetValue<I>());
if (Result != 0) return Result;
return TTupleThreeWay<R, TIndexSequence<Indices...>>::Do(LHS, RHS);
}
};
template <typename R>
struct TTupleThreeWay<R, TIndexSequence<>>
{
template <typename LHSTupleType, typename RHSTupleType>
FORCEINLINE static constexpr R Do(const LHSTupleType& LHS, const RHSTupleType& RHS)
{
return R::equivalent;
}
};
template <typename, typename> struct TTTupleWeaklyEqualityComparable;
template <typename T, typename U, typename... Ts, typename... Us>
struct TTTupleWeaklyEqualityComparable<TTypeSequence<T, Ts...>, TTypeSequence<U, Us...>>
: TBoolConstant<CWeaklyEqualityComparable<T, U> && TTTupleWeaklyEqualityComparable<TTypeSequence<Ts...>, TTypeSequence<Us...>>::Value>
{ };
template <>
struct TTTupleWeaklyEqualityComparable<TTypeSequence<>, TTypeSequence<>> : FTrue { };
template <typename TSequence, typename USequence>
concept CTTupleWeaklyEqualityComparable = TTTupleWeaklyEqualityComparable<TSequence, USequence>::Value;
template <typename, typename> struct TTTupleSynthThreeWayComparable;
template <typename T, typename U, typename... Ts, typename... Us>
struct TTTupleSynthThreeWayComparable<TTypeSequence<T, Ts...>, TTypeSequence<U, Us...>>
: TBoolConstant<CSynthThreeWayComparable<T, U> && TTTupleSynthThreeWayComparable<TTypeSequence<Ts...>, TTypeSequence<Us...>>::Value>
{ };
template <>
struct TTTupleSynthThreeWayComparable<TTypeSequence<>, TTypeSequence<>> : FTrue { };
template <typename TSequence, typename USequence>
concept CTTupleSynthThreeWayComparable = TTTupleSynthThreeWayComparable<TSequence, USequence>::Value;
NAMESPACE_PRIVATE_END
template <typename T>
@ -258,34 +309,34 @@ public:
: Super(NAMESPACE_PRIVATE::ForwardingConstructor, Forward<ArgTypes>(Args)...)
{ }
template <typename... OtherTypes> requires (sizeof...(OtherTypes) == sizeof...(Ts)
&& (true && ... && CConstructibleFrom<Ts, const OtherTypes&>)
&& NAMESPACE_PRIVATE::TTupleConvertCopy<sizeof...(Ts) != 1, Ts..., OtherTypes...>::Value)
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<OtherTypes&&, Ts>)) TTuple(const TTuple<OtherTypes...>& InValue)
template <typename... Us> requires (sizeof...(Us) == sizeof...(Ts)
&& (true && ... && CConstructibleFrom<Ts, const Us&>)
&& NAMESPACE_PRIVATE::TTupleConvertCopy<sizeof...(Ts) != 1, Ts..., Us...>::Value)
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<Us&&, Ts>)) TTuple(const TTuple<Us...>& InValue)
: Super(NAMESPACE_PRIVATE::OtherTupleConstructor, InValue)
{ }
template <typename... OtherTypes> requires (sizeof...(OtherTypes) == sizeof...(Ts)
&& (true && ... && CConstructibleFrom<Ts, OtherTypes&&>)
&& NAMESPACE_PRIVATE::TTupleConvertMove<sizeof...(Ts) != 1, Ts..., OtherTypes...>::Value)
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<OtherTypes&&, Ts>)) TTuple(TTuple<OtherTypes...>&& InValue)
template <typename... Us> requires (sizeof...(Us) == sizeof...(Ts)
&& (true && ... && CConstructibleFrom<Ts, Us&&>)
&& NAMESPACE_PRIVATE::TTupleConvertMove<sizeof...(Ts) != 1, Ts..., Us...>::Value)
FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo<Us&&, Ts>)) TTuple(TTuple<Us...>&& InValue)
: Super(NAMESPACE_PRIVATE::OtherTupleConstructor, MoveTemp(InValue))
{ }
FORCEINLINE constexpr TTuple(const TTuple&) = default;
FORCEINLINE constexpr TTuple(TTuple&&) = default;
template <typename... OtherTypes> requires (sizeof...(OtherTypes) == sizeof...(Ts)
&& (true && ... && CAssignableFrom<Ts&, const OtherTypes&>))
FORCEINLINE constexpr TTuple& operator=(const TTuple<OtherTypes...>& InValue)
template <typename... Us> requires (sizeof...(Us) == sizeof...(Ts)
&& (true && ... && CAssignableFrom<Ts&, const Us&>))
FORCEINLINE constexpr TTuple& operator=(const TTuple<Us...>& InValue)
{
Helper::Assign(*this, InValue);
return *this;
}
template <typename... OtherTypes> requires (sizeof...(OtherTypes) == sizeof...(Ts)
&& (true && ... && CAssignableFrom<Ts&, OtherTypes&&>))
FORCEINLINE constexpr TTuple& operator=(TTuple<OtherTypes...>&& InValue)
template <typename... Us> requires (sizeof...(Us) == sizeof...(Ts)
&& (true && ... && CAssignableFrom<Ts&, Us&&>))
FORCEINLINE constexpr TTuple& operator=(TTuple<Us...>&& InValue)
{
Helper::Assign(*this, MoveTemp(InValue));
return *this;
@ -294,6 +345,25 @@ public:
FORCEINLINE constexpr TTuple& operator=(const TTuple&) = default;
FORCEINLINE constexpr TTuple& operator=(TTuple&&) = default;
template <typename... Us> requires (sizeof...(Ts) == sizeof...(Us) && NAMESPACE_PRIVATE::CTTupleWeaklyEqualityComparable<TTypeSequence<Ts...>, TTypeSequence<Us...>>)
friend FORCEINLINE constexpr bool operator==(const TTuple& LHS, const TTuple<Us...>& RHS)
{
if constexpr (sizeof...(Ts) != sizeof...(Us)) return false;
return [&LHS, &RHS]<size_t... Indices>(TIndexSequence<Indices...>) -> bool
{
return (true && ... && (LHS.template GetValue<Indices>() == RHS.template GetValue<Indices>()));
}
(TMakeIndexSequence<sizeof...(Ts)>());
}
template <typename... Us> requires (sizeof...(Ts) == sizeof...(Us) && NAMESPACE_PRIVATE::CTTupleSynthThreeWayComparable<TTypeSequence<Ts...>, TTypeSequence<Us...>>)
friend FORCEINLINE constexpr TCommonComparisonCategory<TSynthThreeWayResult<Ts, Us>...> operator<=>(const TTuple& LHS, const TTuple<Us...>& RHS)
{
using R = TCommonComparisonCategory<TSynthThreeWayResult<Ts, Us>...>;
return NAMESPACE_PRIVATE::TTupleThreeWay<R, TMakeIndexSequence<sizeof...(Ts)>>::Do(LHS, RHS);
}
template <size_t I> requires (I < sizeof...(Ts)) FORCEINLINE constexpr decltype(auto) GetValue() & { return static_cast< NAMESPACE_PRIVATE::TTupleBasicElement<TTupleElement<I, TTuple<Ts...>>, I>& >(*this).GetValue(); }
template <size_t I> requires (I < sizeof...(Ts)) FORCEINLINE constexpr decltype(auto) GetValue() const & { return static_cast<const NAMESPACE_PRIVATE::TTupleBasicElement<TTupleElement<I, TTuple<Ts...>>, I>& >(*this).GetValue(); }
template <size_t I> requires (I < sizeof...(Ts)) FORCEINLINE constexpr decltype(auto) GetValue() volatile& { return static_cast< volatile NAMESPACE_PRIVATE::TTupleBasicElement<TTupleElement<I, TTuple<Ts...>>, I>& >(*this).GetValue(); }
@ -456,31 +526,6 @@ struct TTupleCatImpl
}
};
template <typename R, typename Indices>
struct TTupleThreeWay;
template <typename R, size_t I, size_t... Indices>
struct TTupleThreeWay<R, TIndexSequence<I, Indices...>>
{
template <typename LHSTupleType, typename RHSTupleType>
FORCEINLINE static constexpr R Do(const LHSTupleType& LHS, const RHSTupleType& RHS)
{
auto Result = SynthThreeWayCompare(LHS.template GetValue<I>(), RHS.template GetValue<I>());
if (Result != 0) return Result;
return TTupleThreeWay<R, TIndexSequence<Indices...>>::Do(LHS, RHS);
}
};
template <typename R>
struct TTupleThreeWay<R, TIndexSequence<>>
{
template <typename LHSTupleType, typename RHSTupleType>
FORCEINLINE static constexpr R Do(const LHSTupleType& LHS, const RHSTupleType& RHS)
{
return R::equivalent;
}
};
template <typename Indices>
struct TTupleVisitImpl;
@ -515,20 +560,6 @@ FORCEINLINE constexpr decltype(auto) TupleCat(TTupleTypes&&... Args)
else return NAMESPACE_PRIVATE::TTupleCatImpl<R>::Do(Forward<TTupleTypes>(Args)...);
}
template <typename... LHSTypes, typename... RHSTypes> requires (sizeof...(LHSTypes) != sizeof...(RHSTypes) || (true && ... && CWeaklyEqualityComparable<LHSTypes, RHSTypes>))
FORCEINLINE constexpr bool operator==(const TTuple<LHSTypes...>& LHS, const TTuple<RHSTypes...>& RHS)
{
if constexpr (sizeof...(LHSTypes) != sizeof...(RHSTypes)) return false;
return [&LHS, &RHS]<size_t... Indices>(TIndexSequence<Indices...>) -> bool { return (true && ... && (LHS.template GetValue<Indices>() == RHS.template GetValue<Indices>())); } (TMakeIndexSequence<sizeof...(LHSTypes)>());
}
template <typename... LHSTypes, typename... RHSTypes> requires (sizeof...(LHSTypes) == sizeof...(RHSTypes) && (true && ... && (CSynthThreeWayComparable<LHSTypes, RHSTypes>)))
FORCEINLINE constexpr TCommonComparisonCategory<TSynthThreeWayResult<LHSTypes, RHSTypes>...> operator<=>(const TTuple<LHSTypes...>& LHS, const TTuple<RHSTypes...>& RHS)
{
using R = TCommonComparisonCategory<TSynthThreeWayResult<LHSTypes, RHSTypes>...>;
return NAMESPACE_PRIVATE::TTupleThreeWay<R, TMakeIndexSequence<sizeof...(LHSTypes)>>::Do(LHS, RHS);
}
template <typename F, typename FirstTupleType, typename... TupleTypes>
requires (CTTuple<TRemoveReference<FirstTupleType>> && (true && ... && CTTuple<TRemoveReference<TupleTypes>>))
FORCEINLINE constexpr void VisitTuple(F&& Func, FirstTupleType&& FirstTuple, TupleTypes&&... Tuples)

View File

@ -195,6 +195,42 @@ public:
return *this;
}
friend constexpr bool operator==(const TVariant& LHS, const TVariant& RHS) requires (true && ... && CEqualityComparable<Ts>)
{
if (LHS.GetIndex() != RHS.GetIndex()) return false;
if (LHS.IsValid() == false) return true;
using FCompareImpl = bool(*)(const void*, const void*);
constexpr FCompareImpl CompareImpl[] = { [](const void* LHS, const void* RHS) -> bool { return *reinterpret_cast<const Ts*>(LHS) == *reinterpret_cast<const Ts*>(RHS); }... };
return CompareImpl[LHS.GetIndex()](&LHS.Value, &RHS.Value);
}
friend constexpr partial_ordering operator<=>(const TVariant& LHS, const TVariant& RHS) requires (true && ... && CSynthThreeWayComparable<Ts>)
{
if (LHS.GetIndex() != RHS.GetIndex()) return partial_ordering::unordered;
if (LHS.IsValid() == false) return partial_ordering::equivalent;
using FCompareImpl = partial_ordering(*)(const void*, const void*);
constexpr FCompareImpl CompareImpl[] = { [](const void* LHS, const void* RHS) -> partial_ordering { return SynthThreeWayCompare(*reinterpret_cast<const Ts*>(LHS), *reinterpret_cast<const Ts*>(RHS)); }...};
return CompareImpl[LHS.GetIndex()](&LHS.Value, &RHS.Value);
}
template <typename T> requires (!CBaseOf<TVariant, T> && CEqualityComparable<T>)
FORCEINLINE constexpr bool operator==(const T& InValue) const&
{
return HoldsAlternative<T>() ? GetValue<T>() == InValue : false;
}
template <typename T> requires (!CBaseOf<TVariant, T> && CEqualityComparable<T>)
FORCEINLINE constexpr partial_ordering operator<=>(const T& InValue) const&
{
return HoldsAlternative<T>() ? SynthThreeWayCompare(GetValue<T>(), InValue) : partial_ordering::unordered;
}
FORCEINLINE constexpr bool operator==(FInvalid) const& { return !IsValid(); }
template <size_t I, typename... ArgTypes> requires (I < sizeof...(Ts)
&& CConstructibleFrom<TVariantAlternative<I, TVariant<Ts...>>, ArgTypes...>)
FORCEINLINE constexpr TVariantAlternative<I, TVariant<Ts...>>& Emplace(ArgTypes&&... Args)
@ -317,42 +353,8 @@ private:
TAlignedUnion<1, Ts...> Value;
uint8 TypeIndex;
friend constexpr bool operator==(const TVariant& LHS, const TVariant& RHS) requires (true && ... && CEqualityComparable<Ts>)
{
if (LHS.GetIndex() != RHS.GetIndex()) return false;
if (LHS.IsValid() == false) return true;
using FCompareImpl = bool(*)(const void*, const void*);
constexpr FCompareImpl CompareImpl[] = { [](const void* LHS, const void* RHS) -> bool { return *reinterpret_cast<const Ts*>(LHS) == *reinterpret_cast<const Ts*>(RHS); }... };
return CompareImpl[LHS.GetIndex()](&LHS.Value, &RHS.Value);
}
friend constexpr partial_ordering operator<=>(const TVariant& LHS, const TVariant& RHS) requires (true && ... && CSynthThreeWayComparable<Ts>)
{
if (LHS.GetIndex() != RHS.GetIndex()) return partial_ordering::unordered;
if (LHS.IsValid() == false) return partial_ordering::equivalent;
using FCompareImpl = partial_ordering(*)(const void*, const void*);
constexpr FCompareImpl CompareImpl[] = { [](const void* LHS, const void* RHS) -> partial_ordering { return SynthThreeWayCompare(*reinterpret_cast<const Ts*>(LHS), *reinterpret_cast<const Ts*>(RHS)); }...};
return CompareImpl[LHS.GetIndex()](&LHS.Value, &RHS.Value);
}
};
template <typename T, typename... Ts> requires (!CBaseOf<TVariant<Ts...>, T> && CEqualityComparable<T>)
FORCEINLINE constexpr bool operator==(const TVariant<Ts...>& LHS, const T& RHS)
{
return LHS.template HoldsAlternative<T>() ? LHS.template GetValue<T>() == RHS : false;
}
template <typename... Ts>
FORCEINLINE constexpr bool operator==(const TVariant<Ts...>& LHS, FInvalid)
{
return !LHS.IsValid();
}
NAMESPACE_PRIVATE_BEGIN
template <typename F, typename... VariantTypes>