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)...);
}
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&&>)
FORCEINLINE FAny(T&& InValue) : FAny(InPlaceType<TDecay<T>>, Forward<T>(InValue))
{ }
@ -217,7 +217,7 @@ public:
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&&>)
FORCEINLINE FAny& operator=(T&& InValue)
{
@ -236,13 +236,13 @@ public:
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&
{
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&
{
return HoldsAlternative<T>() ? SynthThreeWayCompare(GetValue<T>(), InValue) : partial_ordering::unordered;
@ -289,51 +289,26 @@ public:
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);
Reset();
return;
B = MoveTemp(A);
A.Reset();
}
if (InValue.IsValid() && !IsValid())
else if (!A.IsValid() && B.IsValid())
{
*this = MoveTemp(InValue);
InValue.Reset();
return;
A = MoveTemp(B);
B.Reset();
}
if (GetTypeInfo() == InValue.GetTypeInfo())
else
{
switch (GetRepresentation())
{
case ERepresentation::Empty:
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();
FAny Temp = MoveTemp(A);
A = MoveTemp(B);
B = MoveTemp(Temp);
}
return;
}
FAny Temp = MoveTemp(*this);
*this = MoveTemp(InValue);
InValue = MoveTemp(Temp);
}
private:
@ -411,7 +386,7 @@ private:
{
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
{

View File

@ -81,12 +81,6 @@ public:
Callable = InCallable;
}
FORCEINLINE constexpr void Swap(TFunctionStorage& InValue)
{
NAMESPACE_REDCRAFT::Swap(ValuePtr, InValue.ValuePtr);
NAMESPACE_REDCRAFT::Swap(Callable, InValue.Callable);
}
private:
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);
Destroy();
Invalidate();
B = MoveTemp(A);
A.Destroy();
A.Invalidate();
}
else if (InValue.IsValid() && !IsValid())
else if (!A.IsValid() && B.IsValid())
{
*this = MoveTemp(InValue);
InValue.Destroy();
InValue.Invalidate();
A = MoveTemp(B);
B.Destroy();
B.Invalidate();
}
else
{
TFunctionStorage Temp = MoveTemp(*this);
*this = MoveTemp(InValue);
InValue = MoveTemp(Temp);
TFunctionStorage Temp = MoveTemp(A);
A = MoveTemp(B);
B = MoveTemp(Temp);
}
}
@ -487,8 +481,6 @@ public:
FORCEINLINE constexpr bool IsValid() const { return Storage.IsValid(); }
FORCEINLINE constexpr explicit operator bool() const { return Storage.IsValid(); }
FORCEINLINE constexpr void Swap(TFunctionImpl& InValue) { Storage.Swap(InValue.Storage); }
private:
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());
}
friend FORCEINLINE constexpr void Swap(TFunctionImpl& A, TFunctionImpl& B) requires (!bIsRef) { Swap(A.Storage, B.Storage); }
};
NAMESPACE_PRIVATE_END
@ -647,6 +641,8 @@ public:
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>
@ -735,6 +731,8 @@ public:
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");

View File

@ -57,7 +57,7 @@ public:
}
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)
: 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;
return NAMESPACE_REDCRAFT::GetTypeHash(GetValue());
if (!A.IsValid()) return 2824517378;
return GetTypeHash(A.GetValue());
}
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);
Reset();
return;
B = MoveTemp(A);
A.Reset();
}
if (InValue.IsValid() && !IsValid())
else if (!A.IsValid() && B.IsValid())
{
*this = MoveTemp(InValue);
InValue.Reset();
return;
A = MoveTemp(B);
B.Reset();
}
else
{
Swap(A.GetValue(), B.GetValue());
}
NAMESPACE_REDCRAFT::Swap(GetValue(), InValue.GetValue());
}
private:

View File

@ -47,9 +47,9 @@ public:
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:

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() 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)>());
}
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)>());
}

View File

@ -86,12 +86,6 @@ FORCEINLINE constexpr size_t GetTypeHash(T 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>; })
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);
}
template <typename T> requires (requires(T& A, T& B) { A.Swap(B); }
|| (CMoveConstructible<T> && CMoveAssignable<T>))
template <typename T> requires (CMoveConstructible<T> && CMoveAssignable<T>)
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);
A = MoveTemp(B);
B = MoveTemp(Temp);
}
}
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...>; }
&& !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))
{ }
@ -217,13 +217,13 @@ public:
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&
{
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&
{
return HoldsAlternative<T>() ? SynthThreeWayCompare(GetValue<T>(), InValue) : partial_ordering::unordered;
@ -287,51 +287,43 @@ public:
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;
using NAMESPACE_REDCRAFT::GetTypeHash;
if (!A.IsValid()) return 114514;
using FHashImpl = size_t(*)(const void*);
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);
Reset();
return;
B = MoveTemp(A);
A.Reset();
}
if (InValue.IsValid() && !IsValid())
else if (!A.IsValid() && B.IsValid())
{
*this = MoveTemp(InValue);
InValue.Reset();
return;
A = MoveTemp(B);
B.Reset();
}
if (GetIndex() == InValue.GetIndex())
else if (A.GetIndex() == B.GetIndex())
{
using NAMESPACE_REDCRAFT::Swap;
using FSwapImpl = void(*)(void*, void*);
constexpr FSwapImpl SwapImpl[] = { [](void* A, void* B) { Swap(*reinterpret_cast<Ts*>(A), *reinterpret_cast<Ts*>(B)); }... };
SwapImpl[GetIndex()](&Value, &InValue.Value);
return;
SwapImpl[A.GetIndex()](&A.Value, &B.Value);
}
else
{
TVariant Temp = MoveTemp(A);
A = MoveTemp(B);
B = MoveTemp(Temp);
}
TVariant Temp = MoveTemp(*this);
*this = MoveTemp(InValue);
InValue = MoveTemp(Temp);
}
private: