#pragma once #include "CoreTypes.h" #include "Templates/Utility.h" #include "Concepts/Concepts.h" #include "TypeTraits/TypeTraits.h" #include NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) // The result of the three-way comparison operator is the built-in type of the compiler, which is directly introduced here. typedef NAMESPACE_STD::partial_ordering partial_ordering; typedef NAMESPACE_STD::weak_ordering weak_ordering; typedef NAMESPACE_STD::strong_ordering strong_ordering; NAMESPACE_PRIVATE_BEGIN template struct TCommonComparisonCategory { using Type = void; }; template<> struct TCommonComparisonCategory<0> { using Type = strong_ordering; }; template<> struct TCommonComparisonCategory<2> { using Type = partial_ordering; }; template<> struct TCommonComparisonCategory<4> { using Type = weak_ordering; }; template<> struct TCommonComparisonCategory<6> { using Type = partial_ordering; }; NAMESPACE_PRIVATE_END template struct TCommonComparisonCategory : NAMESPACE_PRIVATE::TCommonComparisonCategory<(0u | ... | ( TIsSame::Value ? 0u : TIsSame::Value ? 4u : TIsSame::Value ? 2u : 1u ) )> { }; template concept CThreeWayComparesAs = CSameAs::Type, OrderingType>; template concept CThreeWayComparable = CWeaklyEqualityComparableWith && CPartiallyOrderedWith && requires(const TRemoveReference::Type& A, const TRemoveReference::Type& B) { { A <=> B } -> CThreeWayComparesAs; }; template concept CThreeWayComparableWith = CWeaklyEqualityComparableWith && CPartiallyOrderedWith && CThreeWayComparable && CThreeWayComparable && CCommonReferenceWith::Type&, const typename TRemoveReference::Type&> && CThreeWayComparable::Type&, const typename TRemoveReference::Type&>::Type, OrderingType> && requires(const TRemoveReference::Type& A, const TRemoveReference::Type& B) { { A <=> B } -> CThreeWayComparesAs; { B <=> A } -> CThreeWayComparesAs; }; template struct TCompareThreeWayResult { }; template requires CThreeWayComparableWith struct TCompareThreeWayResult { using Type = decltype(DeclVal::Type&>() <=> DeclVal::Type&>()); }; template concept CSynthThreeWayComparable = CThreeWayComparable || requires(const TRemoveReference::Type& A, const TRemoveReference::Type& B) { { A < B } -> CBooleanTestable; { B < A } -> CBooleanTestable; }; template concept CSynthThreeWayComparableWith = CThreeWayComparableWith || requires(const TRemoveReference::Type& A, const TRemoveReference::Type& B) { { A < B } -> CBooleanTestable; { B < A } -> CBooleanTestable; }; template requires CSynthThreeWayComparableWith constexpr decltype(auto) SynthThreeWayCompare(T&& LHS, U&& RHS) { if constexpr (CThreeWayComparableWith) { return Forward(LHS) <=> Forward(RHS); } else { return Forward(LHS) < Forward(RHS) ? weak_ordering::less : Forward(RHS) < Forward(LHS) ? weak_ordering::greater : weak_ordering::equivalent; } } template struct TSynthThreeWayResult { using Type = decltype(SynthThreeWayCompare(DeclVal::Type&>(), DeclVal::Type&>())); }; NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END