feat(miscellaneous): add TSynthThreeWay and the corresponding testing

This commit is contained in:
_Redstone_c_ 2022-03-30 12:07:48 +08:00
parent 782f5f5cb2
commit fd0bebd7be
2 changed files with 77 additions and 2 deletions

View File

@ -108,6 +108,14 @@ struct FTestStrongOrdering
friend strong_ordering operator<=>(FTestStrongOrdering LHS, FTestStrongOrdering RHS) { return LHS.Num <=> RHS.Num; } friend strong_ordering operator<=>(FTestStrongOrdering LHS, FTestStrongOrdering RHS) { return LHS.Num <=> RHS.Num; }
}; };
struct FTestSynth
{
int32 A;
FTestSynth(int32 InA) : A(InA) { }
friend bool operator==(FTestSynth LHS, FTestSynth RHS) { return LHS.A == RHS.A; }
friend bool operator< (FTestSynth LHS, FTestSynth RHS) { return LHS.A < RHS.A; }
};
NAMESPACE_UNNAMED_END NAMESPACE_UNNAMED_END
void TestCompare() void TestCompare()
@ -200,6 +208,17 @@ void TestCompare()
always_check((TCompareThreeWay<int32>()(0, 0) == strong_ordering::equal)); always_check((TCompareThreeWay<int32>()(0, 0) == strong_ordering::equal));
always_check((TCompareThreeWay<void>() (0, 0.0) == strong_ordering::equal)); always_check((TCompareThreeWay<void>() (0, 0.0) == strong_ordering::equal));
always_check(TSynthThreeWay{}(FTestPartialOrdering(-1), FTestPartialOrdering( 0)) == partial_ordering::less);
always_check(TSynthThreeWay{}(FTestPartialOrdering( 0), FTestPartialOrdering( 0)) == partial_ordering::equivalent);
always_check(TSynthThreeWay{}(FTestPartialOrdering( 0), FTestPartialOrdering(-1)) == partial_ordering::greater);
always_check(TSynthThreeWay{}(FTestPartialOrdering( 0, true), FTestPartialOrdering( 0, false)) == partial_ordering::unordered);
always_check(TSynthThreeWay{}(FTestSynth(-1), FTestSynth( 0)) == weak_ordering::less);
always_check(TSynthThreeWay{}(FTestSynth( 0), FTestSynth( 0)) == weak_ordering::equivalent);
always_check(TSynthThreeWay{}(FTestSynth( 0), FTestSynth(-1)) == weak_ordering::greater);
always_check((StrongOrder(0, 0) == strong_ordering::equal)); always_check((StrongOrder(0, 0) == strong_ordering::equal));
always_check((WeakOrder(0, 0) == strong_ordering::equal)); always_check((WeakOrder(0, 0) == strong_ordering::equal));
always_check((PartialOrder(0, 0) == strong_ordering::equal)); always_check((PartialOrder(0, 0) == strong_ordering::equal));

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Templates/Utility.h"
#include "Concepts/Concepts.h" #include "Concepts/Concepts.h"
#include "TypeTraits/TypeTraits.h" #include "TypeTraits/TypeTraits.h"
@ -52,7 +53,7 @@ concept CThreeWayComparableWith = CWeaklyEqualityComparableWith<T, U> && CPartia
CThreeWayComparable<T, OrderingType> && CThreeWayComparable<U, OrderingType> && CThreeWayComparable<T, OrderingType> && CThreeWayComparable<U, OrderingType> &&
CCommonReferenceWith<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&> && CCommonReferenceWith<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&> &&
CThreeWayComparable<typename TCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>::Type, OrderingType> && CThreeWayComparable<typename TCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>::Type, OrderingType> &&
requires(const TRemoveReference<T>::Type& A, const TRemoveReference<T>::Type& B) requires(const TRemoveReference<T>::Type& A, const TRemoveReference<U>::Type& B)
{ {
{ A <=> B } -> CThreeWayComparesAs<OrderingType>; { A <=> B } -> CThreeWayComparesAs<OrderingType>;
{ B <=> A } -> CThreeWayComparesAs<OrderingType>; { B <=> A } -> CThreeWayComparesAs<OrderingType>;
@ -67,7 +68,7 @@ struct TCompareThreeWayResult<T, U>
using Type = decltype(DeclVal<const typename TRemoveReference<T>::Type&>() <=> DeclVal<const typename TRemoveReference<U>::Type&>()); using Type = decltype(DeclVal<const typename TRemoveReference<T>::Type&>() <=> DeclVal<const typename TRemoveReference<U>::Type&>());
}; };
template <typename T = void> requires CSameAs<T, void> || CThreeWayComparable<T> template <typename T = void> requires (CSameAs<T, void> || CThreeWayComparable<T>)
struct TCompareThreeWay struct TCompareThreeWay
{ {
constexpr auto operator()(T&& LHS, T&& RHS) const constexpr auto operator()(T&& LHS, T&& RHS) const
@ -86,6 +87,61 @@ struct TCompareThreeWay<void>
} }
}; };
template <typename T, typename OrderingType = partial_ordering>
concept CSynthThreeWayComparable = CThreeWayComparable<T> ||
requires(const TRemoveReference<T>::Type& A, const TRemoveReference<T>::Type& B)
{
{ A < B } -> CBooleanTestable;
{ B < A } -> CBooleanTestable;
};
template <typename T, typename U, typename OrderingType = partial_ordering>
concept CSynthThreeWayComparableWith = CThreeWayComparableWith<T, U> ||
requires(const TRemoveReference<T>::Type& A, const TRemoveReference<U>::Type& B)
{
{ A < B } -> CBooleanTestable;
{ B < A } -> CBooleanTestable;
};
template <typename T = void> requires (CSameAs<T, void> || CSynthThreeWayComparable<T>)
struct TSynthThreeWay
{
constexpr auto operator()(T&& LHS, T&& RHS) const
{
if constexpr (CThreeWayComparable<T>)
{
return Forward<T>(LHS) <=> Forward<T>(RHS);
}
else
{
return Forward<T>(LHS) < Forward<T>(RHS) ? weak_ordering::less : Forward<T>(RHS) < Forward<T>(LHS) ? weak_ordering::greater : weak_ordering::equivalent;
}
}
};
template <>
struct TSynthThreeWay<void>
{
template <typename T, typename U> requires CSynthThreeWayComparableWith<T, U>
constexpr auto operator()(T&& LHS, U&& RHS) const
{
if constexpr (CThreeWayComparableWith<T, U>)
{
return Forward<T>(LHS) <=> Forward<U>(RHS);
}
else
{
return Forward<T>(LHS) < Forward<U>(RHS) ? weak_ordering::less : Forward<U>(RHS) < Forward<T>(LHS) ? weak_ordering::greater : weak_ordering::equivalent;
}
}
};
template <typename T, typename U = T>
struct TSynthThreeWayResult
{
using Type = decltype(TSynthThreeWay{}(DeclVal<const typename TRemoveReference<T>::Type&>(), DeclVal<const typename TRemoveReference<U>::Type&>()));
};
NAMESPACE_UNNAMED_BEGIN NAMESPACE_UNNAMED_BEGIN
inline constexpr decltype(NAMESPACE_STD::strong_order) StrongOrder; inline constexpr decltype(NAMESPACE_STD::strong_order) StrongOrder;