refactor(templates): refactor Swap into a member function

This commit is contained in:
_Redstone_c_ 2022-04-14 22:41:22 +08:00
parent 5c82ab1e0d
commit 018d3afb73
6 changed files with 145 additions and 141 deletions

View File

@ -91,6 +91,15 @@ void AnyMoveAssign(void* Target, void* Source)
using FAnyMoveAssignFunc = void(*)(void*, void*); using FAnyMoveAssignFunc = void(*)(void*, void*);
template <typename T>
void AnySwap(void* A, void* B)
{
if constexpr (TIsSwappable<T>::Value) Swap(*reinterpret_cast<T*>(A), *reinterpret_cast<T*>(B));
else check_no_entry();
}
using FAnySwapFunc = void(*)(void*, void*);
struct FAnyRTTI struct FAnyRTTI
{ {
bool bIsInline; bool bIsInline;
@ -102,6 +111,7 @@ struct FAnyRTTI
FAnyMoveConstructFunc MoveConstruct; FAnyMoveConstructFunc MoveConstruct;
FAnyCopyAssignFunc CopyAssign; FAnyCopyAssignFunc CopyAssign;
FAnyMoveAssignFunc MoveAssign; FAnyMoveAssignFunc MoveAssign;
FAnySwapFunc SwapObject;
}; };
template <typename T, bool bInIsInline> template <typename T, bool bInIsInline>
@ -118,6 +128,7 @@ struct TAnyRTTIHelper
AnyMoveConstruct<T>, AnyMoveConstruct<T>,
AnyCopyAssign<T>, AnyCopyAssign<T>,
AnyMoveAssign<T>, AnyMoveAssign<T>,
AnySwap<T>,
}; };
}; };
@ -315,6 +326,35 @@ struct TAny
ResetImpl(); ResetImpl();
} }
constexpr void Swap(TAny& InValue)
{
if (!IsValid() && !InValue.IsValid()) return;
if (IsValid() && !InValue.IsValid())
{
InValue = MoveTemp(*this);
Reset();
return;
}
if (InValue.IsValid() && !IsValid())
{
*this = MoveTemp(InValue);
InValue.Reset();
return;
}
if (GetTypeInfo() == InValue.GetTypeInfo())
{
RTTI->SwapObject(GetData(), InValue.GetData());
return;
}
TAny Temp = MoveTemp(*this);
*this = MoveTemp(InValue);
InValue = MoveTemp(Temp);
}
private: private:
union union
@ -369,30 +409,6 @@ constexpr bool operator==(const TAny<InlineSize, InlineAlignment>& LHS, FInvalid
return !LHS.IsValid(); return !LHS.IsValid();
} }
template <size_t InlineSize, size_t InlineAlignment>
constexpr void Swap(TAny<InlineSize, InlineAlignment>& A, TAny<InlineSize, InlineAlignment>& B)
{
if (!A && !B) return;
if (A && !B)
{
B = MoveTemp(A);
A.Reset();
return;
}
if (B && !A)
{
A = MoveTemp(B);
B.Reset();
return;
}
TAny<InlineSize, InlineAlignment> Temp = MoveTemp(A);
A = MoveTemp(B);
B = MoveTemp(Temp);
}
template <typename T> struct TIsTAny : FFalse { }; template <typename T> struct TIsTAny : FFalse { };
template <size_t InlineSize, size_t InlineAlignment> struct TIsTAny<TAny<InlineSize, InlineAlignment>> : FTrue { }; template <size_t InlineSize, size_t InlineAlignment> struct TIsTAny<TAny<InlineSize, InlineAlignment>> : FTrue { };

View File

@ -292,6 +292,28 @@ public:
constexpr void Reset() requires (FunctionType != EFunctionType::Reference) { Call = nullptr; } constexpr void Reset() requires (FunctionType != EFunctionType::Reference) { Call = nullptr; }
constexpr void Swap(TFunctionImpl& InValue) requires (FunctionType != EFunctionType::Reference)
{
if (!IsValid() && !InValue.IsValid()) return;
if (IsValid() && !InValue.IsValid())
{
InValue = MoveTemp(*this);
Reset();
return;
}
if (InValue.IsValid() && !IsValid())
{
*this = MoveTemp(InValue);
InValue.Reset();
return;
}
NAMESPACE_REDCRAFT::Swap(Call, InValue.Call);
NAMESPACE_REDCRAFT::Swap(Storage, InValue.Storage);
}
private: private:
using CallFunc = ResultType(*)(void*, Types&&...); using CallFunc = ResultType(*)(void*, Types&&...);
@ -412,54 +434,6 @@ constexpr bool operator==(const TUniqueFunction<F>& LHS, nullptr_t)
return !LHS; return !LHS;
} }
template <typename F, size_t I, size_t J>
constexpr void Swap(TFunction<F, I, J>& A, TFunction<F, I, J>& B)
{
if (!A && !B) return;
if (A && !B)
{
B = MoveTemp(A);
A = nullptr;
return;
}
if (B && !A)
{
A = MoveTemp(B);
B = nullptr;
return;
}
TFunction<F, I, J> Temp = MoveTemp(A);
A = MoveTemp(B);
B = MoveTemp(Temp);
}
template <typename F, size_t I, size_t J>
constexpr void Swap(TUniqueFunction<F, I, J>& A, TUniqueFunction<F, I, J>& B)
{
if (!A && !B) return;
if (A && !B)
{
B = MoveTemp(A);
A = nullptr;
return;
}
if (B && !A)
{
A = MoveTemp(B);
B = nullptr;
return;
}
TFunction<F, I, J> Temp = MoveTemp(A);
A = MoveTemp(B);
B = MoveTemp(Temp);
}
static_assert(sizeof(TFunctionRef<void()>) == 16, "The byte size of TFunctionRef is unexpected"); static_assert(sizeof(TFunctionRef<void()>) == 16, "The byte size of TFunctionRef is unexpected");
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");
static_assert(sizeof(TUniqueFunction<void()>) == 64, "The byte size of TUniqueFunction is unexpected"); static_assert(sizeof(TUniqueFunction<void()>) == 64, "The byte size of TUniqueFunction is unexpected");

