#pragma once #include "CoreTypes.h" #include "Templates/Utility.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 // ReSharper disable CppInconsistentNaming using partial_ordering = NAMESPACE_STD::partial_ordering; using weak_ordering = NAMESPACE_STD::weak_ordering; using strong_ordering = NAMESPACE_STD::strong_ordering; // ReSharper restore CppInconsistentNaming NAMESPACE_PRIVATE_BEGIN template struct TCommonComparisonCategoryBasic { }; template<> struct TCommonComparisonCategoryBasic<0> { using FType = strong_ordering; }; template<> struct TCommonComparisonCategoryBasic<2> { using FType = partial_ordering; }; template<> struct TCommonComparisonCategoryBasic<4> { using FType = weak_ordering; }; template<> struct TCommonComparisonCategoryBasic<6> { using FType = partial_ordering; }; template struct TCommonComparisonCategoryImpl : TCommonComparisonCategoryBasic <(0u | ... | ( CSameAs ? 0u : CSameAs ? 4u : CSameAs ? 2u : 1u ) )> { }; NAMESPACE_PRIVATE_END template using TCommonComparisonCategory = typename NAMESPACE_PRIVATE::TCommonComparisonCategoryImpl::FType; template concept CThreeWayComparesAs = CSameAs, OrderingType>; template concept CThreeWayComparable = CWeaklyEqualityComparable && CPartiallyOrdered && CCommonReference&, const TRemoveReference&> && requires(const TRemoveReference& A, const TRemoveReference& B, const TRemoveReference&, const TRemoveReference&>>& C) { { A <=> A } -> CThreeWayComparesAs; { B <=> B } -> CThreeWayComparesAs; { A <=> B } -> CThreeWayComparesAs; { B <=> A } -> CThreeWayComparesAs; { C <=> C } -> CThreeWayComparesAs; }; template requires (CThreeWayComparable) using TCompareThreeWayResult = decltype(DeclVal&>() <=> DeclVal&>()); template concept CSynthThreeWayComparable = CThreeWayComparable || CTotallyOrdered; template requires (CSynthThreeWayComparable) FORCEINLINE constexpr decltype(auto) SynthThreeWayCompare(T&& LHS, U&& RHS) { if constexpr (CThreeWayComparable) { 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 requires (CSynthThreeWayComparable) using TSynthThreeWayResult = decltype(SynthThreeWayCompare(DeclVal&>(), DeclVal&>())); NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END