refactor(typetraits): simplifies concept selection and removes the concept of bitwise operations
This commit is contained in:
parent
ee46d84897
commit
97910be70c
@ -152,7 +152,6 @@ struct FTracker
|
||||
~FTracker() { always_check(Status == 3); Status = -1; }
|
||||
FTracker& operator=(const FTracker&) { always_check(Status == 4); Status = -1; return *this; }
|
||||
FTracker& operator=(FTracker&&) { always_check(Status == 5); Status = -1; return *this; }
|
||||
friend bool operator==(const FTracker&, const FTracker&) { always_check(Status == 6); Status = -1; return true; }
|
||||
};
|
||||
|
||||
int32 FTracker::Status = -1;
|
||||
@ -181,10 +180,6 @@ void TestMemoryOperator()
|
||||
Memory::MoveConstruct(PtrA, PtrB);
|
||||
always_check(FTracker::Status == -1);
|
||||
|
||||
FTracker::Status = -1;
|
||||
Memory::RelocateConstruct(PtrA, PtrB);
|
||||
always_check(FTracker::Status == -1);
|
||||
|
||||
FTracker::Status = 3;
|
||||
Memory::Destruct(PtrA);
|
||||
always_check(FTracker::Status == -1);
|
||||
@ -197,11 +192,6 @@ void TestMemoryOperator()
|
||||
Memory::MoveAssign(PtrA, PtrB);
|
||||
always_check(FTracker::Status == -1);
|
||||
|
||||
FTracker::Status = 6;
|
||||
const bool bResult = Memory::Compare(PtrA, PtrB);
|
||||
always_check(bResult);
|
||||
always_check(FTracker::Status == -1);
|
||||
|
||||
Memory::Free(PtrA);
|
||||
Memory::Free(PtrB);
|
||||
}
|
||||
|
@ -110,8 +110,11 @@ 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; }
|
||||
friend bool operator<=(FTestSynth LHS, FTestSynth RHS) { return LHS.A <= RHS.A; }
|
||||
friend bool operator==(FTestSynth LHS, FTestSynth RHS) { return LHS.A == RHS.A; }
|
||||
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
|
||||
@ -194,8 +197,8 @@ void TestCompare()
|
||||
always_check(CThreeWayComparable<FTestWeakOrdering>);
|
||||
always_check(CThreeWayComparable<FTestStrongOrdering>);
|
||||
|
||||
always_check((CThreeWayComparableWith<bool, bool>));
|
||||
always_check((CThreeWayComparableWith<int16, int32>));
|
||||
always_check((CThreeWayComparable<bool, bool>));
|
||||
always_check((CThreeWayComparable<int16, int32>));
|
||||
|
||||
always_check((CSameAs<TCompareThreeWayResult<int32 >::Type, strong_ordering >));
|
||||
always_check((CSameAs<TCompareThreeWayResult<float >::Type, partial_ordering>));
|
||||
|
@ -459,15 +459,15 @@ void TestTypeTraits()
|
||||
always_check((CSameAs<int64, TCommonReference<int8, int32, int64>::Type>));
|
||||
always_check((CSameAs<double, TCommonReference<float, double>::Type>));
|
||||
|
||||
always_check((CCommonWith<int32, int32>));
|
||||
always_check((CCommonWith<int8, int32>));
|
||||
always_check((CCommonWith<float, double>));
|
||||
always_check(!(CCommonWith<FTestStructA, int32>));
|
||||
always_check((CCommonType<int32, int32>));
|
||||
always_check((CCommonType<int8, int32>));
|
||||
always_check((CCommonType<float, double>));
|
||||
always_check(!(CCommonType<FTestStructA, int32>));
|
||||
|
||||
always_check((CCommonReferenceWith<int8, int32>));
|
||||
always_check((CCommonReferenceWith<float, int32>));
|
||||
always_check((CCommonReferenceWith<float, double>));
|
||||
always_check(!(CCommonReferenceWith<FTestStructA, double>));
|
||||
always_check((CCommonReference<int8, int32>));
|
||||
always_check((CCommonReference<float, int32>));
|
||||
always_check((CCommonReference<float, double>));
|
||||
always_check(!(CCommonReference<FTestStructA, double>));
|
||||
|
||||
// Swappable.h
|
||||
|
||||
@ -476,7 +476,7 @@ void TestTypeTraits()
|
||||
always_check(CSwappable<FTestStructN>);
|
||||
always_check(!CSwappable<FSingleton>);
|
||||
|
||||
always_check((CSwappableWith<int32&, int32&>));
|
||||
always_check((CSwappable<int32&, int32&>));
|
||||
|
||||
// CopyQualifiers.h
|
||||
|
||||
@ -585,16 +585,16 @@ void TestTypeTraits()
|
||||
always_check((CEqualityComparable<int32>));
|
||||
always_check(!(CEqualityComparable<FTestStructA>));
|
||||
|
||||
always_check((CEqualityComparableWith<int32, int32>));
|
||||
always_check((CEqualityComparableWith<int32, int64>));
|
||||
always_check(!(CEqualityComparableWith<FTestStructA, FTestStructA>));
|
||||
always_check((CEqualityComparable<int32, int32>));
|
||||
always_check((CEqualityComparable<int32, int64>));
|
||||
always_check(!(CEqualityComparable<FTestStructA, FTestStructA>));
|
||||
|
||||
always_check((CTotallyOrdered<int32>));
|
||||
always_check(!(CTotallyOrdered<FTestStructA>));
|
||||
|
||||
always_check((CTotallyOrderedWith<int32, int32>));
|
||||
always_check((CTotallyOrderedWith<int32, int64>));
|
||||
always_check(!(CTotallyOrderedWith<FTestStructA, FTestStructA>));
|
||||
always_check((CTotallyOrdered<int32, int32>));
|
||||
always_check((CTotallyOrdered<int32, int64>));
|
||||
always_check(!(CTotallyOrdered<FTestStructA, FTestStructA>));
|
||||
|
||||
}
|
||||
|
||||
|
@ -15,13 +15,9 @@ template <typename ElementType>
|
||||
requires CDefaultConstructible<ElementType>
|
||||
FORCEINLINE void DefaultConstruct(ElementType* Address, size_t Count = 1)
|
||||
{
|
||||
if constexpr (CZeroConstructible<ElementType>)
|
||||
if constexpr (!CTriviallyDefaultConstructible<ElementType>)
|
||||
{
|
||||
Memory::Memset(Address, 0, sizeof(ElementType) * Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
ElementType* Element = (ElementType*)Address;
|
||||
ElementType* Element = Address;
|
||||
while (Count)
|
||||
{
|
||||
new (Element) ElementType;
|
||||
@ -35,7 +31,7 @@ template <typename DestinationElementType, typename SourceElementType = Destinat
|
||||
requires CConstructibleFrom<DestinationElementType, const SourceElementType&>
|
||||
FORCEINLINE void Construct(DestinationElementType* Destination, const SourceElementType* Source, size_t Count = 1)
|
||||
{
|
||||
if constexpr (CBitwiseConstructible<DestinationElementType, const SourceElementType>)
|
||||
if constexpr (CTriviallyConstructibleFrom<DestinationElementType, const SourceElementType> && sizeof(DestinationElementType) == sizeof(SourceElementType))
|
||||
{
|
||||
Memory::Memcpy(Destination, Source, sizeof(SourceElementType) * Count);
|
||||
}
|
||||
@ -91,43 +87,6 @@ FORCEINLINE void MoveConstruct(ElementType* Destination, ElementType* Source, si
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DestinationElementType, typename SourceElementType = DestinationElementType>
|
||||
requires CConstructibleFrom<DestinationElementType, SourceElementType&&> && CDestructible<SourceElementType>
|
||||
FORCEINLINE void RelocateConstruct(DestinationElementType* Destination, SourceElementType* Source, size_t Count = 1)
|
||||
{
|
||||
if constexpr (CBitwiseRelocatable<DestinationElementType, SourceElementType>)
|
||||
{
|
||||
Memory::Memmove(Destination, Source, sizeof(SourceElementType) * Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (Count)
|
||||
{
|
||||
typedef SourceElementType RelocateConstructItemsElementTypeTypedef;
|
||||
|
||||
new (Destination) DestinationElementType(MoveTemp(*Source));
|
||||
++(DestinationElementType*&)Destination;
|
||||
(Source++)->RelocateConstructItemsElementTypeTypedef::~RelocateConstructItemsElementTypeTypedef();
|
||||
--Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
requires CDestructible<ElementType>
|
||||
FORCEINLINE void Destruct(ElementType* Element, size_t Count = 1)
|
||||
{
|
||||
if constexpr (!CTriviallyDestructible<ElementType>)
|
||||
{
|
||||
while (Count)
|
||||
{
|
||||
Element->~ElementType();
|
||||
++Element;
|
||||
--Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
requires CCopyAssignable<ElementType>
|
||||
FORCEINLINE void CopyAssign(ElementType* Destination, const ElementType* Source, size_t Count = 1)
|
||||
@ -152,7 +111,7 @@ template <typename ElementType>
|
||||
requires CMoveAssignable<ElementType>
|
||||
FORCEINLINE void MoveAssign(ElementType* Destination, ElementType* Source, size_t Count = 1)
|
||||
{
|
||||
if constexpr (CTriviallyCopyConstructible<ElementType>)
|
||||
if constexpr (CTriviallyMoveAssignable<ElementType>)
|
||||
{
|
||||
Memory::Memmove(Destination, Source, sizeof(ElementType) * Count);
|
||||
}
|
||||
@ -169,25 +128,17 @@ FORCEINLINE void MoveAssign(ElementType* Destination, ElementType* Source, size_
|
||||
}
|
||||
|
||||
template <typename ElementType>
|
||||
requires CEqualityComparable<ElementType>
|
||||
FORCEINLINE bool Compare(const ElementType* LHS, const ElementType* RHS, size_t Count = 1)
|
||||
requires CDestructible<ElementType>
|
||||
FORCEINLINE void Destruct(ElementType* Element, size_t Count = 1)
|
||||
{
|
||||
if constexpr (CBitwiseComparable<ElementType>)
|
||||
{
|
||||
return !Memory::Memcmp(LHS, RHS, sizeof(ElementType) * Count);
|
||||
}
|
||||
else
|
||||
if constexpr (!CTriviallyDestructible<ElementType>)
|
||||
{
|
||||
while (Count)
|
||||
{
|
||||
if (!(*LHS == *RHS)) return false;
|
||||
|
||||
++LHS;
|
||||
++RHS;
|
||||
Element->~ElementType();
|
||||
++Element;
|
||||
--Count;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,53 +40,35 @@ struct TCommonComparisonCategory
|
||||
template <typename T, typename OrderingType>
|
||||
concept CThreeWayComparesAs = CSameAs<typename TCommonComparisonCategory<T, OrderingType>::Type, OrderingType>;
|
||||
|
||||
template <typename T, typename OrderingType = partial_ordering>
|
||||
concept CThreeWayComparable = CWeaklyEqualityComparableWith<T, T> && CPartiallyOrderedWith<T, T> &&
|
||||
requires(const TRemoveReference<T>::Type& A, const TRemoveReference<T>::Type& B)
|
||||
{
|
||||
{ A <=> B } -> CThreeWayComparesAs<OrderingType>;
|
||||
};
|
||||
|
||||
template <typename T, typename U, typename OrderingType = partial_ordering>
|
||||
concept CThreeWayComparableWith = CWeaklyEqualityComparableWith<T, U> && CPartiallyOrderedWith<T, U> &&
|
||||
CThreeWayComparable<T, OrderingType> && CThreeWayComparable<U, OrderingType> &&
|
||||
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> &&
|
||||
requires(const TRemoveReference<T>::Type& A, const TRemoveReference<U>::Type& B)
|
||||
template <typename T, typename U = T, typename OrderingType = partial_ordering>
|
||||
concept CThreeWayComparable = CWeaklyEqualityComparable<T, U> && CPartiallyOrdered<T, U>
|
||||
&& CCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>
|
||||
&& requires(const typename TRemoveReference<T>::Type& A, const typename TRemoveReference<U>::Type& B,
|
||||
const typename TRemoveReference<typename TCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>::Type>::Type& C)
|
||||
{
|
||||
{ A <=> A } -> CThreeWayComparesAs<OrderingType>;
|
||||
{ B <=> B } -> CThreeWayComparesAs<OrderingType>;
|
||||
{ A <=> B } -> CThreeWayComparesAs<OrderingType>;
|
||||
{ B <=> A } -> CThreeWayComparesAs<OrderingType>;
|
||||
{ C <=> C } -> CThreeWayComparesAs<OrderingType>;
|
||||
};
|
||||
|
||||
template <typename T, typename U = T>
|
||||
struct TCompareThreeWayResult { };
|
||||
|
||||
template <typename T, typename U> requires CThreeWayComparableWith<T, U>
|
||||
template <typename T, typename U> requires CThreeWayComparable<T, U>
|
||||
struct TCompareThreeWayResult<T, U>
|
||||
{
|
||||
using Type = decltype(DeclVal<const typename TRemoveReference<T>::Type&>() <=> DeclVal<const typename TRemoveReference<U>::Type&>());
|
||||
};
|
||||
|
||||
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 = T, typename OrderingType = partial_ordering>
|
||||
concept CSynthThreeWayComparable = CThreeWayComparable<T, U> || CTotallyOrdered<T, U>;
|
||||
|
||||
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, typename U> requires CSynthThreeWayComparableWith<T, U>
|
||||
template <typename T, typename U = T> requires CSynthThreeWayComparable<T, U>
|
||||
constexpr decltype(auto) SynthThreeWayCompare(T&& LHS, U&& RHS)
|
||||
{
|
||||
if constexpr (CThreeWayComparableWith<T, U>)
|
||||
if constexpr (CThreeWayComparable<T, U>)
|
||||
{
|
||||
return Forward<T>(LHS) <=> Forward<U>(RHS);
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ private:
|
||||
template <typename T>
|
||||
TOptional(T) -> TOptional<T>;
|
||||
|
||||
template <typename T, typename U> requires CWeaklyEqualityComparableWith<T, U>
|
||||
template <typename T, typename U> requires CWeaklyEqualityComparable<T, U>
|
||||
constexpr bool operator==(const TOptional<T>& LHS, const TOptional<U>& RHS)
|
||||
{
|
||||
if (LHS.IsValid() != RHS.IsValid()) return false;
|
||||
@ -262,7 +262,7 @@ constexpr bool operator==(const TOptional<T>& LHS, const TOptional<U>& RHS)
|
||||
return *LHS == *RHS;
|
||||
}
|
||||
|
||||
template <typename T, typename U> requires CSynthThreeWayComparableWith<T, U>
|
||||
template <typename T, typename U> requires CSynthThreeWayComparable<T, U>
|
||||
constexpr partial_ordering operator<=>(const TOptional<T>& LHS, const TOptional<U>& RHS)
|
||||
{
|
||||
if (LHS.IsValid() != RHS.IsValid()) return partial_ordering::unordered;
|
||||
@ -270,7 +270,7 @@ constexpr partial_ordering operator<=>(const TOptional<T>& LHS, const TOptional<
|
||||
return SynthThreeWayCompare(*LHS, *RHS);
|
||||
}
|
||||
|
||||
template <typename T, typename U> requires CWeaklyEqualityComparableWith<T, U>
|
||||
template <typename T, typename U> requires CWeaklyEqualityComparable<T, U>
|
||||
constexpr bool operator==(const TOptional<T>& LHS, const U& RHS)
|
||||
{
|
||||
return LHS.IsValid() ? *LHS == RHS : false;
|
||||
|
@ -557,14 +557,14 @@ constexpr auto TupleCat(TTupleTypes&&... Args)
|
||||
else return NAMESPACE_PRIVATE::TTupleCatImpl<R>::F(Forward<TTupleTypes>(Args)...);
|
||||
}
|
||||
|
||||
template <typename... LHSTypes, typename... RHSTypes> requires ((sizeof...(LHSTypes) != sizeof...(RHSTypes)) || (true && ... && CWeaklyEqualityComparableWith<LHSTypes, RHSTypes>))
|
||||
template <typename... LHSTypes, typename... RHSTypes> requires ((sizeof...(LHSTypes) != sizeof...(RHSTypes)) || (true && ... && CWeaklyEqualityComparable<LHSTypes, RHSTypes>))
|
||||
constexpr bool operator==(const TTuple<LHSTypes...>& LHS, const TTuple<RHSTypes...>& RHS)
|
||||
{
|
||||
if constexpr (sizeof...(LHSTypes) != sizeof...(RHSTypes)) return false;
|
||||
return[&LHS, &RHS]<size_t... Indices>(TIndexSequence<Indices...>) -> bool { return (true && ... && (LHS.template GetValue<Indices>() == RHS.template GetValue<Indices>())); } (TMakeIndexSequence<sizeof...(LHSTypes)>());
|
||||
}
|
||||
|
||||
template <typename... LHSTypes, typename... RHSTypes> requires ((sizeof...(LHSTypes) == sizeof...(RHSTypes)) && (true && ... && (CSynthThreeWayComparableWith<LHSTypes, RHSTypes>)))
|
||||
template <typename... LHSTypes, typename... RHSTypes> requires ((sizeof...(LHSTypes) == sizeof...(RHSTypes)) && (true && ... && (CSynthThreeWayComparable<LHSTypes, RHSTypes>)))
|
||||
constexpr typename TCommonComparisonCategory<typename TSynthThreeWayResult<LHSTypes, RHSTypes>::Type...>::Type operator<=>(const TTuple<LHSTypes...>& LHS, const TTuple<RHSTypes...>& RHS)
|
||||
{
|
||||
using R = typename TCommonComparisonCategory<typename TSynthThreeWayResult<LHSTypes, RHSTypes>::Type...>::Type;
|
||||
|
@ -1,68 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "TypeTraits/PrimaryType.h"
|
||||
#include "TypeTraits/HelperClasses.h"
|
||||
#include "TypeTraits/CompositeType.h"
|
||||
#include "TypeTraits/Miscellaneous.h"
|
||||
#include "TypeTraits/SupportedOperations.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
// Assume that all operands of bitwise operations have the same size
|
||||
|
||||
// Specialize these template classes for user-defined types
|
||||
template <typename T> struct TIsZeroConstructible;
|
||||
template <typename T, typename U> struct TIsBitwiseConstructible;
|
||||
template <typename T, typename U> struct TIsBitwiseRelocatable;
|
||||
template <typename T> struct TIsBitwiseComparable;
|
||||
|
||||
// Normal use of these concepts
|
||||
template <typename T> concept CZeroConstructible = TIsZeroConstructible<T>::Value;
|
||||
template <typename T, typename U = T> concept CBitwiseConstructible = TIsBitwiseConstructible<T, U>::Value;
|
||||
template <typename T, typename U = T> concept CBitwiseRelocatable = TIsBitwiseRelocatable<T, U>::Value;
|
||||
template <typename T> concept CBitwiseComparable = TIsBitwiseComparable<T>::Value;
|
||||
|
||||
// Default constructible enum, arithmetic and pointer are zero constructible
|
||||
template <typename T> struct TIsZeroConstructible : TBoolConstant<CDefaultConstructible<T> && (CEnum<T> || CArithmetic<T> || CPointer<T>)> { };
|
||||
|
||||
// Constructing a const T is the same as constructing a T
|
||||
template <typename T> struct TIsZeroConstructible<const T> : TIsZeroConstructible<T> { };
|
||||
|
||||
// T can always be bitwise constructed from itself if it is trivially copy constructible
|
||||
template <typename T, typename U> struct TIsBitwiseConstructible : TBoolConstant<CSameAs<T, U> ? CTriviallyCopyConstructible<T> : false> { };
|
||||
|
||||
// Constructing a const T is the same as constructing a T
|
||||
template <typename T, typename U> struct TIsBitwiseConstructible<const T, U> : TIsBitwiseConstructible<T, U> { };
|
||||
|
||||
// Const pointers can be bitwise constructed from non-const pointers
|
||||
template <typename T> struct TIsBitwiseConstructible<const T*, T*> : FTrue { };
|
||||
|
||||
// Unsigned types can be bitwise converted to their signed equivalents, and vice versa
|
||||
template <> struct TIsBitwiseConstructible<uint8, int8> : FTrue { };
|
||||
template <> struct TIsBitwiseConstructible< int8, uint8> : FTrue { };
|
||||
template <> struct TIsBitwiseConstructible<uint16, int16> : FTrue { };
|
||||
template <> struct TIsBitwiseConstructible< int16, uint16> : FTrue { };
|
||||
template <> struct TIsBitwiseConstructible<uint32, int32> : FTrue { };
|
||||
template <> struct TIsBitwiseConstructible< int32, uint32> : FTrue { };
|
||||
template <> struct TIsBitwiseConstructible<uint64, int64> : FTrue { };
|
||||
template <> struct TIsBitwiseConstructible< int64, uint64> : FTrue { };
|
||||
|
||||
// WARNING: T is bitwise relocatable from itself by default
|
||||
// T is bitwise relocatable from U, if U is trivially destructible and can be constructed bitwise to T
|
||||
template <typename T, typename U> struct TIsBitwiseRelocatable : TBoolConstant<CSameAs<T, U> ? true : CTriviallyDestructible<U> && CBitwiseConstructible<T, U>> { };
|
||||
|
||||
// Constructing a const T is the same as constructing a T
|
||||
template <typename T, typename U> struct TIsBitwiseRelocatable<const T, U> : TIsBitwiseRelocatable<T, U> { };
|
||||
|
||||
// Enum, arithmetic and pointer are zero constructible
|
||||
template <typename T> struct TIsBitwiseComparable : TBoolConstant<CEnum<T> || CArithmetic<T> || CPointer<T>> { };
|
||||
|
||||
// Constructing a const T is the same as constructing a T
|
||||
template <typename T> struct TIsBitwiseComparable<const T> : TIsBitwiseComparable<T> { };
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
@ -9,8 +9,8 @@ NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
template <typename T>
|
||||
concept CBooleanTestable = CConvertibleTo<T, bool> &&
|
||||
requires(T && B) { { !Forward<T>(B) } -> CConvertibleTo<bool>; };
|
||||
concept CBooleanTestable = CConvertibleTo<T, bool>
|
||||
&& requires(T && B) { { !Forward<T>(B) } -> CConvertibleTo<bool>; };
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
|
@ -24,30 +24,16 @@ NAMESPACE_PRIVATE_END
|
||||
template <typename... Types> struct TCommonType : TConditional<NAMESPACE_PRIVATE::CCommonType<Types...>, NAMESPACE_PRIVATE::TCommonType<Types...>, NAMESPACE_PRIVATE::FNoopStruct>::Type { };
|
||||
template <typename... Types> struct TCommonReference : TConditional<NAMESPACE_PRIVATE::CCommonReference<Types...>, NAMESPACE_PRIVATE::TCommonReference<Types...>, NAMESPACE_PRIVATE::FNoopStruct>::Type { };
|
||||
|
||||
template <typename T, typename U>
|
||||
concept CCommonReferenceWith =
|
||||
requires
|
||||
{
|
||||
typename TCommonReference<T, U>::Type;
|
||||
typename TCommonReference<U, T>::Type;
|
||||
} &&
|
||||
CSameAs<typename TCommonReference<T, U>::Type, typename TCommonReference<U, T>::Type> &&
|
||||
CConvertibleTo<T, typename TCommonReference<T, U>::Type>&&
|
||||
CConvertibleTo<U, typename TCommonReference<T, U>::Type>;
|
||||
template <typename... Ts>
|
||||
concept CCommonReference =
|
||||
requires { typename TCommonReference<Ts...>::Type; }
|
||||
&& (true && ... && CConvertibleTo<Ts, typename TCommonReference<Ts...>::Type>);
|
||||
|
||||
template <typename T, typename U>
|
||||
concept CCommonWith =
|
||||
requires
|
||||
{
|
||||
typename TCommonType<T, U>::Type;
|
||||
typename TCommonType<U, T>::Type;
|
||||
requires CSameAs<typename TCommonType<T, U>::Type, typename TCommonType<U, T>::Type>;
|
||||
static_cast<TCommonType<T, U>::Type>(DeclVal<T>());
|
||||
static_cast<TCommonType<T, U>::Type>(DeclVal<U>());
|
||||
} &&
|
||||
CCommonReferenceWith<const T&, const U&> &&
|
||||
CCommonReferenceWith<typename TCommonType<T, U>::Type&, typename TCommonReference<const T&, const U&>::Type> &&
|
||||
CSameAs<typename TCommonReference<T, U>::Type, typename TCommonReference<U, T>::Type>;
|
||||
template <typename... Ts>
|
||||
concept CCommonType =
|
||||
requires { typename TCommonType<Ts...>::Type; }
|
||||
&& (true && ... && CConstructibleFrom<typename TCommonReference<Ts...>::Type, Ts&&>)
|
||||
&& CCommonReference<const Ts&...> && CCommonReference<typename TCommonType<Ts...>::Type&, typename TCommonReference<const Ts&...>::Type>;
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
|
@ -9,8 +9,8 @@ NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
template <typename T, typename U>
|
||||
concept CWeaklyEqualityComparableWith =
|
||||
template <typename T, typename U = T>
|
||||
concept CWeaklyEqualityComparable =
|
||||
requires(const typename TRemoveReference<T>::Type& A, const typename TRemoveReference<U>::Type& B)
|
||||
{
|
||||
{ A == B } -> CBooleanTestable;
|
||||
@ -19,19 +19,13 @@ concept CWeaklyEqualityComparableWith =
|
||||
{ B != A } -> CBooleanTestable;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept CEqualityComparable = CWeaklyEqualityComparableWith<T, T>;
|
||||
template <typename T, typename U = T>
|
||||
concept CEqualityComparable = CWeaklyEqualityComparable<T> && CWeaklyEqualityComparable<U> && CWeaklyEqualityComparable<T, U>
|
||||
&& CCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>
|
||||
&& CWeaklyEqualityComparable<typename TCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>::Type>;
|
||||
|
||||
template <typename T, typename U>
|
||||
concept CEqualityComparableWith =
|
||||
CEqualityComparable<T> &&
|
||||
CEqualityComparable<U> &&
|
||||
CWeaklyEqualityComparableWith<T, U> &&
|
||||
CCommonReferenceWith<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&> &&
|
||||
CEqualityComparable<typename TCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>::Type>;
|
||||
|
||||
template <typename T, typename U>
|
||||
concept CPartiallyOrderedWith =
|
||||
template <typename T, typename U = T>
|
||||
concept CPartiallyOrdered =
|
||||
requires(const typename TRemoveReference<T>::Type& A, const typename TRemoveReference<U>::Type& B)
|
||||
{
|
||||
{ A < B } -> CBooleanTestable;
|
||||
@ -44,15 +38,13 @@ concept CPartiallyOrderedWith =
|
||||
{ B >= A } -> CBooleanTestable;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept CTotallyOrdered = CEqualityComparable<T> && CPartiallyOrderedWith<T, T>;
|
||||
|
||||
template <typename T, typename U>
|
||||
concept CTotallyOrderedWith =
|
||||
CTotallyOrdered<T> && CTotallyOrdered<U> &&
|
||||
CPartiallyOrderedWith<T, U> &&
|
||||
CEqualityComparableWith<T, U> &&
|
||||
CTotallyOrdered<typename TCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>::Type>;
|
||||
template <typename T, typename U = T>
|
||||
concept CTotallyOrdered =
|
||||
CPartiallyOrdered<T> && CPartiallyOrdered<U>
|
||||
&& CEqualityComparable<T> && CEqualityComparable<U>
|
||||
&& CPartiallyOrdered<T, U> && CEqualityComparable<T, U>
|
||||
&& CPartiallyOrdered<typename TCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>::Type>
|
||||
&& CEqualityComparable<typename TCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>::Type>;
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
|
@ -11,16 +11,15 @@ NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
template <typename T>
|
||||
concept CMovable =
|
||||
CObject<T> &&
|
||||
CMoveConstructible<T> &&
|
||||
CMoveAssignable<T> &&
|
||||
CSwappable<T>;
|
||||
concept CMovable = CObject<T>
|
||||
&& CMoveConstructible<T>
|
||||
&& CMoveAssignable<T>
|
||||
&& CSwappable<T>;
|
||||
|
||||
template <typename T>
|
||||
concept CCopyable = CMovable<T> &&
|
||||
CCopyConstructible<T> &&
|
||||
CCopyAssignable<T>;
|
||||
concept CCopyable = CMovable<T>
|
||||
&& CCopyConstructible<T>
|
||||
&& CCopyAssignable<T>;
|
||||
|
||||
template <typename T>
|
||||
concept CSemiregular = CCopyable<T> && CDefaultConstructible<T>;
|
||||
|
@ -8,21 +8,17 @@ NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
template <typename T>
|
||||
concept CSwappable = requires(T& A, T& B) { Swap(A, B); };
|
||||
|
||||
template <typename T, typename U>
|
||||
concept CSwappableWith = CCommonReferenceWith<T, U> &&
|
||||
requires(T&& A, U&& B)
|
||||
template <typename T, typename U = T>
|
||||
concept CSwappable = CCommonReference<T, U> &&
|
||||
requires(T& A, U& B)
|
||||
{
|
||||
Swap(Forward<T>(A), Forward<T>(A));
|
||||
Swap(Forward<U>(B), Forward<U>(B));
|
||||
Swap(Forward<T>(A), Forward<U>(B));
|
||||
Swap(Forward<U>(B), Forward<T>(A));
|
||||
Swap(A, A);
|
||||
Swap(B, B);
|
||||
Swap(A, B);
|
||||
Swap(B, A);
|
||||
};
|
||||
|
||||
//template <typename T> concept CNothrowSwappable;
|
||||
//template <typename T, typename U> concept CNothrowSwappableWith;
|
||||
//template <typename T, typename U> concept CNothrowSwappable;
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "TypeTraits/Common.h"
|
||||
#include "TypeTraits/CopyQualifiers.h"
|
||||
#include "TypeTraits/InPlaceSpecialization.h"
|
||||
#include "TypeTraits/BitwiseOperations.h"
|
||||
#include "TypeTraits/BooleanTestable.h"
|
||||
#include "TypeTraits/Object.h"
|
||||
#include "TypeTraits/Comparable.h"
|
||||
|
Loading…
Reference in New Issue
Block a user