View File

@ -225,6 +225,28 @@ public:
} }
} }
template <typename T> requires TIsMoveConstructible<OptionalType>::Value && TIsSwappable<OptionalType>::Value
constexpr void Swap(TOptional& InValue)
{
if (!IsValid() && !InValue.IsValid()) return;
if (IsValid() && !InValue.IsValid())
{
InValue = MoveTemp(*this);
Reset();
return;
}
if (InValue.IsValid() && !IsValid())
{
*this = MoveTemp(InValue);
InValue.Reset();
return;
}
NAMESPACE_REDCRAFT::Swap(GetValue(), InValue.GetValue());
}
private: private:
TAlignedStorage<sizeof(OptionalType), alignof(OptionalType)>::Type Value; TAlignedStorage<sizeof(OptionalType), alignof(OptionalType)>::Type Value;
@ -273,28 +295,6 @@ constexpr TOptional<T> MakeOptional(Types&&... Args)
return TOptional<T>(InPlace, Forward<T>(Args)...); return TOptional<T>(InPlace, Forward<T>(Args)...);
} }
template <typename T> requires TIsMoveConstructible<T>::Value&& TIsSwappable<T>::Value
constexpr void Swap(TOptional<T>& A, TOptional<T>& B)
{
if (!A && !B) return;
if (A && !B)
{
B = MoveTemp(A);
A.Reset();
return;
}
if (B && !A)
{
A = MoveTemp(B);
B.Reset();
return;
}
Swap(*A, *B);
}
template <typename T> struct TIsTOptional : FFalse { }; template <typename T> struct TIsTOptional : FFalse { };
template <typename T> struct TIsTOptional<TOptional<T>> : FTrue { }; template <typename T> struct TIsTOptional<TOptional<T>> : FTrue { };

View File

@ -207,6 +207,11 @@ protected:
return T(Forward<TTupleType>(Arg).template GetValue<Indices>()...); return T(Forward<TTupleType>(Arg).template GetValue<Indices>()...);
} }
template <typename TTupleType>
static constexpr void Swap(TTupleType& A, TTupleType& B)
{
((NAMESPACE_REDCRAFT::Swap(A.template GetValue<Indices>(), B.template GetValue<Indices>())), ...);
}
}; };
NAMESPACE_PRIVATE_END NAMESPACE_PRIVATE_END
@ -371,6 +376,11 @@ public:
constexpr size_t GetTypeHash() const requires (true && ... && CHashable<Types>); constexpr size_t GetTypeHash() const requires (true && ... && CHashable<Types>);
constexpr void Swap(TTuple& InValue) requires (true && ... && (TIsMoveConstructible<Types>::Value&& TIsSwappable<Types>::Value))
{
Super::Swap(*this, InValue);
}
}; };
template <typename... Types> template <typename... Types>
@ -517,19 +527,6 @@ struct TTupleThreeWay<R, TIndexSequence<>>
} }
}; };
template <typename Indices>
struct TTupleSwapImpl;
template <size_t... Indices>
struct TTupleSwapImpl<TIndexSequence<Indices...>>
{
template <typename TTupleType>
static constexpr void F(TTupleType& A, TTupleType& B)
{
((Swap(A.template GetValue<Indices>(), B.template GetValue<Indices>())), ...);
}
};
template <typename Indices> template <typename Indices>
struct TTupleVisitImpl; struct TTupleVisitImpl;
@ -578,12 +575,6 @@ constexpr typename TCommonComparisonCategory<typename TSynthThreeWayResult<LHSTy
return NAMESPACE_PRIVATE::TTupleThreeWay<R, TMakeIndexSequence<sizeof...(LHSTypes)>>::F(LHS, RHS); return NAMESPACE_PRIVATE::TTupleThreeWay<R, TMakeIndexSequence<sizeof...(LHSTypes)>>::F(LHS, RHS);
} }
template <typename... Types> requires (true && ... && (TIsMoveConstructible<Types>::Value && TIsSwappable<Types>::Value))
constexpr void Swap(TTuple<Types...>& A, TTuple<Types...>& B)
{
NAMESPACE_PRIVATE::TTupleSwapImpl<TIndexSequenceFor<Types...>>::F(A, B);
}
template <typename F> requires TIsInvocable<F>::Value template <typename F> requires TIsInvocable<F>::Value
constexpr void VisitTuple(F&& Func) { } constexpr void VisitTuple(F&& Func) { }

