refactor(templates): refactor GetTypeHash and Swap to friend

This commit is contained in:
_Redstone_c_ 2022-12-19 18:00:52 +08:00
parent de059cb980
commit b75cb30f4f
8 changed files with 86 additions and 136 deletions

View File

@ -91,7 +91,7 @@ public:
EmplaceImpl<T>(Forward<Ts>(Args)...); EmplaceImpl<T>(Forward<Ts>(Args)...);
} }
template <typename T> requires (!CBaseOf<FAny, TDecay<T>> && !CTInPlaceType<TDecay<T>> template <typename T> requires (!CSameAs<FAny, TDecay<T>> && !CTInPlaceType<TDecay<T>>
&& NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, T&&>) && NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, T&&>)
FORCEINLINE FAny(T&& InValue) : FAny(InPlaceType<TDecay<T>>, Forward<T>(InValue)) FORCEINLINE FAny(T&& InValue) : FAny(InPlaceType<TDecay<T>>, Forward<T>(InValue))
{ } { }
@ -217,7 +217,7 @@ public:
return *this; return *this;
} }
template <typename T> requires (!CBaseOf<FAny, TDecay<T>> && !CTInPlaceType<TDecay<T>> template <typename T> requires (!CSameAs<FAny, TDecay<T>> && !CTInPlaceType<TDecay<T>>
&& NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, T&&>) && NAMESPACE_PRIVATE::CFAnyPlaceable<T> && CConstructibleFrom<TDecay<T>, T&&>)
FORCEINLINE FAny& operator=(T&& InValue) FORCEINLINE FAny& operator=(T&& InValue)
{ {
@ -236,13 +236,13 @@ public:
return *this; return *this;
} }
template <typename T> requires (!CBaseOf<FAny, TRemoveCVRef<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T>) template <typename T> requires (!CSameAs<FAny, TRemoveCVRef<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T>)
FORCEINLINE constexpr bool operator==(const T& InValue) const& FORCEINLINE constexpr bool operator==(const T& InValue) const&
{ {
return HoldsAlternative<T>() ? GetValue<T>() == InValue : false; return HoldsAlternative<T>() ? GetValue<T>() == InValue : false;
} }
template <typename T> requires (!CBaseOf<FAny, TRemoveCVRef<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T>) template <typename T> requires (!CSameAs<FAny, TRemoveCVRef<T>> && NAMESPACE_PRIVATE::CFAnyPlaceable<T>)
FORCEINLINE constexpr partial_ordering operator<=>(const T& InValue) const& FORCEINLINE constexpr partial_ordering operator<=>(const T& InValue) const&
{ {
return HoldsAlternative<T>() ? SynthThreeWayCompare(GetValue<T>(), InValue) : partial_ordering::unordered; return HoldsAlternative<T>() ? SynthThreeWayCompare(GetValue<T>(), InValue) : partial_ordering::unordered;
@ -289,51 +289,26 @@ public:
Invalidate(); Invalidate();
} }
void Swap(FAny& InValue) friend void Swap(FAny& A, FAny& B)
{ {
if (!IsValid() && !InValue.IsValid()) return; if (!A.IsValid() && !B.IsValid()) return;
if (IsValid() && !InValue.IsValid()) if (A.IsValid() && !B.IsValid())
{ {
InValue = MoveTemp(*this); B = MoveTemp(A);
Reset(); A.Reset();
return;
} }
else if (!A.IsValid() && B.IsValid())
if (InValue.IsValid() && !IsValid())
{ {
*this = MoveTemp(InValue); A = MoveTemp(B);
InValue.Reset(); B.Reset();
return;
} }
else
if (GetTypeInfo() == InValue.GetTypeInfo())
{ {
switch (GetRepresentation()) FAny Temp = MoveTemp(A);
{ A = MoveTemp(B);
case ERepresentation::Empty: B = MoveTemp(Temp);
break;
case ERepresentation::Trivial:
uint8 TempBuffer[sizeof(TrivialStorage.Internal)];
Memory::Memmove(TempBuffer, TrivialStorage.Internal);
Memory::Memmove(TrivialStorage.Internal, InValue.TrivialStorage.Internal);
Memory::Memmove(InValue.TrivialStorage.Internal, TempBuffer);
break;
case ERepresentation::Small:
SmallStorage.RTTI->SwapObject(&SmallStorage.Internal, &InValue.SmallStorage.Internal);
break;
case ERepresentation::Big:
NAMESPACE_REDCRAFT::Swap(BigStorage.External, InValue.BigStorage.External);
break;
default: check_no_entry();
} }
return;
}
FAny Temp = MoveTemp(*this);
*this = MoveTemp(InValue);
InValue = MoveTemp(Temp);
} }
private: private:
@ -411,7 +386,7 @@ private:
{ {
if constexpr (CSwappable<T>) if constexpr (CSwappable<T>)
{ {
NAMESPACE_REDCRAFT::Swap(*reinterpret_cast<T*>(A), *reinterpret_cast<T*>(B)); Swap(*reinterpret_cast<T*>(A), *reinterpret_cast<T*>(B));
} }
else else
{ {

View File

@ -81,12 +81,6 @@ public:
Callable = InCallable; Callable = InCallable;
} }
FORCEINLINE constexpr void Swap(TFunctionStorage& InValue)
{
NAMESPACE_REDCRAFT::Swap(ValuePtr, InValue.ValuePtr);
NAMESPACE_REDCRAFT::Swap(Callable, InValue.Callable);
}
private: private:
uintptr ValuePtr; uintptr ValuePtr;
@ -295,27 +289,27 @@ public:
} }
void Swap(TFunctionStorage& InValue) friend void Swap(TFunctionStorage& A, TFunctionStorage& B)
{ {
if (!IsValid() && !InValue.IsValid()) return; if (!A.IsValid() && !B.IsValid()) return;
if (IsValid() && !InValue.IsValid()) if (A.IsValid() && !B.IsValid())
{ {
InValue = MoveTemp(*this); B = MoveTemp(A);
Destroy(); A.Destroy();
Invalidate(); A.Invalidate();
} }
else if (InValue.IsValid() && !IsValid()) else if (!A.IsValid() && B.IsValid())
{ {
*this = MoveTemp(InValue); A = MoveTemp(B);
InValue.Destroy(); B.Destroy();
InValue.Invalidate(); B.Invalidate();
} }
else else
{ {
TFunctionStorage Temp = MoveTemp(*this); TFunctionStorage Temp = MoveTemp(A);
*this = MoveTemp(InValue); A = MoveTemp(B);
InValue = MoveTemp(Temp); B = MoveTemp(Temp);
} }
} }
@ -487,8 +481,6 @@ public:
FORCEINLINE constexpr bool IsValid() const { return Storage.IsValid(); } FORCEINLINE constexpr bool IsValid() const { return Storage.IsValid(); }
FORCEINLINE constexpr explicit operator bool() const { return Storage.IsValid(); } FORCEINLINE constexpr explicit operator bool() const { return Storage.IsValid(); }
FORCEINLINE constexpr void Swap(TFunctionImpl& InValue) { Storage.Swap(InValue.Storage); }
private: private:
using CallableType = ResultType(*)(uintptr, Ts&&...); using CallableType = ResultType(*)(uintptr, Ts&&...);
@ -536,6 +528,8 @@ protected: // These functions should not be used by user-defined class
return *reinterpret_cast<DecayedType*>(Storage.GetValuePtr()); return *reinterpret_cast<DecayedType*>(Storage.GetValuePtr());
} }
friend FORCEINLINE constexpr void Swap(TFunctionImpl& A, TFunctionImpl& B) requires (!bIsRef) { Swap(A.Storage, B.Storage); }
}; };
NAMESPACE_PRIVATE_END NAMESPACE_PRIVATE_END
@ -647,6 +641,8 @@ public:
FORCEINLINE constexpr void Reset() { Impl::Destroy(); Impl::Invalidate(); } FORCEINLINE constexpr void Reset() { Impl::Destroy(); Impl::Invalidate(); }
friend FORCEINLINE constexpr void Swap(TFunction& A, TFunction& B) { Swap(static_cast<Impl&>(A), static_cast<Impl&>(B)); }
}; };
template <CFunction F> template <CFunction F>
@ -735,6 +731,8 @@ public:
FORCEINLINE constexpr void Reset() { Impl::Destroy(); Impl::Invalidate(); } FORCEINLINE constexpr void Reset() { Impl::Destroy(); Impl::Invalidate(); }
friend FORCEINLINE constexpr void Swap(TUniqueFunction& A, TUniqueFunction& B) { Swap(static_cast<Impl&>(A), static_cast<Impl&>(B)); }
}; };
static_assert(sizeof(TFunction<void()>) == 64, "The byte size of TFunction is unexpected"); static_assert(sizeof(TFunction<void()>) == 64, "The byte size of TFunction is unexpected");

