diff --git a/Redcraft.Utility/Source/Public/Templates/Any.h b/Redcraft.Utility/Source/Public/Templates/Any.h index ac29222..4d56346 100644 --- a/Redcraft.Utility/Source/Public/Templates/Any.h +++ b/Redcraft.Utility/Source/Public/Templates/Any.h @@ -91,6 +91,15 @@ void AnyMoveAssign(void* Target, void* Source) using FAnyMoveAssignFunc = void(*)(void*, void*); +template +void AnySwap(void* A, void* B) +{ + if constexpr (TIsSwappable::Value) Swap(*reinterpret_cast(A), *reinterpret_cast(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 @@ -118,6 +128,7 @@ struct TAnyRTTIHelper AnyMoveConstruct, AnyCopyAssign, AnyMoveAssign, + AnySwap, }; }; @@ -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& LHS, FInvalid return !LHS.IsValid(); } -template -constexpr void Swap(TAny& A, TAny& B) -{ - if (!A && !B) return; - - if (A && !B) - { - B = MoveTemp(A); - A.Reset(); - return; - } - - if (B && !A) - { - A = MoveTemp(B); - B.Reset(); - return; - } - - TAny Temp = MoveTemp(A); - A = MoveTemp(B); - B = MoveTemp(Temp); -} - template struct TIsTAny : FFalse { }; template struct TIsTAny> : FTrue { }; diff --git a/Redcraft.Utility/Source/Public/Templates/Function.h b/Redcraft.Utility/Source/Public/Templates/Function.h index 74cdc0c..f1461f2 100644 --- a/Redcraft.Utility/Source/Public/Templates/Function.h +++ b/Redcraft.Utility/Source/Public/Templates/Function.h @@ -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& LHS, nullptr_t) return !LHS; } -template -constexpr void Swap(TFunction& A, TFunction& B) -{ - if (!A && !B) return; - - if (A && !B) - { - B = MoveTemp(A); - A = nullptr; - return; - } - - if (B && !A) - { - A = MoveTemp(B); - B = nullptr; - return; - } - - TFunction Temp = MoveTemp(A); - A = MoveTemp(B); - B = MoveTemp(Temp); -} - -template -constexpr void Swap(TUniqueFunction& A, TUniqueFunction& B) -{ - if (!A && !B) return; - - if (A && !B) - { - B = MoveTemp(A); - A = nullptr; - return; - } - - if (B && !A) - { - A = MoveTemp(B); - B = nullptr; - return; - } - - TFunction Temp = MoveTemp(A); - A = MoveTemp(B); - B = MoveTemp(Temp); -} - static_assert(sizeof(TFunctionRef) == 16, "The byte size of TFunctionRef is unexpected"); static_assert(sizeof(TFunction) == 64, "The byte size of TFunction is unexpected"); static_assert(sizeof(TUniqueFunction) == 64, "The byte size of TUniqueFunction is unexpected"); diff --git a/Redcraft.Utility/Source/Public/Templates/Optional.h b/Redcraft.Utility/Source/Public/Templates/Optional.h index 1b65418..5f7d901 100644 --- a/Redcraft.Utility/Source/Public/Templates/Optional.h +++ b/Redcraft.Utility/Source/Public/Templates/Optional.h @@ -225,6 +225,28 @@ public: } } + template requires TIsMoveConstructible::Value && TIsSwappable::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::Type Value; @@ -273,28 +295,6 @@ constexpr TOptional MakeOptional(Types&&... Args) return TOptional(InPlace, Forward(Args)...); } -template requires TIsMoveConstructible::Value&& TIsSwappable::Value -constexpr void Swap(TOptional& A, TOptional& 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 struct TIsTOptional : FFalse { }; template struct TIsTOptional> : FTrue { }; diff --git a/Redcraft.Utility/Source/Public/Templates/Tuple.h b/Redcraft.Utility/Source/Public/Templates/Tuple.h index 5a0b051..62a6b55 100644 --- a/Redcraft.Utility/Source/Public/Templates/Tuple.h +++ b/Redcraft.Utility/Source/Public/Templates/Tuple.h @@ -207,6 +207,11 @@ protected: return T(Forward(Arg).template GetValue()...); } + template + static constexpr void Swap(TTupleType& A, TTupleType& B) + { + ((NAMESPACE_REDCRAFT::Swap(A.template GetValue(), B.template GetValue())), ...); + } }; NAMESPACE_PRIVATE_END @@ -371,6 +376,11 @@ public: constexpr size_t GetTypeHash() const requires (true && ... && CHashable); + constexpr void Swap(TTuple& InValue) requires (true && ... && (TIsMoveConstructible::Value&& TIsSwappable::Value)) + { + Super::Swap(*this, InValue); + } + }; template @@ -517,19 +527,6 @@ struct TTupleThreeWay> } }; -template -struct TTupleSwapImpl; - -template -struct TTupleSwapImpl> -{ - template - static constexpr void F(TTupleType& A, TTupleType& B) - { - ((Swap(A.template GetValue(), B.template GetValue())), ...); - } -}; - template struct TTupleVisitImpl; @@ -578,12 +575,6 @@ constexpr typename TCommonComparisonCategory>::F(LHS, RHS); } -template requires (true && ... && (TIsMoveConstructible::Value && TIsSwappable::Value)) -constexpr void Swap(TTuple& A, TTuple& B) -{ - NAMESPACE_PRIVATE::TTupleSwapImpl>::F(A, B); -} - template requires TIsInvocable::Value constexpr void VisitTuple(F&& Func) { } diff --git a/Redcraft.Utility/Source/Public/Templates/Utility.h b/Redcraft.Utility/Source/Public/Templates/Utility.h index e0c0ae6..0a3dc73 100644 --- a/Redcraft.Utility/Source/Public/Templates/Utility.h +++ b/Redcraft.Utility/Source/Public/Templates/Utility.h @@ -61,12 +61,20 @@ constexpr T&& Forward(typename TRemoveReference::Type&& Obj) return (T&&)Obj; } -template requires TIsMoveConstructible::Value && TIsMoveAssignable::Value +template requires requires(T& A, T& B) { A.Swap(B); } + || (TIsMoveConstructible::Value && TIsMoveAssignable::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 requires TIsMoveConstructible::Value && TIsAssignable::Value diff --git a/Redcraft.Utility/Source/Public/Templates/Variant.h b/Redcraft.Utility/Source/Public/Templates/Variant.h index 08f8b2c..ef5704a 100644 --- a/Redcraft.Utility/Source/Public/Templates/Variant.h +++ b/Redcraft.Utility/Source/Public/Templates/Variant.h @@ -132,6 +132,15 @@ constexpr bool VariantEqualityOperator(const void* LHS, const void* RHS) using FVariantEqualityOperatorFunc = bool(*)(const void*, const void*); +template +constexpr void VariantSwap(void* A, void* B) +{ + if constexpr (TIsSwappable::Value) Swap(*reinterpret_cast(A), *reinterpret_cast(B)); + else check_no_entry(); +} + +using FVariantSwapFunc = void(*)(void*, void*); + template struct TVariantHelper { @@ -141,6 +150,7 @@ struct TVariantHelper static constexpr FVariantCopyAssignFunc CopyAssignFuncs[] = { VariantCopyAssign... }; static constexpr FVariantMoveAssignFunc MoveAssignFuncs[] = { VariantMoveAssign... }; static constexpr FVariantEqualityOperatorFunc EqualityOperatorFuncs[] = { VariantEqualityOperator... }; + static constexpr FVariantSwapFunc SwapFuncs[] = { VariantSwap... }; }; template @@ -425,6 +435,35 @@ struct TVariant TypeIndex = INDEX_NONE; } + + constexpr void Swap(TVariant& InValue) requires (true && ... && (TIsMoveConstructible::Value && TIsSwappable::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& LHS, FInvalid) return !LHS.IsValid(); } -template requires (true && ... && (TIsMoveConstructible::Value && TIsSwappable::Value)) -constexpr void Swap(TVariant& A, TVariant& B) -{ - if (!A && !B) return; - - if (A && !B) - { - B = MoveTemp(A); - A.Reset(); - return; - } - - if (B && !A) - { - A = MoveTemp(B); - B.Reset(); - return; - } - - TVariant Temp = MoveTemp(A); - A = MoveTemp(B); - B = MoveTemp(Temp); -} - template struct TIsTVariant : FFalse { }; template struct TIsTVariant> : FTrue { };