From 099cba38f4ec0d1b436c483e4cb9f45493152f55 Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Mon, 25 Apr 2022 23:04:19 +0800 Subject: [PATCH] refactor(templates): simplify TTuple implementation --- .../Source/Public/Templates/Tuple.h | 140 ++++++++---------- .../Source/Public/Templates/Variant.h | 20 +-- 2 files changed, 73 insertions(+), 87 deletions(-) diff --git a/Redcraft.Utility/Source/Public/Templates/Tuple.h b/Redcraft.Utility/Source/Public/Templates/Tuple.h index c7c8d0d..cbd004d 100644 --- a/Redcraft.Utility/Source/Public/Templates/Tuple.h +++ b/Redcraft.Utility/Source/Public/Templates/Tuple.h @@ -151,11 +151,6 @@ struct TTupleImpl, Types...> : TTupleElement struct TElementType : NAMESPACE_PRIVATE::TTupleElementType { }; - template struct TElementIndex : NAMESPACE_PRIVATE::TTupleElementIndex { }; - TTupleImpl() = default; template @@ -171,16 +166,24 @@ protected: TTupleImpl(const TTupleImpl&) = default; TTupleImpl(TTupleImpl&&) = default; + TTupleImpl& operator=(const TTupleImpl&) = default; + TTupleImpl& operator=(TTupleImpl&&) = default; + +}; + +template +struct TTupleHelper; + +template +struct TTupleHelper> +{ template static constexpr void Assign(LHSTupleType& LHS, RHSTupleType&& RHS) { - static_assert(ElementSize == LHS.ElementSize && LHS.ElementSize == RHS.ElementSize, "Cannot assign tuple from different size"); + static_assert(sizeof...(Indices) == LHS.ElementSize && LHS.ElementSize == RHS.ElementSize, "Cannot assign tuple from different size"); ((LHS.template GetValue() = Forward(RHS).template GetValue()), ...); } - TTupleImpl& operator=(const TTupleImpl&) = default; - TTupleImpl& operator=(TTupleImpl&&) = default; - template static constexpr auto Apply(F&& Func, TTupleType&& Arg) { @@ -211,11 +214,6 @@ protected: return T(Forward(Arg).template GetValue()...); } - template - static constexpr void Swap(TTupleType& A, TTupleType& B) - { - ((NAMESPACE_REDCRAFT::Swap(A.template GetValue(), B.template GetValue())), ...); - } }; NAMESPACE_PRIVATE_END @@ -226,13 +224,14 @@ struct TTuple : NAMESPACE_PRIVATE::TTupleImpl, Types private: using Super = NAMESPACE_PRIVATE::TTupleImpl, Types...>; + using Helper = NAMESPACE_PRIVATE::TTupleHelper>; public: - static constexpr size_t ElementSize = Super::ElementSize; + static constexpr size_t ElementSize = sizeof...(Types); - template struct TElementType : Super::template TElementType { }; - template struct TElementIndex : Super::template TElementIndex { }; + template struct TElementType : NAMESPACE_PRIVATE::TTupleElementType { }; + template struct TElementIndex : NAMESPACE_PRIVATE::TTupleElementIndex { }; TTuple() = default; @@ -297,7 +296,7 @@ public: && (true && ... && TIsAssignable::Value) constexpr TTuple& operator=(const TTuple& InValue) { - Super::Assign(*this, InValue); + Helper::Assign(*this, InValue); return *this; } @@ -305,7 +304,7 @@ public: && (true && ... && TIsAssignable::Value) constexpr TTuple& operator=(TTuple&& InValue) { - Super::Assign(*this, MoveTemp(InValue)); + Helper::Assign(*this, MoveTemp(InValue)); return *this; } @@ -330,50 +329,50 @@ public: template requires (TElementIndex::Value != INDEX_NONE) constexpr volatile T&& GetValue() volatile&& { return static_cast< volatile TTuple&&>(*this).GetValue::Value>(); } template requires (TElementIndex::Value != INDEX_NONE) constexpr const volatile T&& GetValue() const volatile&& { return static_cast(*this).GetValue::Value>(); } - template requires TIsInvocable::Value constexpr auto Apply(F&& Func) & { return Super::Apply(Forward(Func), static_cast< TTuple& >(*this)); } - template requires TIsInvocable::Value constexpr auto Apply(F&& Func) const & { return Super::Apply(Forward(Func), static_cast(*this)); } - template requires TIsInvocable::Value constexpr auto Apply(F&& Func) volatile& { return Super::Apply(Forward(Func), static_cast< volatile TTuple& >(*this)); } - template requires TIsInvocable::Value constexpr auto Apply(F&& Func) const volatile& { return Super::Apply(Forward(Func), static_cast(*this)); } - template requires TIsInvocable::Value constexpr auto Apply(F&& Func) && { return Super::Apply(Forward(Func), static_cast< TTuple&&>(*this)); } - template requires TIsInvocable::Value constexpr auto Apply(F&& Func) const && { return Super::Apply(Forward(Func), static_cast(*this)); } - template requires TIsInvocable::Value constexpr auto Apply(F&& Func) volatile&& { return Super::Apply(Forward(Func), static_cast< volatile TTuple&&>(*this)); } - template requires TIsInvocable::Value constexpr auto Apply(F&& Func) const volatile&& { return Super::Apply(Forward(Func), static_cast(*this)); } + template requires TIsInvocable::Value constexpr auto Apply(F&& Func) & { return Helper::Apply(Forward(Func), static_cast< TTuple& >(*this)); } + template requires TIsInvocable::Value constexpr auto Apply(F&& Func) const & { return Helper::Apply(Forward(Func), static_cast(*this)); } + template requires TIsInvocable::Value constexpr auto Apply(F&& Func) volatile& { return Helper::Apply(Forward(Func), static_cast< volatile TTuple& >(*this)); } + template requires TIsInvocable::Value constexpr auto Apply(F&& Func) const volatile& { return Helper::Apply(Forward(Func), static_cast(*this)); } + template requires TIsInvocable::Value constexpr auto Apply(F&& Func) && { return Helper::Apply(Forward(Func), static_cast< TTuple&&>(*this)); } + template requires TIsInvocable::Value constexpr auto Apply(F&& Func) const && { return Helper::Apply(Forward(Func), static_cast(*this)); } + template requires TIsInvocable::Value constexpr auto Apply(F&& Func) volatile&& { return Helper::Apply(Forward(Func), static_cast< volatile TTuple&&>(*this)); } + template requires TIsInvocable::Value constexpr auto Apply(F&& Func) const volatile&& { return Helper::Apply(Forward(Func), static_cast(*this)); } - template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) & { return Super::ApplyAfter(Forward(Func), static_cast< TTuple& >(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const & { return Super::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) volatile& { return Super::ApplyAfter(Forward(Func), static_cast< volatile TTuple& >(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const volatile& { return Super::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) && { return Super::ApplyAfter(Forward(Func), static_cast< TTuple&&>(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const && { return Super::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) volatile&& { return Super::ApplyAfter(Forward(Func), static_cast< volatile TTuple&&>(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const volatile&& { return Super::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) & { return Helper::ApplyAfter(Forward(Func), static_cast< TTuple& >(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const & { return Helper::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) volatile& { return Helper::ApplyAfter(Forward(Func), static_cast< volatile TTuple& >(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const volatile& { return Helper::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) && { return Helper::ApplyAfter(Forward(Func), static_cast< TTuple&&>(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const && { return Helper::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) volatile&& { return Helper::ApplyAfter(Forward(Func), static_cast< volatile TTuple&&>(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const volatile&& { return Helper::ApplyAfter(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) & { return Super::ApplyBefore(Forward(Func), static_cast< TTuple& >(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const & { return Super::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) volatile& { return Super::ApplyBefore(Forward(Func), static_cast< volatile TTuple& >(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const volatile& { return Super::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) && { return Super::ApplyBefore(Forward(Func), static_cast< TTuple&&>(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const && { return Super::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) volatile&& { return Super::ApplyBefore(Forward(Func), static_cast< volatile TTuple&&>(*this), Forward(Args)...); } - template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const volatile&& { return Super::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) & { return Helper::ApplyBefore(Forward(Func), static_cast< TTuple& >(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const & { return Helper::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) volatile& { return Helper::ApplyBefore(Forward(Func), static_cast< volatile TTuple& >(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const volatile& { return Helper::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) && { return Helper::ApplyBefore(Forward(Func), static_cast< TTuple&&>(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const && { return Helper::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) volatile&& { return Helper::ApplyBefore(Forward(Func), static_cast< volatile TTuple&&>(*this), Forward(Args)...); } + template requires TIsInvocable::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const volatile&& { return Helper::ApplyBefore(Forward(Func), static_cast(*this), Forward(Args)...); } - template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) & { return Super::Transform(Forward(Func), static_cast< TTuple& >(*this)); } - template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) const & { return Super::Transform(Forward(Func), static_cast(*this)); } - template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) volatile& { return Super::Transform(Forward(Func), static_cast< volatile TTuple& >(*this)); } - template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) const volatile& { return Super::Transform(Forward(Func), static_cast(*this)); } - template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) && { return Super::Transform(Forward(Func), static_cast< TTuple&&>(*this)); } - template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) const && { return Super::Transform(Forward(Func), static_cast(*this)); } - template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) volatile&& { return Super::Transform(Forward(Func), static_cast< volatile TTuple&&>(*this)); } - template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) const volatile&& { return Super::Transform(Forward(Func), static_cast(*this)); } + template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) & { return Helper::Transform(Forward(Func), static_cast< TTuple& >(*this)); } + template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) const & { return Helper::Transform(Forward(Func), static_cast(*this)); } + template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) volatile& { return Helper::Transform(Forward(Func), static_cast< volatile TTuple& >(*this)); } + template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) const volatile& { return Helper::Transform(Forward(Func), static_cast(*this)); } + template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) && { return Helper::Transform(Forward(Func), static_cast< TTuple&&>(*this)); } + template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) const && { return Helper::Transform(Forward(Func), static_cast(*this)); } + template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) volatile&& { return Helper::Transform(Forward(Func), static_cast< volatile TTuple&&>(*this)); } + template requires (true && ... && (TIsInvocable::Value && !TIsSame::Type>::Value)) constexpr auto Transform(F&& Func) const volatile&& { return Helper::Transform(Forward(Func), static_cast(*this)); } - template requires TIsConstructible::Value constexpr T Construct() & { return Super::template Construct(static_cast< TTuple& >(*this)); } - template requires TIsConstructible::Value constexpr T Construct() const & { return Super::template Construct(static_cast(*this)); } - template requires TIsConstructible::Value constexpr T Construct() volatile& { return Super::template Construct(static_cast< volatile TTuple& >(*this)); } - template requires TIsConstructible::Value constexpr T Construct() const volatile& { return Super::template Construct(static_cast(*this)); } - template requires TIsConstructible::Value constexpr T Construct() && { return Super::template Construct(static_cast< TTuple&&>(*this)); } - template requires TIsConstructible::Value constexpr T Construct() const && { return Super::template Construct(static_cast(*this)); } - template requires TIsConstructible::Value constexpr T Construct() volatile&& { return Super::template Construct(static_cast< volatile TTuple&&>(*this)); } - template requires TIsConstructible::Value constexpr T Construct() const volatile&& { return Super::template Construct(static_cast(*this)); } + template requires TIsConstructible::Value constexpr T Construct() & { return Helper::template Construct(static_cast< TTuple& >(*this)); } + template requires TIsConstructible::Value constexpr T Construct() const & { return Helper::template Construct(static_cast(*this)); } + template requires TIsConstructible::Value constexpr T Construct() volatile& { return Helper::template Construct(static_cast< volatile TTuple& >(*this)); } + template requires TIsConstructible::Value constexpr T Construct() const volatile& { return Helper::template Construct(static_cast(*this)); } + template requires TIsConstructible::Value constexpr T Construct() && { return Helper::template Construct(static_cast< TTuple&&>(*this)); } + template requires TIsConstructible::Value constexpr T Construct() const && { return Helper::template Construct(static_cast(*this)); } + template requires TIsConstructible::Value constexpr T Construct() volatile&& { return Helper::template Construct(static_cast< volatile TTuple&&>(*this)); } + template requires TIsConstructible::Value constexpr T Construct() const volatile&& { return Helper::template Construct(static_cast(*this)); } constexpr size_t GetTypeHash() const requires (true && ... && CHashable) { @@ -382,7 +381,7 @@ public: constexpr void Swap(TTuple& InValue) requires (true && ... && (TIsMoveConstructible::Value&& TIsSwappable::Value)) { - Super::Swap(*this, InValue); + [&A = *this, &B = InValue](TIndexSequence) { ((NAMESPACE_REDCRAFT::Swap(A.template GetValue(), B.template GetValue())), ...); } (TMakeIndexSequence()); } }; @@ -449,14 +448,14 @@ template struct TTupleCatMake, TIndexSequence> { template - struct TForward { using Type = typename TConditional::Value, typename TRemoveReference::Type&&, U>::Type; }; + struct ForwardType { using Type = typename TConditional::Value, typename TRemoveReference::Type&&, U>::Type; }; template static constexpr TTuple F(TTupleType&& InValue) { return TTuple ( - static_cast(InValue).template GetValue())>::Type> + static_cast(InValue).template GetValue())>::Type> ( Forward(InValue).template GetValue() )... @@ -493,19 +492,6 @@ struct TTupleCatImpl } }; -template -struct TTupleEqual; - -template -struct TTupleEqual> -{ - template - static constexpr bool F(const LHSTupleType& LHS, const RHSTupleType& RHS) - { - return (true && ... && (LHS.template GetValue() == RHS.template GetValue())); - } -}; - template struct TTupleThreeWay; @@ -549,7 +535,7 @@ template <> struct TTupleVisitImpl> { template - static constexpr void F(TupleTypes&&... Tuples) { } + static constexpr void F(TupleTypes&&... Tuples) { } }; NAMESPACE_PRIVATE_END @@ -569,7 +555,7 @@ template requires ((sizeof...(LHSTy constexpr bool operator==(const TTuple& LHS, const TTuple& RHS) { if constexpr (sizeof...(LHSTypes) != sizeof...(RHSTypes)) return false; - return NAMESPACE_PRIVATE::TTupleEqual>::F(LHS, RHS); + return[&LHS, &RHS](TIndexSequence) -> bool { return (true && ... && (LHS.template GetValue() == RHS.template GetValue())); } (TMakeIndexSequence()); } template requires ((sizeof...(LHSTypes) == sizeof...(RHSTypes)) && (true && ... && (CSynthThreeWayComparableWith))) diff --git a/Redcraft.Utility/Source/Public/Templates/Variant.h b/Redcraft.Utility/Source/Public/Templates/Variant.h index 62725b5..f68418c 100644 --- a/Redcraft.Utility/Source/Public/Templates/Variant.h +++ b/Redcraft.Utility/Source/Public/Templates/Variant.h @@ -219,13 +219,13 @@ struct TVariant constexpr TVariant(const TVariant& InValue) requires (true && ... && TIsCopyConstructible::Value) : TypeIndex(static_cast(InValue.GetIndex())) { - if (IsValid()) FHelper::CopyConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); + if (IsValid()) Helper::CopyConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); } constexpr TVariant(TVariant&& InValue) requires (true && ... && TIsMoveConstructible::Value) : TypeIndex(static_cast(InValue.GetIndex())) { - if (IsValid()) FHelper::MoveConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); + if (IsValid()) Helper::MoveConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); } template requires (I < AlternativeSize) @@ -264,11 +264,11 @@ struct TVariant return *this; } - if (GetIndex() == InValue.GetIndex()) FHelper::CopyAssignFuncs[InValue.GetIndex()](&Value, &InValue.Value); + if (GetIndex() == InValue.GetIndex()) Helper::CopyAssignFuncs[InValue.GetIndex()](&Value, &InValue.Value); else { Reset(); - FHelper::CopyConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); + Helper::CopyConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); TypeIndex = static_cast(InValue.GetIndex()); } @@ -285,11 +285,11 @@ struct TVariant return *this; } - if (GetIndex() == InValue.GetIndex()) FHelper::MoveAssignFuncs[InValue.GetIndex()](&Value, &InValue.Value); + if (GetIndex() == InValue.GetIndex()) Helper::MoveAssignFuncs[InValue.GetIndex()](&Value, &InValue.Value); else { Reset(); - FHelper::MoveConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); + Helper::MoveConstructFuncs[InValue.GetIndex()](&Value, &InValue.Value); TypeIndex = static_cast(InValue.GetIndex()); } @@ -421,7 +421,7 @@ struct TVariant if constexpr (!(true && ... && TIsTriviallyDestructible::Value)) { - FHelper::DestroyFuncs[GetIndex()](&Value); + Helper::DestroyFuncs[GetIndex()](&Value); } TypeIndex = static_cast(INDEX_NONE); @@ -453,7 +453,7 @@ struct TVariant if (GetIndex() == InValue.GetIndex()) { - FHelper::SwapFuncs[GetIndex()](&Value, &InValue.Value); + Helper::SwapFuncs[GetIndex()](&Value, &InValue.Value); return; } @@ -464,7 +464,7 @@ struct TVariant private: - using FHelper = NAMESPACE_PRIVATE::TVariantHelper; + using Helper = NAMESPACE_PRIVATE::TVariantHelper; TAlignedUnion<1, Types...>::Type Value; uint8 TypeIndex; @@ -473,7 +473,7 @@ private: { if (LHS.GetIndex() != RHS.GetIndex()) return false; if (LHS.IsValid() == false) return true; - return FHelper::EqualityOperatorFuncs[LHS.GetIndex()](&LHS.Value, &RHS.Value); + return Helper::EqualityOperatorFuncs[LHS.GetIndex()](&LHS.Value, &RHS.Value); } };