View File

@ -61,12 +61,20 @@ constexpr T&& Forward(typename TRemoveReference<T>::Type&& Obj)
return (T&&)Obj; return (T&&)Obj;
} }
template <typename T> requires TIsMoveConstructible<T>::Value && TIsMoveAssignable<T>::Value template <typename T> requires requires(T& A, T& B) { A.Swap(B); }
|| (TIsMoveConstructible<T>::Value && TIsMoveAssignable<T>::Value)
constexpr void Swap(T& A, T& B) constexpr void Swap(T& A, T& B)
{ {
T Temp = MoveTemp(A); if constexpr (requires(T& A, T& B) { A.Swap(B); })
A = MoveTemp(B); {
B = MoveTemp(Temp); A.Swap(B);
}
else
{
T Temp = MoveTemp(A);
A = MoveTemp(B);
B = MoveTemp(Temp);
}
} }
template <typename T, typename U = T> requires TIsMoveConstructible<T>::Value && TIsAssignable<T&, U>::Value template <typename T, typename U = T> requires TIsMoveConstructible<T>::Value && TIsAssignable<T&, U>::Value

View File

@ -132,6 +132,15 @@ constexpr bool VariantEqualityOperator(const void* LHS, const void* RHS)
using FVariantEqualityOperatorFunc = bool(*)(const void*, const void*); using FVariantEqualityOperatorFunc = bool(*)(const void*, const void*);
template <typename T>
constexpr void VariantSwap(void* A, void* B)
{
if constexpr (TIsSwappable<T>::Value) Swap(*reinterpret_cast<T*>(A), *reinterpret_cast<T*>(B));
else check_no_entry();
}
using FVariantSwapFunc = void(*)(void*, void*);
template <typename... Types> template <typename... Types>
struct TVariantHelper struct TVariantHelper
{ {
@ -141,6 +150,7 @@ struct TVariantHelper
static constexpr FVariantCopyAssignFunc CopyAssignFuncs[] = { VariantCopyAssign<Types>... }; static constexpr FVariantCopyAssignFunc CopyAssignFuncs[] = { VariantCopyAssign<Types>... };
static constexpr FVariantMoveAssignFunc MoveAssignFuncs[] = { VariantMoveAssign<Types>... }; static constexpr FVariantMoveAssignFunc MoveAssignFuncs[] = { VariantMoveAssign<Types>... };
static constexpr FVariantEqualityOperatorFunc EqualityOperatorFuncs[] = { VariantEqualityOperator<Types>... }; static constexpr FVariantEqualityOperatorFunc EqualityOperatorFuncs[] = { VariantEqualityOperator<Types>... };
static constexpr FVariantSwapFunc SwapFuncs[] = { VariantSwap<Types>... };
}; };
template <typename R, typename F, typename T> template <typename R, typename F, typename T>
@ -425,6 +435,35 @@ struct TVariant
TypeIndex = INDEX_NONE; TypeIndex = INDEX_NONE;
} }
constexpr void Swap(TVariant& InValue) requires (true && ... && (TIsMoveConstructible<Types>::Value && TIsSwappable<Types>::Value))
{
if (!IsValid() && !InValue.IsValid()) return;
if (IsValid() && !InValue.IsValid())
{
InValue = MoveTemp(*this);
Reset();
return;
}
if (InValue.IsValid() && !IsValid())
{
*this = MoveTemp(InValue);
InValue.Reset();
return;
}
if (GetIndex() == InValue.GetIndex())
{
FHelper::SwapFuncs[GetIndex()](GetData(), InValue.GetData());
return;
}
TVariant Temp = MoveTemp(*this);
*this = MoveTemp(InValue);
InValue = MoveTemp(Temp);
}
private: private:
@ -454,30 +493,6 @@ constexpr bool operator==(const TVariant<Types...>& LHS, FInvalid)
return !LHS.IsValid(); return !LHS.IsValid();
} }
template <typename... Types> requires (true && ... && (TIsMoveConstructible<Types>::Value && TIsSwappable<Types>::Value))
constexpr void Swap(TVariant<Types...>& A, TVariant<Types...>& B)
{
if (!A && !B) return;
if (A && !B)
{
B = MoveTemp(A);
A.Reset();
return;
}
if (B && !A)
{
A = MoveTemp(B);
B.Reset();
return;
}
TVariant<Types...> Temp = MoveTemp(A);
A = MoveTemp(B);
B = MoveTemp(Temp);
}
template <typename T > struct TIsTVariant : FFalse { }; template <typename T > struct TIsTVariant : FFalse { };
template <typename... Types> struct TIsTVariant<TVariant<Types...>> : FTrue { }; template <typename... Types> struct TIsTVariant<TVariant<Types...>> : FTrue { };