View File

@ -57,7 +57,7 @@ public:
} }
template <typename T = OptionalType> requires (CConstructibleFrom<OptionalType, T&&>) template <typename T = OptionalType> requires (CConstructibleFrom<OptionalType, T&&>)
&& (!CSameAs<TRemoveCVRef<T>, FInPlace>) && (!CBaseOf<TOptional, TRemoveCVRef<T>>) && (!CSameAs<TRemoveCVRef<T>, FInPlace>) && (!CSameAs<TOptional, TRemoveCVRef<T>>)
FORCEINLINE constexpr explicit (!CConvertibleTo<T&&, OptionalType>) TOptional(T&& InValue) FORCEINLINE constexpr explicit (!CConvertibleTo<T&&, OptionalType>) TOptional(T&& InValue)
: TOptional(InPlace, Forward<T>(InValue)) : TOptional(InPlace, Forward<T>(InValue))
{ } { }
@ -269,32 +269,31 @@ public:
} }
} }
FORCEINLINE constexpr size_t GetTypeHash() const requires (CHashable<OptionalType>) friend FORCEINLINE constexpr size_t GetTypeHash(const TOptional& A) requires (CHashable<OptionalType>)
{ {
if (!IsValid()) return 2824517378; if (!A.IsValid()) return 2824517378;
return NAMESPACE_REDCRAFT::GetTypeHash(GetValue()); return GetTypeHash(A.GetValue());
} }
template <typename T> requires (CMoveConstructible<OptionalType> && CSwappable<OptionalType>) template <typename T> requires (CMoveConstructible<OptionalType> && CSwappable<OptionalType>)
constexpr void Swap(TOptional& InValue) friend constexpr void Swap(TOptional& A, TOptional& B)
{ {
if (!IsValid() && !InValue.IsValid()) return; if (!A.IsValid() && !B.IsValid()) return;
if (IsValid() && !InValue.IsValid()) if (A.IsValid() && !B.IsValid())
{ {
InValue = MoveTemp(*this); B = MoveTemp(A);
Reset(); A.Reset();
return;
} }
else if (!A.IsValid() && B.IsValid())
if (InValue.IsValid() && !IsValid())
{ {
*this = MoveTemp(InValue); A = MoveTemp(B);
InValue.Reset(); B.Reset();
return; }
else
{
Swap(A.GetValue(), B.GetValue());
} }
NAMESPACE_REDCRAFT::Swap(GetValue(), InValue.GetValue());
} }
private: private:

