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*);
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
{
bool bIsInline;
@ -102,6 +111,7 @@ struct FAnyRTTI
FAnyMoveConstructFunc MoveConstruct;
FAnyCopyAssignFunc CopyAssign;
FAnyMoveAssignFunc MoveAssign;
FAnySwapFunc SwapObject;
};
template <typename T, bool bInIsInline>
@ -118,6 +128,7 @@ struct TAnyRTTIHelper
AnyMoveConstruct<T>,
AnyCopyAssign<T>,
AnyMoveAssign<T>,
AnySwap<T>,
};
};
@ -315,6 +326,35 @@ struct TAny
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:
union
@ -369,30 +409,6 @@ constexpr bool operator==(const TAny<InlineSize, InlineAlignment>& LHS, FInvalid
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 <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 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:
using CallFunc = ResultType(*)(void*, Types&&...);
@ -412,54 +434,6 @@ constexpr bool operator==(const TUniqueFunction<F>& LHS, nullptr_t)
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(TFunction<void()>) == 64, "The byte size of TFunction 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:
TAlignedStorage<sizeof(OptionalType), alignof(OptionalType)>::Type Value;
@ -273,28 +295,6 @@ constexpr TOptional<T> MakeOptional(Types&&... 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<TOptional<T>> : FTrue { };

View File

@ -207,6 +207,11 @@ protected:
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
@ -371,6 +376,11 @@ public:
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>
@ -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>
struct TTupleVisitImpl;
@ -578,12 +575,6 @@ constexpr typename TCommonComparisonCategory<typename TSynthThreeWayResult<LHSTy
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
constexpr void VisitTuple(F&& Func) { }

View File

@ -61,12 +61,20 @@ constexpr T&& Forward(typename TRemoveReference<T>::Type&& 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)
{
T Temp = MoveTemp(A);
A = MoveTemp(B);
B = MoveTemp(Temp);
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 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*);
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>
struct TVariantHelper
{
@ -141,6 +150,7 @@ struct TVariantHelper
static constexpr FVariantCopyAssignFunc CopyAssignFuncs[] = { VariantCopyAssign<Types>... };
static constexpr FVariantMoveAssignFunc MoveAssignFuncs[] = { VariantMoveAssign<Types>... };
static constexpr FVariantEqualityOperatorFunc EqualityOperatorFuncs[] = { VariantEqualityOperator<Types>... };
static constexpr FVariantSwapFunc SwapFuncs[] = { VariantSwap<Types>... };
};
template <typename R, typename F, typename T>
@ -425,6 +435,35 @@ struct TVariant
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:
@ -454,30 +493,6 @@ constexpr bool operator==(const TVariant<Types...>& LHS, FInvalid)
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... Types> struct TIsTVariant<TVariant<Types...>> : FTrue { };