refactor(typetraits): simplifies concept selection and removes the concept of bitwise operations

This commit is contained in:
_Redstone_c_ 2022-05-21 22:39:22 +08:00
parent ee46d84897
commit 97910be70c
14 changed files with 93 additions and 263 deletions

View File

@ -152,7 +152,6 @@ struct FTracker
~FTracker() { always_check(Status == 3); Status = -1; } ~FTracker() { always_check(Status == 3); Status = -1; }
FTracker& operator=(const FTracker&) { always_check(Status == 4); Status = -1; return *this; } FTracker& operator=(const FTracker&) { always_check(Status == 4); Status = -1; return *this; }
FTracker& operator=(FTracker&&) { always_check(Status == 5); 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; int32 FTracker::Status = -1;
@ -181,10 +180,6 @@ void TestMemoryOperator()
Memory::MoveConstruct(PtrA, PtrB); Memory::MoveConstruct(PtrA, PtrB);
always_check(FTracker::Status == -1); always_check(FTracker::Status == -1);
FTracker::Status = -1;
Memory::RelocateConstruct(PtrA, PtrB);
always_check(FTracker::Status == -1);
FTracker::Status = 3; FTracker::Status = 3;
Memory::Destruct(PtrA); Memory::Destruct(PtrA);
always_check(FTracker::Status == -1); always_check(FTracker::Status == -1);
@ -197,11 +192,6 @@ void TestMemoryOperator()
Memory::MoveAssign(PtrA, PtrB); Memory::MoveAssign(PtrA, PtrB);
always_check(FTracker::Status == -1); 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(PtrA);
Memory::Free(PtrB); Memory::Free(PtrB);
} }

View File

@ -110,8 +110,11 @@ struct FTestSynth
{ {
int32 A; int32 A;
FTestSynth(int32 InA) : A(InA) { } 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; }
friend bool operator> (FTestSynth LHS, FTestSynth RHS) { return LHS.A > RHS.A; }
}; };
NAMESPACE_UNNAMED_END NAMESPACE_UNNAMED_END
@ -194,8 +197,8 @@ void TestCompare()
always_check(CThreeWayComparable<FTestWeakOrdering>); always_check(CThreeWayComparable<FTestWeakOrdering>);
always_check(CThreeWayComparable<FTestStrongOrdering>); always_check(CThreeWayComparable<FTestStrongOrdering>);
always_check((CThreeWayComparableWith<bool, bool>)); always_check((CThreeWayComparable<bool, bool>));
always_check((CThreeWayComparableWith<int16, int32>)); always_check((CThreeWayComparable<int16, int32>));
always_check((CSameAs<TCompareThreeWayResult<int32 >::Type, strong_ordering >)); always_check((CSameAs<TCompareThreeWayResult<int32 >::Type, strong_ordering >));
always_check((CSameAs<TCompareThreeWayResult<float >::Type, partial_ordering>)); always_check((CSameAs<TCompareThreeWayResult<float >::Type, partial_ordering>));

View File

@ -459,15 +459,15 @@ void TestTypeTraits()
always_check((CSameAs<int64, TCommonReference<int8, int32, int64>::Type>)); always_check((CSameAs<int64, TCommonReference<int8, int32, int64>::Type>));
always_check((CSameAs<double, TCommonReference<float, double>::Type>)); always_check((CSameAs<double, TCommonReference<float, double>::Type>));
always_check((CCommonWith<int32, int32>)); always_check((CCommonType<int32, int32>));
always_check((CCommonWith<int8, int32>)); always_check((CCommonType<int8, int32>));
always_check((CCommonWith<float, double>)); always_check((CCommonType<float, double>));
always_check(!(CCommonWith<FTestStructA, int32>)); always_check(!(CCommonType<FTestStructA, int32>));
always_check((CCommonReferenceWith<int8, int32>)); always_check((CCommonReference<int8, int32>));
always_check((CCommonReferenceWith<float, int32>)); always_check((CCommonReference<float, int32>));
always_check((CCommonReferenceWith<float, double>)); always_check((CCommonReference<float, double>));
always_check(!(CCommonReferenceWith<FTestStructA, double>)); always_check(!(CCommonReference<FTestStructA, double>));
// Swappable.h // Swappable.h
@ -476,7 +476,7 @@ void TestTypeTraits()
always_check(CSwappable<FTestStructN>); always_check(CSwappable<FTestStructN>);
always_check(!CSwappable<FSingleton>); always_check(!CSwappable<FSingleton>);
always_check((CSwappableWith<int32&, int32&>)); always_check((CSwappable<int32&, int32&>));
// CopyQualifiers.h // CopyQualifiers.h
@ -585,16 +585,16 @@ void TestTypeTraits()
always_check((CEqualityComparable<int32>)); always_check((CEqualityComparable<int32>));
always_check(!(CEqualityComparable<FTestStructA>)); always_check(!(CEqualityComparable<FTestStructA>));
always_check((CEqualityComparableWith<int32, int32>)); always_check((CEqualityComparable<int32, int32>));
always_check((CEqualityComparableWith<int32, int64>)); always_check((CEqualityComparable<int32, int64>));
always_check(!(CEqualityComparableWith<FTestStructA, FTestStructA>)); always_check(!(CEqualityComparable<FTestStructA, FTestStructA>));
always_check((CTotallyOrdered<int32>)); always_check((CTotallyOrdered<int32>));
always_check(!(CTotallyOrdered<FTestStructA>)); always_check(!(CTotallyOrdered<FTestStructA>));
always_check((CTotallyOrderedWith<int32, int32>)); always_check((CTotallyOrdered<int32, int32>));
always_check((CTotallyOrderedWith<int32, int64>)); always_check((CTotallyOrdered<int32, int64>));
always_check(!(CTotallyOrderedWith<FTestStructA, FTestStructA>)); always_check(!(CTotallyOrdered<FTestStructA, FTestStructA>));
} }

View File

@ -15,13 +15,9 @@ template <typename ElementType>
requires CDefaultConstructible<ElementType> requires CDefaultConstructible<ElementType>
FORCEINLINE void DefaultConstruct(ElementType* Address, size_t Count = 1) FORCEINLINE void DefaultConstruct(ElementType* Address, size_t Count = 1)
{ {
if constexpr (CZeroConstructible<ElementType>) if constexpr (!CTriviallyDefaultConstructible<ElementType>)
{ {
Memory::Memset(Address, 0, sizeof(ElementType) * Count); ElementType* Element = Address;
}
else
{
ElementType* Element = (ElementType*)Address;
while (Count) while (Count)
{ {
new (Element) ElementType; new (Element) ElementType;
@ -35,7 +31,7 @@ template <typename DestinationElementType, typename SourceElementType = Destinat
requires CConstructibleFrom<DestinationElementType, const SourceElementType&> requires CConstructibleFrom<DestinationElementType, const SourceElementType&>
FORCEINLINE void Construct(DestinationElementType* Destination, const SourceElementType* Source, size_t Count = 1) 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); 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> template <typename ElementType>
requires CCopyAssignable<ElementType> requires CCopyAssignable<ElementType>
FORCEINLINE void CopyAssign(ElementType* Destination, const ElementType* Source, size_t Count = 1) FORCEINLINE void CopyAssign(ElementType* Destination, const ElementType* Source, size_t Count = 1)
@ -152,7 +111,7 @@ template <typename ElementType>
requires CMoveAssignable<ElementType> requires CMoveAssignable<ElementType>
FORCEINLINE void MoveAssign(ElementType* Destination, ElementType* Source, size_t Count = 1) 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); Memory::Memmove(Destination, Source, sizeof(ElementType) * Count);
} }
@ -169,25 +128,17 @@ FORCEINLINE void MoveAssign(ElementType* Destination, ElementType* Source, size_
} }
template <typename ElementType> template <typename ElementType>
requires CEqualityComparable<ElementType> requires CDestructible<ElementType>
FORCEINLINE bool Compare(const ElementType* LHS, const ElementType* RHS, size_t Count = 1) FORCEINLINE void Destruct(ElementType* Element, size_t Count = 1)
{ {
if constexpr (CBitwiseComparable<ElementType>) if constexpr (!CTriviallyDestructible<ElementType>)
{
return !Memory::Memcmp(LHS, RHS, sizeof(ElementType) * Count);
}
else
{ {
while (Count) while (Count)
{ {
if (!(*LHS == *RHS)) return false; Element->~ElementType();
++Element;
++LHS;
++RHS;
--Count; --Count;
} }
return true;
} }
} }

View File

@ -40,53 +40,35 @@ struct TCommonComparisonCategory
template <typename T, typename OrderingType> template <typename T, typename OrderingType>
concept CThreeWayComparesAs = CSameAs<typename TCommonComparisonCategory<T, OrderingType>::Type, OrderingType>; concept CThreeWayComparesAs = CSameAs<typename TCommonComparisonCategory<T, OrderingType>::Type, OrderingType>;
template <typename T, typename OrderingType = partial_ordering> template <typename T, typename U = T, typename OrderingType = partial_ordering>
concept CThreeWayComparable = CWeaklyEqualityComparableWith<T, T> && CPartiallyOrderedWith<T, T> && concept CThreeWayComparable = CWeaklyEqualityComparable<T, U> && CPartiallyOrdered<T, U>
requires(const TRemoveReference<T>::Type& A, const TRemoveReference<T>::Type& B) && CCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>
{ && requires(const typename TRemoveReference<T>::Type& A, const typename TRemoveReference<U>::Type& B,
{ A <=> B } -> CThreeWayComparesAs<OrderingType>; const typename TRemoveReference<typename TCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>::Type>::Type& C)
};
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)
{ {
{ A <=> A } -> CThreeWayComparesAs<OrderingType>;
{ B <=> B } -> CThreeWayComparesAs<OrderingType>;
{ A <=> B } -> CThreeWayComparesAs<OrderingType>; { A <=> B } -> CThreeWayComparesAs<OrderingType>;
{ B <=> A } -> CThreeWayComparesAs<OrderingType>; { B <=> A } -> CThreeWayComparesAs<OrderingType>;
{ C <=> C } -> CThreeWayComparesAs<OrderingType>;
}; };
template <typename T, typename U = T> template <typename T, typename U = T>
struct TCompareThreeWayResult { }; struct TCompareThreeWayResult { };
template <typename T, typename U> requires CThreeWayComparableWith<T, U> template <typename T, typename U> requires CThreeWayComparable<T, U>
struct TCompareThreeWayResult<T, U> 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, typename OrderingType = partial_ordering> template <typename T, typename U = T, typename OrderingType = partial_ordering>
concept CSynthThreeWayComparable = CThreeWayComparable<T> || concept CSynthThreeWayComparable = CThreeWayComparable<T, U> || CTotallyOrdered<T, U>;
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> template <typename T, typename U = T> requires CSynthThreeWayComparable<T, U>
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>
constexpr decltype(auto) SynthThreeWayCompare(T&& LHS, U&& RHS) 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); return Forward<T>(LHS) <=> Forward<U>(RHS);
} }