View File

@ -47,9 +47,9 @@ public:
return Invoke(Get(), Forward<Ts>(Args)...); return Invoke(Get(), Forward<Ts>(Args)...);
} }
FORCEINLINE constexpr size_t GetTypeHash() const requires (CHashable<ReferencedType>) friend FORCEINLINE constexpr size_t GetTypeHash(TReferenceWrapper A) requires (CHashable<ReferencedType>)
{ {
return NAMESPACE_REDCRAFT::GetTypeHash(Get()); return GetTypeHash(A.Get());
} }
private: private:

View File

@ -409,20 +409,20 @@ public:
template <typename T> requires (CConstructibleFrom<T, Ts...>) FORCEINLINE constexpr T Construct() volatile&& { return Helper::template Construct<T>(static_cast< volatile TTuple&&>(*this)); } template <typename T> requires (CConstructibleFrom<T, Ts...>) FORCEINLINE constexpr T Construct() volatile&& { return Helper::template Construct<T>(static_cast< volatile TTuple&&>(*this)); }
template <typename T> requires (CConstructibleFrom<T, Ts...>) FORCEINLINE constexpr T Construct() const volatile&& { return Helper::template Construct<T>(static_cast<const volatile TTuple&&>(*this)); } template <typename T> requires (CConstructibleFrom<T, Ts...>) FORCEINLINE constexpr T Construct() const volatile&& { return Helper::template Construct<T>(static_cast<const volatile TTuple&&>(*this)); }
FORCEINLINE constexpr size_t GetTypeHash() const requires (true && ... && CHashable<Ts>) friend FORCEINLINE constexpr size_t GetTypeHash(const TTuple& A) requires (true && ... && CHashable<Ts>)
{ {
return [this]<size_t... Indices>(TIndexSequence<Indices...>) -> size_t return [&A]<size_t... Indices>(TIndexSequence<Indices...>) -> size_t
{ {
return HashCombine(NAMESPACE_REDCRAFT::GetTypeHash(GetValue<Indices>())...); return HashCombine(GetTypeHash(A.template GetValue<Indices>())...);
} }
(TMakeIndexSequence<sizeof...(Ts)>()); (TMakeIndexSequence<sizeof...(Ts)>());
} }
FORCEINLINE constexpr void Swap(TTuple& InValue) requires (true && ... && (CMoveConstructible<Ts> && CSwappable<Ts>)) friend FORCEINLINE constexpr void Swap(TTuple& A, TTuple& B) requires (true && ... && (CMoveConstructible<Ts> && CSwappable<Ts>))
{ {
[&A = *this, &B = InValue]<size_t... Indices>(TIndexSequence<Indices...>) [&A, &B]<size_t... Indices>(TIndexSequence<Indices...>)
{ {
((NAMESPACE_REDCRAFT::Swap(A.template GetValue<Indices>(), B.template GetValue<Indices>())), ...); ((Swap(A.template GetValue<Indices>(), B.template GetValue<Indices>())), ...);
} }
(TMakeIndexSequence<sizeof...(Ts)>()); (TMakeIndexSequence<sizeof...(Ts)>());
} }

View File

@ -86,12 +86,6 @@ FORCEINLINE constexpr size_t GetTypeHash(T A)
return GetTypeHash(reinterpret_cast<intptr>(A)); return GetTypeHash(reinterpret_cast<intptr>(A));
} }
template <typename T> requires (requires(const T& A) { { GetTypeHash(A.GetTypeHash()) } -> CSameAs<size_t>; })
FORCEINLINE constexpr size_t GetTypeHash(const T& A)
{
return GetTypeHash(A.GetTypeHash());
}
template <typename T> requires (requires(const T& A) { { GetTypeHash(A.hash_code()) } -> CSameAs<size_t>; }) template <typename T> requires (requires(const T& A) { { GetTypeHash(A.hash_code()) } -> CSameAs<size_t>; })
FORCEINLINE constexpr size_t GetTypeHash(const T& A) FORCEINLINE constexpr size_t GetTypeHash(const T& A)
{ {

View File

@ -55,20 +55,12 @@ FORCEINLINE constexpr T&& Forward(TRemoveReference<T>&& Obj)
return static_cast<T&&>(Obj); return static_cast<T&&>(Obj);
} }
template <typename T> requires (requires(T& A, T& B) { A.Swap(B); } template <typename T> requires (CMoveConstructible<T> && CMoveAssignable<T>)
|| (CMoveConstructible<T> && CMoveAssignable<T>))
FORCEINLINE constexpr void Swap(T& A, T& B) FORCEINLINE constexpr void Swap(T& A, T& B)
{ {
if constexpr (requires(T& A, T& B) { A.Swap(B); })
{
A.Swap(B);
}
else
{
T Temp = MoveTemp(A); T Temp = MoveTemp(A);
A = MoveTemp(B); A = MoveTemp(B);
B = MoveTemp(Temp); B = MoveTemp(Temp);
}
} }
template <typename T, typename U = T> requires (CMoveConstructible<T> && CAssignableFrom<T&, U>) template <typename T, typename U = T> requires (CMoveConstructible<T> && CAssignableFrom<T&, U>)

View File

