diff --git a/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp b/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp index 1da865e..0ae8927 100644 --- a/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp +++ b/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp @@ -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 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() == 404); always_check(TempO.Get(500) == 404); diff --git a/Redcraft.Utility/Source/Public/Templates/Any.h b/Redcraft.Utility/Source/Public/Templates/Any.h index d739dce..d063216 100644 --- a/Redcraft.Utility/Source/Public/Templates/Any.h +++ b/Redcraft.Utility/Source/Public/Templates/Any.h @@ -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" @@ -236,6 +235,20 @@ public: return *this; } + + template requires (!CBaseOf> && NAMESPACE_PRIVATE::CFAnyPlaceable) + FORCEINLINE constexpr bool operator==(const T& InValue) const& + { + return HoldsAlternative() ? GetValue() == InValue : false; + } + + template requires (!CBaseOf> && NAMESPACE_PRIVATE::CFAnyPlaceable) + FORCEINLINE constexpr partial_ordering operator<=>(const T& InValue) const& + { + return HoldsAlternative() ? SynthThreeWayCompare(GetValue(), InValue) : partial_ordering::unordered; + } + + FORCEINLINE constexpr bool operator==(FInvalid) const& { return !IsValid(); } template requires (NAMESPACE_PRIVATE::CFAnyPlaceable && CConstructibleFrom, Ts&&...>) FORCEINLINE TDecay& Emplace(Ts&&... Args) @@ -527,17 +540,6 @@ private: FORCEINLINE constexpr void Invalidate() { TypeInfo = 0; } - template requires (!CBaseOf>) - friend FORCEINLINE constexpr bool operator==(const FAny& LHS, const T& RHS) - { - return LHS.template HoldsAlternative() ? LHS.template GetValue() == 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"); diff --git a/Redcraft.Utility/Source/Public/Templates/Function.h b/Redcraft.Utility/Source/Public/Templates/Function.h index d63ae06..5dfc674 100644 --- a/Redcraft.Utility/Source/Public/Templates/Function.h +++ b/Redcraft.Utility/Source/Public/Templates/Function.h @@ -482,6 +482,8 @@ public: FORCEINLINE ResultType operator()(Ts... Args) const& requires (CSameAs) { return CallImpl(Forward(Args)...); } FORCEINLINE ResultType operator()(Ts... Args) const&& requires (CSameAs) { return CallImpl(Forward(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(Forward(InValue)); } + template + TFunctionRef(const T&& InValue) = delete; + }; template @@ -718,7 +723,7 @@ public: return *this; } - + template requires (NAMESPACE_PRIVATE::TIsInvocableSignature>::Value && CConstructibleFrom, ArgTypes...> && CMoveConstructible> && CDestructible>) FORCEINLINE TDecay& Emplace(ArgTypes&&... Args) @@ -732,24 +737,6 @@ public: }; -template -FORCEINLINE constexpr bool operator==(const TFunctionRef& LHS, nullptr_t) -{ - return !LHS; -} - -template -FORCEINLINE constexpr bool operator==(const TFunction& LHS, nullptr_t) -{ - return !LHS; -} - -template -FORCEINLINE constexpr bool operator==(const TUniqueFunction& LHS, nullptr_t) -{ - return !LHS; -} - static_assert(sizeof(TFunction) == 64, "The byte size of TFunction is unexpected"); static_assert(sizeof(TUniqueFunction) == 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 8ec76ed..f622a80 100644 --- a/Redcraft.Utility/Source/Public/Templates/Optional.h +++ b/Redcraft.Utility/Source/Public/Templates/Optional.h @@ -16,6 +16,9 @@ class TOptional; NAMESPACE_PRIVATE_BEGIN +template struct TIsTOptional : FFalse { }; +template struct TIsTOptional> : FTrue { }; + template concept CTOptionalAllowUnwrappable = !(CConstructibleFrom& > @@ -33,6 +36,8 @@ concept CTOptionalAllowUnwrappable = NAMESPACE_PRIVATE_END +template concept CTOptional = NAMESPACE_PRIVATE::TIsTOptional>::Value; + template requires (CDestructible) class TOptional { @@ -192,6 +197,36 @@ public: return *this; } + + template requires (CWeaklyEqualityComparable) + friend FORCEINLINE constexpr bool operator==(const TOptional& LHS, const TOptional& RHS) + { + if (LHS.IsValid() != RHS.IsValid()) return false; + if (LHS.IsValid() == false) return true; + return *LHS == *RHS; + } + + template requires (CSynthThreeWayComparable) + friend FORCEINLINE constexpr partial_ordering operator<=>(const TOptional& LHS, const TOptional& RHS) + { + if (LHS.IsValid() != RHS.IsValid()) return partial_ordering::unordered; + if (LHS.IsValid() == false) return partial_ordering::equivalent; + return SynthThreeWayCompare(*LHS, *RHS); + } + + template requires (!CTOptional&& CWeaklyEqualityComparable) + FORCEINLINE constexpr bool operator==(const T& InValue) const& + { + return IsValid() ? GetValue() == InValue : false; + } + + template requires (!CTOptional&& CSynthThreeWayComparable) + 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 requires (CConstructibleFrom) FORCEINLINE constexpr OptionalType& Emplace(ArgTypes&&... Args) @@ -272,34 +307,6 @@ private: template TOptional(T) -> TOptional; -template requires (CWeaklyEqualityComparable) -FORCEINLINE constexpr bool operator==(const TOptional& LHS, const TOptional& RHS) -{ - if (LHS.IsValid() != RHS.IsValid()) return false; - if (LHS.IsValid() == false) return true; - return *LHS == *RHS; -} - -template requires (CSynthThreeWayComparable) -FORCEINLINE constexpr partial_ordering operator<=>(const TOptional& LHS, const TOptional& RHS) -{ - if (LHS.IsValid() != RHS.IsValid()) return partial_ordering::unordered; - if (LHS.IsValid() == false) return partial_ordering::equivalent; - return SynthThreeWayCompare(*LHS, *RHS); -} - -template requires (CWeaklyEqualityComparable) -FORCEINLINE constexpr bool operator==(const TOptional& LHS, const U& RHS) -{ - return LHS.IsValid() ? *LHS == RHS : false; -} - -template -FORCEINLINE constexpr bool operator==(const TOptional& LHS, FInvalid) -{ - return !LHS.IsValid(); -} - template requires (CDestructible) FORCEINLINE constexpr TOptional> MakeOptional(FInvalid) { @@ -318,15 +325,6 @@ FORCEINLINE constexpr TOptional MakeOptional(Ts&&... Args) return TOptional(InPlace, Forward(Args)...); } -NAMESPACE_PRIVATE_BEGIN - -template struct TIsTOptional : FFalse { }; -template struct TIsTOptional> : FTrue { }; - -NAMESPACE_PRIVATE_END - -template concept CTOptional = NAMESPACE_PRIVATE::TIsTOptional>::Value; - NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Templates/Tuple.h b/Redcraft.Utility/Source/Public/Templates/Tuple.h index edb2217..325a45f 100644 --- a/Redcraft.Utility/Source/Public/Templates/Tuple.h +++ b/Redcraft.Utility/Source/Public/Templates/Tuple.h @@ -226,6 +226,57 @@ public: }; +template +struct TTupleThreeWay; + +template +struct TTupleThreeWay> +{ + template + FORCEINLINE static constexpr R Do(const LHSTupleType& LHS, const RHSTupleType& RHS) + { + auto Result = SynthThreeWayCompare(LHS.template GetValue(), RHS.template GetValue()); + if (Result != 0) return Result; + return TTupleThreeWay>::Do(LHS, RHS); + } +}; + +template +struct TTupleThreeWay> +{ + template + FORCEINLINE static constexpr R Do(const LHSTupleType& LHS, const RHSTupleType& RHS) + { + return R::equivalent; + } +}; + +template struct TTTupleWeaklyEqualityComparable; + +template +struct TTTupleWeaklyEqualityComparable, TTypeSequence> + : TBoolConstant && TTTupleWeaklyEqualityComparable, TTypeSequence>::Value> +{ }; + +template <> +struct TTTupleWeaklyEqualityComparable, TTypeSequence<>> : FTrue { }; + +template +concept CTTupleWeaklyEqualityComparable = TTTupleWeaklyEqualityComparable::Value; + +template struct TTTupleSynthThreeWayComparable; + +template +struct TTTupleSynthThreeWayComparable, TTypeSequence> + : TBoolConstant && TTTupleSynthThreeWayComparable, TTypeSequence>::Value> +{ }; + +template <> +struct TTTupleSynthThreeWayComparable, TTypeSequence<>> : FTrue { }; + +template +concept CTTupleSynthThreeWayComparable = TTTupleSynthThreeWayComparable::Value; + NAMESPACE_PRIVATE_END template @@ -258,34 +309,34 @@ public: : Super(NAMESPACE_PRIVATE::ForwardingConstructor, Forward(Args)...) { } - template requires (sizeof...(OtherTypes) == sizeof...(Ts) - && (true && ... && CConstructibleFrom) - && NAMESPACE_PRIVATE::TTupleConvertCopy::Value) - FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo)) TTuple(const TTuple& InValue) + template requires (sizeof...(Us) == sizeof...(Ts) + && (true && ... && CConstructibleFrom) + && NAMESPACE_PRIVATE::TTupleConvertCopy::Value) + FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo)) TTuple(const TTuple& InValue) : Super(NAMESPACE_PRIVATE::OtherTupleConstructor, InValue) { } - template requires (sizeof...(OtherTypes) == sizeof...(Ts) - && (true && ... && CConstructibleFrom) - && NAMESPACE_PRIVATE::TTupleConvertMove::Value) - FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo)) TTuple(TTuple&& InValue) + template requires (sizeof...(Us) == sizeof...(Ts) + && (true && ... && CConstructibleFrom) + && NAMESPACE_PRIVATE::TTupleConvertMove::Value) + FORCEINLINE constexpr explicit (!(true && ... && CConvertibleTo)) TTuple(TTuple&& InValue) : Super(NAMESPACE_PRIVATE::OtherTupleConstructor, MoveTemp(InValue)) { } FORCEINLINE constexpr TTuple(const TTuple&) = default; FORCEINLINE constexpr TTuple(TTuple&&) = default; - template requires (sizeof...(OtherTypes) == sizeof...(Ts) - && (true && ... && CAssignableFrom)) - FORCEINLINE constexpr TTuple& operator=(const TTuple& InValue) + template requires (sizeof...(Us) == sizeof...(Ts) + && (true && ... && CAssignableFrom)) + FORCEINLINE constexpr TTuple& operator=(const TTuple& InValue) { Helper::Assign(*this, InValue); return *this; } - template requires (sizeof...(OtherTypes) == sizeof...(Ts) - && (true && ... && CAssignableFrom)) - FORCEINLINE constexpr TTuple& operator=(TTuple&& InValue) + template requires (sizeof...(Us) == sizeof...(Ts) + && (true && ... && CAssignableFrom)) + FORCEINLINE constexpr TTuple& operator=(TTuple&& InValue) { Helper::Assign(*this, MoveTemp(InValue)); return *this; @@ -293,6 +344,25 @@ public: FORCEINLINE constexpr TTuple& operator=(const TTuple&) = default; FORCEINLINE constexpr TTuple& operator=(TTuple&&) = default; + + template requires (sizeof...(Ts) == sizeof...(Us) && NAMESPACE_PRIVATE::CTTupleWeaklyEqualityComparable, TTypeSequence>) + friend FORCEINLINE constexpr bool operator==(const TTuple& LHS, const TTuple& RHS) + { + if constexpr (sizeof...(Ts) != sizeof...(Us)) return false; + + return [&LHS, &RHS](TIndexSequence) -> bool + { + return (true && ... && (LHS.template GetValue() == RHS.template GetValue())); + } + (TMakeIndexSequence()); + } + + template requires (sizeof...(Ts) == sizeof...(Us) && NAMESPACE_PRIVATE::CTTupleSynthThreeWayComparable, TTypeSequence>) + friend FORCEINLINE constexpr TCommonComparisonCategory...> operator<=>(const TTuple& LHS, const TTuple& RHS) + { + using R = TCommonComparisonCategory...>; + return NAMESPACE_PRIVATE::TTupleThreeWay>::Do(LHS, RHS); + } template requires (I < sizeof...(Ts)) FORCEINLINE constexpr decltype(auto) GetValue() & { return static_cast< NAMESPACE_PRIVATE::TTupleBasicElement>, I>& >(*this).GetValue(); } template requires (I < sizeof...(Ts)) FORCEINLINE constexpr decltype(auto) GetValue() const & { return static_cast>, I>& >(*this).GetValue(); } @@ -456,31 +526,6 @@ struct TTupleCatImpl } }; -template -struct TTupleThreeWay; - -template -struct TTupleThreeWay> -{ - template - FORCEINLINE static constexpr R Do(const LHSTupleType& LHS, const RHSTupleType& RHS) - { - auto Result = SynthThreeWayCompare(LHS.template GetValue(), RHS.template GetValue()); - if (Result != 0) return Result; - return TTupleThreeWay>::Do(LHS, RHS); - } -}; - -template -struct TTupleThreeWay> -{ - template - FORCEINLINE static constexpr R Do(const LHSTupleType& LHS, const RHSTupleType& RHS) - { - return R::equivalent; - } -}; - template struct TTupleVisitImpl; @@ -515,20 +560,6 @@ FORCEINLINE constexpr decltype(auto) TupleCat(TTupleTypes&&... Args) else return NAMESPACE_PRIVATE::TTupleCatImpl::Do(Forward(Args)...); } -template requires (sizeof...(LHSTypes) != sizeof...(RHSTypes) || (true && ... && CWeaklyEqualityComparable)) -FORCEINLINE constexpr bool operator==(const TTuple& LHS, const TTuple& RHS) -{ - if constexpr (sizeof...(LHSTypes) != sizeof...(RHSTypes)) return false; - return [&LHS, &RHS](TIndexSequence) -> bool { return (true && ... && (LHS.template GetValue() == RHS.template GetValue())); } (TMakeIndexSequence()); -} - -template requires (sizeof...(LHSTypes) == sizeof...(RHSTypes) && (true && ... && (CSynthThreeWayComparable))) -FORCEINLINE constexpr TCommonComparisonCategory...> operator<=>(const TTuple& LHS, const TTuple& RHS) -{ - using R = TCommonComparisonCategory...>; - return NAMESPACE_PRIVATE::TTupleThreeWay>::Do(LHS, RHS); -} - template requires (CTTuple> && (true && ... && CTTuple>)) FORCEINLINE constexpr void VisitTuple(F&& Func, FirstTupleType&& FirstTuple, TupleTypes&&... Tuples) diff --git a/Redcraft.Utility/Source/Public/Templates/Variant.h b/Redcraft.Utility/Source/Public/Templates/Variant.h index 70ee64e..b02a669 100644 --- a/Redcraft.Utility/Source/Public/Templates/Variant.h +++ b/Redcraft.Utility/Source/Public/Templates/Variant.h @@ -194,6 +194,42 @@ public: return *this; } + + friend constexpr bool operator==(const TVariant& LHS, const TVariant& RHS) requires (true && ... && CEqualityComparable) + { + 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(LHS) == *reinterpret_cast(RHS); }... }; + + return CompareImpl[LHS.GetIndex()](&LHS.Value, &RHS.Value); + } + + friend constexpr partial_ordering operator<=>(const TVariant& LHS, const TVariant& RHS) requires (true && ... && CSynthThreeWayComparable) + { + 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(LHS), *reinterpret_cast(RHS)); }...}; + + return CompareImpl[LHS.GetIndex()](&LHS.Value, &RHS.Value); + } + + template requires (!CBaseOf && CEqualityComparable) + FORCEINLINE constexpr bool operator==(const T& InValue) const& + { + return HoldsAlternative() ? GetValue() == InValue : false; + } + + template requires (!CBaseOf && CEqualityComparable) + FORCEINLINE constexpr partial_ordering operator<=>(const T& InValue) const& + { + return HoldsAlternative() ? SynthThreeWayCompare(GetValue(), InValue) : partial_ordering::unordered; + } + + FORCEINLINE constexpr bool operator==(FInvalid) const& { return !IsValid(); } template requires (I < sizeof...(Ts) && CConstructibleFrom>, ArgTypes...>) @@ -317,42 +353,8 @@ private: TAlignedUnion<1, Ts...> Value; uint8 TypeIndex; - friend constexpr bool operator==(const TVariant& LHS, const TVariant& RHS) requires (true && ... && CEqualityComparable) - { - 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(LHS) == *reinterpret_cast(RHS); }... }; - - return CompareImpl[LHS.GetIndex()](&LHS.Value, &RHS.Value); - } - - friend constexpr partial_ordering operator<=>(const TVariant& LHS, const TVariant& RHS) requires (true && ... && CSynthThreeWayComparable) - { - 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(LHS), *reinterpret_cast(RHS)); }...}; - - return CompareImpl[LHS.GetIndex()](&LHS.Value, &RHS.Value); - } - }; -template requires (!CBaseOf, T> && CEqualityComparable) -FORCEINLINE constexpr bool operator==(const TVariant& LHS, const T& RHS) -{ - return LHS.template HoldsAlternative() ? LHS.template GetValue() == RHS : false; -} - -template -FORCEINLINE constexpr bool operator==(const TVariant& LHS, FInvalid) -{ - return !LHS.IsValid(); -} - NAMESPACE_PRIVATE_BEGIN template