View File

@ -254,7 +254,7 @@ private:
template <typename T> template <typename T>
TOptional(T) -> TOptional<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) constexpr bool operator==(const TOptional<T>& LHS, const TOptional<U>& RHS)
{ {
if (LHS.IsValid() != RHS.IsValid()) return false; 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; 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) constexpr partial_ordering operator<=>(const TOptional<T>& LHS, const TOptional<U>& RHS)
{ {
if (LHS.IsValid() != RHS.IsValid()) return partial_ordering::unordered; 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); 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) constexpr bool operator==(const TOptional<T>& LHS, const U& RHS)
{ {
return LHS.IsValid() ? *LHS == RHS : false; return LHS.IsValid() ? *LHS == RHS : false;

View File

@ -557,14 +557,14 @@ constexpr auto TupleCat(TTupleTypes&&... Args)
else return NAMESPACE_PRIVATE::TTupleCatImpl<R>::F(Forward<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) constexpr bool operator==(const TTuple<LHSTypes...>& LHS, const TTuple<RHSTypes...>& RHS)
{ {
if constexpr (sizeof...(LHSTypes) != sizeof...(RHSTypes)) return false; 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)>()); 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) 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; using R = typename TCommonComparisonCategory<typename TSynthThreeWayResult<LHSTypes, RHSTypes>::Type...>::Type;

View File

@ -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

View File

@ -9,8 +9,8 @@ NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_MODULE_BEGIN(Utility)
template <typename T> template <typename T>
concept CBooleanTestable = CConvertibleTo<T, bool> && concept CBooleanTestable = CConvertibleTo<T, bool>
requires(T && B) { { !Forward<T>(B) } -> CConvertibleTo<bool>; }; && requires(T && B) { { !Forward<T>(B) } -> CConvertibleTo<bool>; };
NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft) NAMESPACE_MODULE_END(Redcraft)

View File

@ -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 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... Types> struct TCommonReference : TConditional<NAMESPACE_PRIVATE::CCommonReference<Types...>, NAMESPACE_PRIVATE::TCommonReference<Types...>, NAMESPACE_PRIVATE::FNoopStruct>::Type { };
template <typename T, typename U> template <typename... Ts>
concept CCommonReferenceWith = concept CCommonReference =
requires requires { typename TCommonReference<Ts...>::Type; }
{ && (true && ... && CConvertibleTo<Ts, typename TCommonReference<Ts...>::Type>);
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 T, typename U> template <typename... Ts>
concept CCommonWith = concept CCommonType =
requires requires { typename TCommonType<Ts...>::Type; }
{ && (true && ... && CConstructibleFrom<typename TCommonReference<Ts...>::Type, Ts&&>)
typename TCommonType<T, U>::Type; && CCommonReference<const Ts&...> && CCommonReference<typename TCommonType<Ts...>::Type&, typename TCommonReference<const Ts&...>::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>;
NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft) NAMESPACE_MODULE_END(Redcraft)

View File

@ -9,8 +9,8 @@ NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_MODULE_BEGIN(Utility)
template <typename T, typename U> template <typename T, typename U = T>
concept CWeaklyEqualityComparableWith = concept CWeaklyEqualityComparable =
requires(const typename TRemoveReference<T>::Type& A, const typename TRemoveReference<U>::Type& B) requires(const typename TRemoveReference<T>::Type& A, const typename TRemoveReference<U>::Type& B)
{ {
{ A == B } -> CBooleanTestable; { A == B } -> CBooleanTestable;
@ -19,19 +19,13 @@ concept CWeaklyEqualityComparableWith =
{ B != A } -> CBooleanTestable; { B != A } -> CBooleanTestable;
}; };
template <typename T> template <typename T, typename U = T>
concept CEqualityComparable = CWeaklyEqualityComparableWith<T, 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> template <typename T, typename U = T>
concept CEqualityComparableWith = concept CPartiallyOrdered =
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 =
requires(const typename TRemoveReference<T>::Type& A, const typename TRemoveReference<U>::Type& B) requires(const typename TRemoveReference<T>::Type& A, const typename TRemoveReference<U>::Type& B)
{ {
{ A < B } -> CBooleanTestable; { A < B } -> CBooleanTestable;
@ -44,15 +38,13 @@ concept CPartiallyOrderedWith =
{ B >= A } -> CBooleanTestable; { B >= A } -> CBooleanTestable;
}; };
template <typename T> template <typename T, typename U = T>
concept CTotallyOrdered = CEqualityComparable<T> && CPartiallyOrderedWith<T, T>; concept CTotallyOrdered =
CPartiallyOrdered<T> && CPartiallyOrdered<U>
template <typename T, typename U> && CEqualityComparable<T> && CEqualityComparable<U>
concept CTotallyOrderedWith = && CPartiallyOrdered<T, U> && CEqualityComparable<T, U>
CTotallyOrdered<T> && CTotallyOrdered<U> && && CPartiallyOrdered<typename TCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>::Type>
CPartiallyOrderedWith<T, U> && && CEqualityComparable<typename TCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>::Type>;
CEqualityComparableWith<T, U> &&
CTotallyOrdered<typename TCommonReference<const typename TRemoveReference<T>::Type&, const typename TRemoveReference<U>::Type&>::Type>;
NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft) NAMESPACE_MODULE_END(Redcraft)

View File

@ -11,16 +11,15 @@ NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_MODULE_BEGIN(Utility)
template <typename T> template <typename T>
concept CMovable = concept CMovable = CObject<T>
CObject<T> && && CMoveConstructible<T>
CMoveConstructible<T> && && CMoveAssignable<T>
CMoveAssignable<T> && && CSwappable<T>;
CSwappable<T>;
template <typename T> template <typename T>
concept CCopyable = CMovable<T> && concept CCopyable = CMovable<T>
CCopyConstructible<T> && && CCopyConstructible<T>
CCopyAssignable<T>; && CCopyAssignable<T>;
template <typename T> template <typename T>
concept CSemiregular = CCopyable<T> && CDefaultConstructible<T>; concept CSemiregular = CCopyable<T> && CDefaultConstructible<T>;

View File

@ -8,21 +8,17 @@ NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_MODULE_BEGIN(Utility)
template <typename T> template <typename T, typename U = T>
concept CSwappable = requires(T& A, T& B) { Swap(A, B); }; concept CSwappable = CCommonReference<T, U> &&
requires(T& A, U& B)
template <typename T, typename U>
concept CSwappableWith = CCommonReferenceWith<T, U> &&
requires(T&& A, U&& B)
{ {
Swap(Forward<T>(A), Forward<T>(A)); Swap(A, A);
Swap(Forward<U>(B), Forward<U>(B)); Swap(B, B);
Swap(Forward<T>(A), Forward<U>(B)); Swap(A, B);
Swap(Forward<U>(B), Forward<T>(A)); Swap(B, A);
}; };
//template <typename T> concept CNothrowSwappable; //template <typename T, typename U> concept CNothrowSwappable;
//template <typename T, typename U> concept CNothrowSwappableWith;
NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft) NAMESPACE_MODULE_END(Redcraft)

View File

@ -12,7 +12,6 @@
#include "TypeTraits/Common.h" #include "TypeTraits/Common.h"
#include "TypeTraits/CopyQualifiers.h" #include "TypeTraits/CopyQualifiers.h"
#include "TypeTraits/InPlaceSpecialization.h" #include "TypeTraits/InPlaceSpecialization.h"
#include "TypeTraits/BitwiseOperations.h"
#include "TypeTraits/BooleanTestable.h" #include "TypeTraits/BooleanTestable.h"
#include "TypeTraits/Object.h" #include "TypeTraits/Object.h"
#include "TypeTraits/Comparable.h" #include "TypeTraits/Comparable.h"