@ -120,7 +120,7 @@ public:
template <typename T> requires (requires { typename NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>; } template <typename T> requires (requires { typename NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>; }
&& !CTInPlaceType<TRemoveCVRef<T>> && !CTInPlaceIndex<TRemoveCVRef<T>> && !CTInPlaceType<TRemoveCVRef<T>> && !CTInPlaceIndex<TRemoveCVRef<T>>
&& !CBaseOf<TVariant, TRemoveCVRef<T>>) && !CSameAs<TVariant, TRemoveCVRef<T>>)
FORCEINLINE constexpr TVariant(T&& InValue) : TVariant(InPlaceType<NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>>, Forward<T>(InValue)) FORCEINLINE constexpr TVariant(T&& InValue) : TVariant(InPlaceType<NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>>, Forward<T>(InValue))
{ } { }
@ -217,13 +217,13 @@ public:
return CompareImpl[LHS.GetIndex()](&LHS.Value, &RHS.Value); return CompareImpl[LHS.GetIndex()](&LHS.Value, &RHS.Value);
} }
template <typename T> requires (!CBaseOf<TVariant, T> && CEqualityComparable<T>) template <typename T> requires (!CSameAs<TVariant, T> && CEqualityComparable<T>)
FORCEINLINE constexpr bool operator==(const T& InValue) const& FORCEINLINE constexpr bool operator==(const T& InValue) const&
{ {
return HoldsAlternative<T>() ? GetValue<T>() == InValue : false; return HoldsAlternative<T>() ? GetValue<T>() == InValue : false;
} }
template <typename T> requires (!CBaseOf<TVariant, T> && CEqualityComparable<T>) template <typename T> requires (!CSameAs<TVariant, T> && CEqualityComparable<T>)
FORCEINLINE constexpr partial_ordering operator<=>(const T& InValue) const& FORCEINLINE constexpr partial_ordering operator<=>(const T& InValue) const&
{ {
return HoldsAlternative<T>() ? SynthThreeWayCompare(GetValue<T>(), InValue) : partial_ordering::unordered; return HoldsAlternative<T>() ? SynthThreeWayCompare(GetValue<T>(), InValue) : partial_ordering::unordered;
@ -287,51 +287,43 @@ public:
TypeIndex = static_cast<uint8>(INDEX_NONE); TypeIndex = static_cast<uint8>(INDEX_NONE);
} }
FORCEINLINE constexpr size_t GetTypeHash() const requires (true && ... && CHashable<Ts>) friend FORCEINLINE constexpr size_t GetTypeHash(const TVariant& A) requires (true && ... && CHashable<Ts>)
{ {
if (!IsValid()) return 114514; if (!A.IsValid()) return 114514;
using NAMESPACE_REDCRAFT::GetTypeHash;
using FHashImpl = size_t(*)(const void*); using FHashImpl = size_t(*)(const void*);
constexpr FHashImpl HashImpl[] = { [](const void* This) -> size_t { return GetTypeHash(*reinterpret_cast<const Ts*>(This)); }... }; constexpr FHashImpl HashImpl[] = { [](const void* This) -> size_t { return GetTypeHash(*reinterpret_cast<const Ts*>(This)); }... };
return HashCombine(GetTypeHash(GetIndex()), HashImpl[GetIndex()](&Value)); return HashCombine(GetTypeHash(A.GetIndex()), HashImpl[A.GetIndex()](&A.Value));
} }
constexpr void Swap(TVariant& InValue) requires (true && ... && (CMoveConstructible<Ts> && CSwappable<Ts>)) friend constexpr void Swap(TVariant& A, TVariant& B) requires (true && ... && (CMoveConstructible<Ts> && CSwappable<Ts>))
{ {
if (!IsValid() && !InValue.IsValid()) return; if (!A.IsValid() && !B.IsValid()) return;
if (IsValid() && !InValue.IsValid()) if (A.IsValid() && !B.IsValid())
{ {
InValue = MoveTemp(*this); B = MoveTemp(A);
Reset(); A.Reset();
return;
} }
else if (!A.IsValid() && B.IsValid())
if (InValue.IsValid() && !IsValid())
{ {
*this = MoveTemp(InValue); A = MoveTemp(B);
InValue.Reset(); B.Reset();
return;
} }
else if (A.GetIndex() == B.GetIndex())
if (GetIndex() == InValue.GetIndex())
{ {
using NAMESPACE_REDCRAFT::Swap;
using FSwapImpl = void(*)(void*, void*); using FSwapImpl = void(*)(void*, void*);
constexpr FSwapImpl SwapImpl[] = { [](void* A, void* B) { Swap(*reinterpret_cast<Ts*>(A), *reinterpret_cast<Ts*>(B)); }... }; constexpr FSwapImpl SwapImpl[] = { [](void* A, void* B) { Swap(*reinterpret_cast<Ts*>(A), *reinterpret_cast<Ts*>(B)); }... };
SwapImpl[GetIndex()](&Value, &InValue.Value); SwapImpl[A.GetIndex()](&A.Value, &B.Value);
}
return; else
{
TVariant Temp = MoveTemp(A);
A = MoveTemp(B);
B = MoveTemp(Temp);
} }
TVariant Temp = MoveTemp(*this);
*this = MoveTemp(InValue);
InValue = MoveTemp(Temp);
} }
private: private: