diff --git a/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp b/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp index 679a6e0..eaa3138 100644 --- a/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp +++ b/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp @@ -1233,6 +1233,8 @@ void TestFunction() TFunction Identity = [](bool In) { return In; }; TFunction NotIdentity = NotFn(Identity); + always_check(NotFn(Identity)(false)); + always_check(Identity(true)); always_check(NotIdentity(false)); } diff --git a/Redcraft.Utility/Source/Public/Templates/Any.h b/Redcraft.Utility/Source/Public/Templates/Any.h index 1eaec55..82f20b0 100644 --- a/Redcraft.Utility/Source/Public/Templates/Any.h +++ b/Redcraft.Utility/Source/Public/Templates/Any.h @@ -13,31 +13,73 @@ NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) -inline constexpr size_t ANY_DEFAULT_INLINE_SIZE = 64 - sizeof(uintptr); -inline constexpr size_t ANY_DEFAULT_INLINE_ALIGNMENT = 16; +// TAny's CustomStorage concept, see FAnyDefaultStorage. +template +concept CAnyStorage = true; // TODO -template requires (Memory::IsValidAlignment(InlineAlignment)) -struct alignas(InlineAlignment) TAny +// TAny's default storage structure. +struct alignas(16) FAnyDefaultStorage { - constexpr TAny() : TypeInfo(0) { } + // The built-in copy/move operators are disabled and CopyCustom/MoveCustom is used instead of them. + + // You can add custom variables like this. + //Type Variable; + + //~ Begin CAnyStorage Interface + inline static constexpr size_t InlineSize = 64 - sizeof(uintptr); + inline static constexpr size_t InlineAlignment = 16; + constexpr void* InlineAllocation() { return &InlineAllocationImpl; } + constexpr const void* InlineAllocation() const { return &InlineAllocationImpl; } + constexpr void*& HeapAllocation() { return HeapAllocationImpl; } + constexpr void* HeapAllocation() const { return HeapAllocationImpl; } + constexpr uintptr& TypeInfo() { return TypeInfoImpl; } + constexpr uintptr TypeInfo() const { return TypeInfoImpl; } + constexpr void CopyCustom(const FAnyDefaultStorage& InValue) { /* Variable = InValue.Variable; */ } // You just need to copy the custom variables. + constexpr void MoveCustom( FAnyDefaultStorage&& InValue) { /* Variable = MoveTemp(InValue.Variable); */ } // You just need to move the custom variables. + //~ End CAnyStorage Interface + + union + { + uint8 InlineAllocationImpl[InlineSize]; + void* HeapAllocationImpl; + }; + + uintptr TypeInfoImpl; + +}; + +static_assert(CAnyStorage); + +// You can add custom storage area through CustomStorage, such as TFunction. +// It is not recommended to use this, FAny is recommended. +template +struct TAny +{ + inline static constexpr size_t InlineSize = CustomStorage::InlineSize; + inline static constexpr size_t InlineAlignment = CustomStorage::InlineAlignment; + + constexpr TAny() { Storage.TypeInfo() = 0; } constexpr TAny(FInvalid) : TAny() { } - + FORCEINLINE TAny(const TAny& InValue) - : TypeInfo(InValue.TypeInfo) { + Storage.CopyCustom(InValue.Storage); + + Storage.TypeInfo() = InValue.Storage.TypeInfo(); + if (!IsValid()) return; switch (GetRepresentation()) { case ERepresentation::Trivial: - Memory::Memcpy(InlineAllocation, InValue.InlineAllocation); + Memory::Memcpy(Storage.InlineAllocation(), InValue.Storage.InlineAllocation(), Storage.InlineSize); break; case ERepresentation::Small: GetTypeInfoImpl().CopyConstructImpl(GetAllocation(), InValue.GetAllocation()); break; case ERepresentation::Big: - HeapAllocation = Memory::Malloc(GetTypeInfoImpl().TypeSize, GetTypeInfoImpl().TypeAlignment); + Storage.HeapAllocation() = Memory::Malloc(GetTypeInfoImpl().TypeSize, GetTypeInfoImpl().TypeAlignment); GetTypeInfoImpl().CopyConstructImpl(GetAllocation(), InValue.GetAllocation()); break; default: check_no_entry(); @@ -45,21 +87,24 @@ struct alignas(InlineAlignment) TAny } FORCEINLINE TAny(TAny&& InValue) - : TypeInfo(InValue.TypeInfo) { + Storage.MoveCustom(MoveTemp(InValue.Storage)); + + Storage.TypeInfo() = InValue.Storage.TypeInfo(); + if (!IsValid()) return; switch (GetRepresentation()) { case ERepresentation::Trivial: - Memory::Memcpy(InlineAllocation, InValue.InlineAllocation); + Memory::Memcpy(Storage.InlineAllocation(), InValue.Storage.InlineAllocation(), Storage.InlineSize); break; case ERepresentation::Small: GetTypeInfoImpl().MoveConstructImpl(GetAllocation(), InValue.GetAllocation()); break; case ERepresentation::Big: - HeapAllocation = InValue.HeapAllocation; - InValue.TypeInfo = 0; + Storage.HeapAllocation() = InValue.Storage.HeapAllocation(); + InValue.Storage.TypeInfo() = 0; break; default: check_no_entry(); } @@ -87,6 +132,8 @@ struct alignas(InlineAlignment) TAny { if (&InValue == this) return *this; + Storage.CopyCustom(InValue.Storage); + if (!InValue.IsValid()) { Reset(); @@ -96,7 +143,7 @@ struct alignas(InlineAlignment) TAny switch (GetRepresentation()) { case ERepresentation::Trivial: - Memory::Memcpy(InlineAllocation, InValue.InlineAllocation); + Memory::Memcpy(Storage.InlineAllocation(), InValue.Storage.InlineAllocation(), Storage.InlineSize); break; case ERepresentation::Small: case ERepresentation::Big: @@ -109,18 +156,18 @@ struct alignas(InlineAlignment) TAny { ResetImpl(); - TypeInfo = InValue.TypeInfo; + Storage.TypeInfo() = InValue.Storage.TypeInfo(); switch (GetRepresentation()) { case ERepresentation::Trivial: - Memory::Memcpy(InlineAllocation, InValue.InlineAllocation); + Memory::Memcpy(Storage.InlineAllocation(), InValue.Storage.InlineAllocation(), Storage.InlineSize); break; case ERepresentation::Small: GetTypeInfoImpl().CopyConstructImpl(GetAllocation(), InValue.GetAllocation()); break; case ERepresentation::Big: - HeapAllocation = Memory::Malloc(GetTypeInfoImpl().TypeSize, GetTypeInfoImpl().TypeAlignment); + Storage.HeapAllocation() = Memory::Malloc(GetTypeInfoImpl().TypeSize, GetTypeInfoImpl().TypeAlignment); GetTypeInfoImpl().CopyConstructImpl(GetAllocation(), InValue.GetAllocation()); break; default: check_no_entry(); @@ -134,6 +181,8 @@ struct alignas(InlineAlignment) TAny { if (&InValue == this) return *this; + Storage.MoveCustom(MoveTemp(InValue.Storage)); + if (!InValue.IsValid()) { Reset(); @@ -143,15 +192,15 @@ struct alignas(InlineAlignment) TAny switch (GetRepresentation()) { case ERepresentation::Trivial: - Memory::Memcpy(InlineAllocation, InValue.InlineAllocation); + Memory::Memcpy(Storage.InlineAllocation(), InValue.Storage.InlineAllocation(), Storage.InlineSize); break; case ERepresentation::Small: GetTypeInfoImpl().MoveAssignImpl(GetAllocation(), InValue.GetAllocation()); break; case ERepresentation::Big: ResetImpl(); - HeapAllocation = InValue.HeapAllocation; - InValue.TypeInfo = 0; + Storage.HeapAllocation() = InValue.Storage.HeapAllocation(); + InValue.Storage.TypeInfo() = 0; break; default: check_no_entry(); } @@ -160,19 +209,19 @@ struct alignas(InlineAlignment) TAny { ResetImpl(); - TypeInfo = InValue.TypeInfo; + Storage.TypeInfo() = InValue.Storage.TypeInfo(); switch (GetRepresentation()) { case ERepresentation::Trivial: - Memory::Memcpy(InlineAllocation, InValue.InlineAllocation); + Memory::Memcpy(Storage.InlineAllocation(), InValue.Storage.InlineAllocation(), Storage.InlineSize); break; case ERepresentation::Small: GetTypeInfoImpl().MoveConstructImpl(GetAllocation(), InValue.GetAllocation()); break; case ERepresentation::Big: - HeapAllocation = InValue.HeapAllocation; - InValue.TypeInfo = 0; + Storage.HeapAllocation() = InValue.Storage.HeapAllocation(); + InValue.Storage.TypeInfo() = 0; break; default: check_no_entry(); } @@ -211,10 +260,10 @@ struct alignas(InlineAlignment) TAny return GetValue(); } - constexpr const type_info& GetTypeInfo() const { return IsValid() ? *GetTypeInfoImpl().TypeInfo : typeid(void); } + constexpr const type_info& GetTypeInfo() const { return IsValid() ? *GetTypeInfoImpl().NativeTypeInfo : typeid(void); } - constexpr bool IsValid() const { return TypeInfo != 0; } - constexpr explicit operator bool() const { return TypeInfo != 0; } + constexpr bool IsValid() const { return Storage.TypeInfo() != 0; } + constexpr explicit operator bool() const { return Storage.TypeInfo() != 0; } template constexpr bool HoldsAlternative() const { return IsValid() ? GetTypeInfo() == typeid(T) : false; } @@ -236,10 +285,13 @@ struct alignas(InlineAlignment) TAny template requires CSameAs>&& CDestructible> constexpr const T& Get(const T& DefaultValue) const& { return HoldsAlternative() ? GetValue() : DefaultValue; } + constexpr CustomStorage& GetCustomStorage() requires (!CSameAs) { return Storage; } + constexpr const CustomStorage& GetCustomStorage() const requires (!CSameAs) { return Storage; } + FORCEINLINE void Reset() { ResetImpl(); - TypeInfo = 0; + Storage.TypeInfo() = 0; } FORCEINLINE size_t GetTypeHash() const @@ -280,6 +332,8 @@ struct alignas(InlineAlignment) TAny private: + CustomStorage Storage; + static constexpr uintptr_t RepresentationMask = 3; enum class ERepresentation : uint8 @@ -291,7 +345,7 @@ private: struct FTypeInfoImpl { - const type_info* TypeInfo; + const type_info* NativeTypeInfo; const size_t TypeSize; const size_t TypeAlignment; @@ -321,9 +375,9 @@ private: template constexpr FTypeInfoImpl(TInPlaceType) - : TypeInfo (&typeid(T)) - , TypeSize ( sizeof(T)) - , TypeAlignment (alignof(T)) + : NativeTypeInfo (&typeid(T)) + , TypeSize ( sizeof(T)) + , TypeAlignment (alignof(T)) , CopyConstructImpl ([](void* A, const void* B) { if constexpr (requires(T* A, const T* B) { Memory::CopyConstruct (A, B); }) Memory::CopyConstruct (reinterpret_cast(A), reinterpret_cast(B)); else checkf(false, TEXT("The type '%s' is not copy constructible."), typeid(Types).name()); }) , MoveConstructImpl ([](void* A, void* B) { if constexpr (requires(T* A, T* B) { Memory::MoveConstruct (A, B); }) Memory::MoveConstruct (reinterpret_cast(A), reinterpret_cast< T*>(B)); else checkf(false, TEXT("The type '%s' is not move constructible."), typeid(Types).name()); }) @@ -339,43 +393,35 @@ private: { } }; - union - { - TAlignedStorage InlineAllocation; - void* HeapAllocation; - }; + constexpr ERepresentation GetRepresentation() const { return static_cast(Storage.TypeInfo() & RepresentationMask); } + constexpr const FTypeInfoImpl& GetTypeInfoImpl() const { return *reinterpret_cast(Storage.TypeInfo() & ~RepresentationMask); } - uintptr TypeInfo; - - constexpr ERepresentation GetRepresentation() const { return static_cast(TypeInfo & RepresentationMask); } - constexpr const FTypeInfoImpl& GetTypeInfoImpl() const { return *reinterpret_cast(TypeInfo & ~RepresentationMask); } - - constexpr void* GetAllocation() { return GetRepresentation() == ERepresentation::Trivial || GetRepresentation() == ERepresentation::Small ? &InlineAllocation : HeapAllocation; } - constexpr const void* GetAllocation() const { return GetRepresentation() == ERepresentation::Trivial || GetRepresentation() == ERepresentation::Small ? &InlineAllocation : HeapAllocation; } + constexpr void* GetAllocation() { return GetRepresentation() == ERepresentation::Trivial || GetRepresentation() == ERepresentation::Small ? Storage.InlineAllocation() : Storage.HeapAllocation(); } + constexpr const void* GetAllocation() const { return GetRepresentation() == ERepresentation::Trivial || GetRepresentation() == ERepresentation::Small ? Storage.InlineAllocation() : Storage.HeapAllocation(); } template FORCEINLINE void EmplaceImpl(Types&&... Args) { static constexpr const FTypeInfoImpl SelectedTypeInfo(InPlaceType); - TypeInfo = reinterpret_cast(&SelectedTypeInfo); + Storage.TypeInfo() = reinterpret_cast(&SelectedTypeInfo); - constexpr bool bIsInlineStorable = sizeof(SelectedType) <= InlineSize && alignof(SelectedType) <= InlineAlignment; + constexpr bool bIsInlineStorable = sizeof(SelectedType) <= Storage.InlineSize && alignof(SelectedType) <= Storage.InlineAlignment; constexpr bool bIsTriviallyStorable = bIsInlineStorable && CTrivial && CTriviallyCopyable; if constexpr (bIsTriviallyStorable) { - new(&InlineAllocation) SelectedType(Forward(Args)...); - TypeInfo |= static_cast(ERepresentation::Trivial); + new(Storage.InlineAllocation()) SelectedType(Forward(Args)...); + Storage.TypeInfo() |= static_cast(ERepresentation::Trivial); } else if constexpr (bIsInlineStorable) { - new(&InlineAllocation) SelectedType(Forward(Args)...); - TypeInfo |= static_cast(ERepresentation::Small); + new(Storage.InlineAllocation()) SelectedType(Forward(Args)...); + Storage.TypeInfo() |= static_cast(ERepresentation::Small); } else { - HeapAllocation = new SelectedType(Forward(Args)...); - TypeInfo |= static_cast(ERepresentation::Big); + Storage.HeapAllocation() = new SelectedType(Forward(Args)...); + Storage.TypeInfo() |= static_cast(ERepresentation::Big); } } @@ -392,7 +438,7 @@ private: break; case ERepresentation::Big: GetTypeInfoImpl().DestroyImpl(GetAllocation()); - Memory::Free(HeapAllocation); + Memory::Free(Storage.HeapAllocation()); break; default: check_no_entry(); } @@ -411,32 +457,32 @@ private: if (LHS.IsValid() == false) return partial_ordering::equivalent; return LHS.GetTypeInfoImpl().SynthThreeWayCompareImpl(LHS.GetAllocation(), RHS.GetAllocation());; } - + }; -template -constexpr bool operator==(const TAny& LHS, const T& RHS) +template +constexpr bool operator==(const TAny& LHS, const T& RHS) { return LHS.template HoldsAlternative() ? LHS.template GetValue() == RHS : false; } -template -constexpr bool operator==(const TAny& LHS, FInvalid) +template +constexpr bool operator==(const TAny& LHS, FInvalid) { return !LHS.IsValid(); } NAMESPACE_PRIVATE_BEGIN -template struct TIsTAny : FFalse { }; -template struct TIsTAny> : FTrue { }; +template struct TIsTAny : FFalse { }; +template struct TIsTAny> : FTrue { }; NAMESPACE_PRIVATE_END template concept CTAny = NAMESPACE_PRIVATE::TIsTAny::Value; -using FAny = TAny; +using FAny = TAny<>; static_assert(sizeof(FAny) == 64, "The byte size of FAny is unexpected"); diff --git a/Redcraft.Utility/Source/Public/Templates/Function.h b/Redcraft.Utility/Source/Public/Templates/Function.h index 91319ba..1d41d2e 100644 --- a/Redcraft.Utility/Source/Public/Templates/Function.h +++ b/Redcraft.Utility/Source/Public/Templates/Function.h @@ -9,23 +9,17 @@ #include "TypeTraits/TypeTraits.h" #include "Miscellaneous/AssertionMacros.h" -// NOTE: Disable alignment limit warning -#pragma warning(disable : 4359) - NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) -inline constexpr size_t FUNCTION_DEFAULT_INLINE_SIZE = ANY_DEFAULT_INLINE_SIZE - sizeof(uintptr); -inline constexpr size_t FUNCTION_DEFAULT_INLINE_ALIGNMENT = ANY_DEFAULT_INLINE_ALIGNMENT; - template requires CFunction struct TFunctionRef; -template requires CFunction && (Memory::IsValidAlignment(InlineAlignment)) +template requires CFunction struct TFunction; -template requires CFunction && (Memory::IsValidAlignment(InlineAlignment)) +template requires CFunction struct TUniqueFunction; NAMESPACE_PRIVATE_BEGIN @@ -33,11 +27,11 @@ NAMESPACE_PRIVATE_BEGIN template struct TIsTFunctionRef : FFalse { }; template struct TIsTFunctionRef> : FTrue { }; -template struct TIsTFunction : FFalse { }; -template struct TIsTFunction> : FTrue { }; +template struct TIsTFunction : FFalse { }; +template struct TIsTFunction> : FTrue { }; -template struct TIsTUniqueFunction : FFalse { }; -template struct TIsTUniqueFunction> : FTrue { }; +template struct TIsTUniqueFunction : FFalse { }; +template struct TIsTUniqueFunction> : FTrue { }; NAMESPACE_PRIVATE_END @@ -86,16 +80,47 @@ template struct TFunctionInfo struct TFunctionInfo { using Fn = Ret(Types...); using CVRef = const int&; }; template struct TFunctionInfo { using Fn = Ret(Types...); using CVRef = const int&&; }; -template struct TFunctionImpl; +template +struct alignas(16) FFunctionStorage +{ + //~ Begin CAnyStorage Interface + inline static constexpr size_t InlineSize = 64 - sizeof(uintptr) - sizeof(CallableType); + inline static constexpr size_t InlineAlignment = 16; + constexpr void* InlineAllocation() { return &InlineAllocationImpl; } + constexpr const void* InlineAllocation() const { return &InlineAllocationImpl; } + constexpr void*& HeapAllocation() { return HeapAllocationImpl; } + constexpr void* HeapAllocation() const { return HeapAllocationImpl; } + constexpr uintptr& TypeInfo() { return TypeInfoImpl; } + constexpr uintptr TypeInfo() const { return TypeInfoImpl; } + constexpr void CopyCustom(const FFunctionStorage& InValue) { Callable = InValue.Callable; } + constexpr void MoveCustom( FFunctionStorage&& InValue) { Callable = InValue.Callable; } + //~ End CAnyStorage Interface -template -struct alignas(InlineAlignment) TFunctionImpl + union + { + uint8 InlineAllocationImpl[InlineSize]; + void* HeapAllocationImpl; + }; + + uintptr TypeInfoImpl; + + CallableType Callable; + + template + friend struct TAny; + +}; + +template struct TFunctionImpl; + +template +struct TFunctionImpl { public: using ResultType = Ret; using ArgumentType = TTuple; - + TFunctionImpl() = default; TFunctionImpl(const TFunctionImpl&) = default; TFunctionImpl(TFunctionImpl&& InValue) = default; @@ -110,8 +135,8 @@ public: FORCEINLINE ResultType operator()(Types... Args) const& requires (CSameAs) { return CallImpl(Forward(Args)...); } FORCEINLINE ResultType operator()(Types... Args) const&& requires (CSameAs) { return CallImpl(Forward(Args)...); } - constexpr bool IsValid() const { return Callable != nullptr; } - constexpr explicit operator bool() const { return Callable != nullptr; } + constexpr bool IsValid() const { return GetCallableImpl() != nullptr; } + constexpr explicit operator bool() const { return GetCallableImpl() != nullptr; } FORCEINLINE const type_info& TargetType() const requires (!bIsRef) { return IsValid() ? Storage.GetTypeInfo() : typeid(void); }; @@ -140,30 +165,49 @@ public: return; } - Swap(Callable, InValue.Callable); Swap(Storage, InValue.Storage); } private: - using StorageType = TConditional*, TAny>; - using StorageRef = TConditional*, TCopyCVRef&>; + using StoragePtrType = TCopyConst*; + using CallableType = ResultType(*)(StoragePtrType, Types&&...); - using CallFunc = ResultType(*)(StorageRef, Types&&...); + struct FunctionRefStorage + { + StoragePtrType Ptr; + CallableType Callable; + }; + + using FunctionStorage = TAny>; + using StorageType = TConditional; StorageType Storage; - CallFunc Callable; + + FORCEINLINE CallableType& GetCallableImpl() + { + if constexpr (bIsRef) return Storage.Callable; + else return Storage.GetCustomStorage().Callable; + } + + FORCEINLINE CallableType GetCallableImpl() const + { + if constexpr (bIsRef) return Storage.Callable; + else return Storage.GetCustomStorage().Callable; + } FORCEINLINE ResultType CallImpl(Types&&... Args) { checkf(IsValid(), TEXT("Attempting to call an unbound TFunction!")); - return Callable(Storage, Forward(Args)...); + if constexpr (bIsRef) return GetCallableImpl()(Storage.Ptr, Forward(Args)...); + else return GetCallableImpl()(&Storage, Forward(Args)...); } FORCEINLINE ResultType CallImpl(Types&&... Args) const { checkf(IsValid(), TEXT("Attempting to call an unbound TFunction!")); - return Callable(Storage, Forward(Args)...); + if constexpr (bIsRef) return GetCallableImpl()(Storage.Ptr, Forward(Args)...); + else return GetCallableImpl()(&Storage, Forward(Args)...); } protected: @@ -171,23 +215,23 @@ protected: template FORCEINLINE void EmplaceImpl(ArgTypes&&... Args) { - using CallableType = TCopyConst, DecayedType>; + using FuncType = TCopyConst, DecayedType>; - if constexpr (bIsRef) Storage = ((reinterpret_cast(AddressOf(Args))), ...); + if constexpr (bIsRef) Storage.Ptr = (AddressOf(Args), ...); else Storage.template Emplace(Forward(Args)...); - Callable = [](StorageRef Storage, Types&&... Args) -> ResultType + GetCallableImpl() = [](StoragePtrType Storage, Types&&... Args) -> ResultType { using InvokeType = TConditional< CReference, - TCopyCVRef, - TCopyCVRef& + TCopyCVRef, + TCopyCVRef& >; - const auto GetFunc = [&Storage]() -> InvokeType + const auto GetFunc = [Storage]() -> InvokeType { - if constexpr (!bIsRef) return Storage.template GetValue(); - else return static_cast(*reinterpret_cast(Storage)); + if constexpr (!bIsRef) return static_cast*>(Storage)->template GetValue(); + else return static_cast(*reinterpret_cast(Storage)); }; return InvokeResult(GetFunc(), Forward(Args)...); @@ -196,11 +240,7 @@ protected: FORCEINLINE void AssignImpl(const TFunctionImpl& InValue) { - if (InValue.IsValid()) - { - Callable = InValue.Callable; - Storage = InValue.Storage; - } + if (InValue.IsValid()) Storage = InValue.Storage; else ResetImpl(); } @@ -208,14 +248,13 @@ protected: { if (InValue.IsValid()) { - Callable = InValue.Callable; Storage = MoveTemp(InValue.Storage); InValue.ResetImpl(); } else ResetImpl(); } - constexpr void ResetImpl() { Callable = nullptr; } + constexpr void ResetImpl() { GetCallableImpl() = nullptr; } }; @@ -226,8 +265,6 @@ struct TFunctionRef : public NAMESPACE_PRIVATE::TFunctionImpl< typename NAMESPACE_PRIVATE::TFunctionInfo::Fn, typename NAMESPACE_PRIVATE::TFunctionInfo::CVRef, - FUNCTION_DEFAULT_INLINE_SIZE, - FUNCTION_DEFAULT_INLINE_ALIGNMENT, true> { private: @@ -235,8 +272,6 @@ private: using Super = NAMESPACE_PRIVATE::TFunctionImpl< typename NAMESPACE_PRIVATE::TFunctionInfo::Fn, typename NAMESPACE_PRIVATE::TFunctionInfo::CVRef, - FUNCTION_DEFAULT_INLINE_SIZE, - FUNCTION_DEFAULT_INLINE_ALIGNMENT, true>; public: @@ -263,14 +298,11 @@ public: }; -template - requires CFunction && (Memory::IsValidAlignment(InlineAlignment)) +template requires CFunction struct TFunction : public NAMESPACE_PRIVATE::TFunctionImpl< typename NAMESPACE_PRIVATE::TFunctionInfo::Fn, typename NAMESPACE_PRIVATE::TFunctionInfo::CVRef, - InlineSize, - InlineAlignment, false> { private: @@ -278,8 +310,6 @@ private: using Super = NAMESPACE_PRIVATE::TFunctionImpl< typename NAMESPACE_PRIVATE::TFunctionInfo::Fn, typename NAMESPACE_PRIVATE::TFunctionInfo::CVRef, - InlineSize, - InlineAlignment, false>; public: @@ -349,14 +379,11 @@ public: }; -template - requires CFunction && (Memory::IsValidAlignment(InlineAlignment)) +template requires CFunction struct TUniqueFunction : public NAMESPACE_PRIVATE::TFunctionImpl< typename NAMESPACE_PRIVATE::TFunctionInfo::Fn, typename NAMESPACE_PRIVATE::TFunctionInfo::CVRef, - InlineSize, - InlineAlignment, false> { private: @@ -364,8 +391,6 @@ private: using Super = NAMESPACE_PRIVATE::TFunctionImpl< typename NAMESPACE_PRIVATE::TFunctionInfo::Fn, typename NAMESPACE_PRIVATE::TFunctionInfo::CVRef, - InlineSize, - InlineAlignment, false>; public: @@ -383,23 +408,23 @@ public: return *this; } - FORCEINLINE TUniqueFunction(const TFunction& InValue) + FORCEINLINE TUniqueFunction(const TFunction& InValue) : Super(*reinterpret_cast(&InValue)) { } - FORCEINLINE TUniqueFunction(TFunction&& InValue) + FORCEINLINE TUniqueFunction(TFunction&& InValue) : Super(MoveTemp(*reinterpret_cast(&InValue))) { InValue.Reset(); } - FORCEINLINE TUniqueFunction& operator=(const TFunction& InValue) + FORCEINLINE TUniqueFunction& operator=(const TFunction& InValue) { Super::AssignImpl(*reinterpret_cast(&InValue)); return *this; } - FORCEINLINE TUniqueFunction& operator=(TFunction&& InValue) + FORCEINLINE TUniqueFunction& operator=(TFunction&& InValue) { Super::AssignImpl(MoveTemp(*reinterpret_cast(&InValue))); return *this;