refactor(templates): TFunction replaces using type aliases with derived classes
This commit is contained in:
		| @@ -1158,6 +1158,30 @@ void TestFunction() | |||||||
| 		TUniqueFunction<void()> UniqueG; UniqueG = MoveTemp(UniqueA); | 		TUniqueFunction<void()> UniqueG; UniqueG = MoveTemp(UniqueA); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	{ | ||||||
|  | 		struct FFunctor | ||||||
|  | 		{ | ||||||
|  | 			int32 A; | ||||||
|  | 			FFunctor(int32 InA) : A(InA) { } | ||||||
|  | 			int32 operator()() const { return A; } | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		FFunctor Functor(0xCC); | ||||||
|  |  | ||||||
|  | //		TFunctionRef<void()>       RefA; | ||||||
|  | 		TFunction<void()>       ObjectA; | ||||||
|  | 		TUniqueFunction<void()> UniqueA; | ||||||
|  |  | ||||||
|  | //		   RefA = Functor; | ||||||
|  | 		ObjectA = Functor; | ||||||
|  | 		UniqueA = Functor; | ||||||
|  |  | ||||||
|  | //		   RefA.Emplace<FFunctor>(0xCC); | ||||||
|  | 		ObjectA.Emplace<FFunctor>(0xCC); | ||||||
|  | 		UniqueA.Emplace<FFunctor>(0xCC); | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	{ | 	{ | ||||||
| 		TFunction<void(int32)> Display = PrintNum; | 		TFunction<void(int32)> Display = PrintNum; | ||||||
| 		Display(-9); | 		Display(-9); | ||||||
|   | |||||||
| @@ -6,10 +6,7 @@ | |||||||
| #include "Templates/Invoke.h" | #include "Templates/Invoke.h" | ||||||
| #include "Memory/Alignment.h" | #include "Memory/Alignment.h" | ||||||
| #include "Templates/Utility.h" | #include "Templates/Utility.h" | ||||||
| #include "Templates/TypeHash.h" |  | ||||||
| #include "TypeTraits/TypeTraits.h" | #include "TypeTraits/TypeTraits.h" | ||||||
| #include "Miscellaneous/TypeInfo.h" |  | ||||||
| #include "Concepts/BooleanTestable.h" |  | ||||||
| #include "Miscellaneous/AssertionMacros.h" | #include "Miscellaneous/AssertionMacros.h" | ||||||
|  |  | ||||||
| // NOTE: Disable alignment limit warning | // NOTE: Disable alignment limit warning | ||||||
| @@ -19,46 +16,33 @@ NAMESPACE_REDCRAFT_BEGIN | |||||||
| NAMESPACE_MODULE_BEGIN(Redcraft) | NAMESPACE_MODULE_BEGIN(Redcraft) | ||||||
| NAMESPACE_MODULE_BEGIN(Utility) | NAMESPACE_MODULE_BEGIN(Utility) | ||||||
|  |  | ||||||
| NAMESPACE_PRIVATE_BEGIN | 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; | ||||||
|  |  | ||||||
| enum class EFunctionType | template <typename F> requires TIsFunction<F>::Value | ||||||
| { | struct TFunctionRef; | ||||||
| 	Reference, |  | ||||||
| 	Object, |  | ||||||
| 	Unique, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| enum class EFunctionSpecifiers | template <typename F, size_t InlineSize, size_t InlineAlignment> requires TIsFunction<F>::Value && (Memory::IsValidAlignment(InlineAlignment)) | ||||||
| { | struct TFunction; | ||||||
| 	None, |  | ||||||
| 	LValue, |  | ||||||
| 	RValue, |  | ||||||
| 	Const, |  | ||||||
| 	ConstLValue, |  | ||||||
| 	ConstRValue, |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| template <typename F, size_t InlineSize, size_t InlineAlignment, EFunctionSpecifiers Specifiers, EFunctionType FunctionType> requires (Memory::IsValidAlignment(InlineAlignment)) | template <typename F, size_t InlineSize, size_t InlineAlignment> requires TIsFunction<F>::Value && (Memory::IsValidAlignment(InlineAlignment)) | ||||||
| struct TFunctionImpl; | struct TUniqueFunction; | ||||||
|  |  | ||||||
| template <typename T>                                                             struct TIsTFunctionImpl                               : FFalse { }; |  | ||||||
| template <typename F, size_t I, size_t J, EFunctionSpecifiers S, EFunctionType E> struct TIsTFunctionImpl<TFunctionImpl<F, I, J, S, E>> : FTrue  { }; |  | ||||||
|  |  | ||||||
| template <typename T> struct TIsTFunctionRef                  : FFalse { }; | template <typename T> struct TIsTFunctionRef                  : FFalse { }; | ||||||
| template <typename F, size_t I, size_t J, EFunctionSpecifiers S> struct TIsTFunctionRef<TFunctionImpl<F, I, J, S, EFunctionType::Reference>> : FTrue  { }; | template <typename F> struct TIsTFunctionRef<TFunctionRef<F>> : FTrue  { }; | ||||||
|  |  | ||||||
| template <typename T>                     struct TIsTFunction                     : FFalse { }; | template <typename T>                     struct TIsTFunction                     : FFalse { }; | ||||||
| template <typename F, size_t I, size_t J, EFunctionSpecifiers S> struct TIsTFunction<TFunctionImpl<F, I, J, S, EFunctionType::Object>> : FTrue  { }; | template <typename F, size_t I, size_t J> struct TIsTFunction<TFunction<F, I, J>> : FTrue  { }; | ||||||
|  |  | ||||||
| template <typename T>                     struct TIsTUniqueFunction                           : FFalse { }; | template <typename T>                     struct TIsTUniqueFunction                           : FFalse { }; | ||||||
| template <typename F, size_t I, size_t J, EFunctionSpecifiers S> struct TIsTUniqueFunction<TFunctionImpl<F, I, J, S, EFunctionType::Unique>> : FTrue  { }; | template <typename F, size_t I, size_t J> struct TIsTUniqueFunction<TUniqueFunction<F, I, J>> : FTrue  { }; | ||||||
|  |  | ||||||
|  | NAMESPACE_PRIVATE_BEGIN | ||||||
|  |  | ||||||
| struct FFunctionIsBound |  | ||||||
| { |  | ||||||
| template <typename T> | template <typename T> | ||||||
| 	static constexpr bool F(const T& Func) | constexpr bool FunctionIsBound(const T& Func) | ||||||
| { | { | ||||||
| 		if constexpr (TIsPointer<T>::Value || TIsMemberPointer<T>::Value || TIsTFunctionImpl<T>::Value) | 	if constexpr (TIsPointer<T>::Value || TIsMemberPointer<T>::Value || TIsTFunctionRef<T>::Value || TIsTFunction<T>::Value || TIsTUniqueFunction<T>::Value) | ||||||
| 	{ | 	{ | ||||||
| 		return !!Func; | 		return !!Func; | ||||||
| 	} | 	} | ||||||
| @@ -67,249 +51,101 @@ struct FFunctionIsBound | |||||||
| 		return true; | 		return true; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| }; |  | ||||||
|  |  | ||||||
| template <EFunctionSpecifiers Specifiers, typename R, typename F, typename... Types> | template <typename Signature, typename F> struct TIsInvocableSignature : FFalse { }; | ||||||
| struct TIsInvocableResultWithSpecifiers : FFalse { }; |  | ||||||
|  |  | ||||||
| template <typename R, typename F, typename... Types> | template <typename Ret, typename... Types, typename F> | ||||||
| struct TIsInvocableResultWithSpecifiers<EFunctionSpecifiers::None, R, F, Types...> | struct TIsInvocableSignature<Ret(Types...), F> | ||||||
| 	: TBoolConstant<TIsInvocableResult<R, F, Types...>::Value && TIsInvocableResult<R, F&, Types...>::Value> | 	: TBoolConstant<TIsInvocableResult<Ret, F, Types...>::Value && TIsInvocableResult<Ret, F&, Types...>::Value> | ||||||
| { }; | { }; | ||||||
|  |  | ||||||
| template <typename R, typename F, typename... Types> | template <typename Ret, typename... Types, typename F> struct TIsInvocableSignature<Ret(Types...) & , F> : TIsInvocableResult<Ret, F&, Types...> { }; | ||||||
| struct TIsInvocableResultWithSpecifiers<EFunctionSpecifiers::LValue, R, F, Types...> : TIsInvocableResult<R, F&, Types...> { }; | template <typename Ret, typename... Types, typename F> struct TIsInvocableSignature<Ret(Types...) &&, F> : TIsInvocableResult<Ret, F , Types...> { }; | ||||||
|  |  | ||||||
| template <typename R, typename F, typename... Types> | template <typename Ret, typename... Types, typename F> | ||||||
| struct TIsInvocableResultWithSpecifiers<EFunctionSpecifiers::RValue, R, F, Types...> : TIsInvocableResult<R, F, Types...> { }; | struct TIsInvocableSignature<Ret(Types...) const, F> | ||||||
|  | 	: TBoolConstant<TIsInvocableResult<Ret, const F, Types...>::Value && TIsInvocableResult<Ret, const F&, Types...>::Value> | ||||||
| template <typename R, typename F, typename... Types> |  | ||||||
| struct TIsInvocableResultWithSpecifiers<EFunctionSpecifiers::Const, R, F, Types...> |  | ||||||
| 	: TBoolConstant<TIsInvocableResult<R, const F, Types...>::Value && TIsInvocableResult<R, const F&, Types...>::Value> |  | ||||||
| { }; | { }; | ||||||
|  |  | ||||||
| template <typename R, typename F, typename... Types> | template <typename Ret, typename... Types, typename F> struct TIsInvocableSignature<Ret(Types...) const& , F> : TIsInvocableResult<Ret, const F&, Types...> { }; | ||||||
| struct TIsInvocableResultWithSpecifiers<EFunctionSpecifiers::ConstLValue, R, F, Types...> : TIsInvocableResult<R, const F&, Types...> { }; | template <typename Ret, typename... Types, typename F> struct TIsInvocableSignature<Ret(Types...) const&&, F> : TIsInvocableResult<Ret, const F , Types...> { }; | ||||||
|  |  | ||||||
| template <typename R, typename F, typename... Types> | template <typename F>                      struct TFunctionInfo; | ||||||
| struct TIsInvocableResultWithSpecifiers<EFunctionSpecifiers::ConstRValue, R, F, Types...> : TIsInvocableResult<R, const F, Types...> { }; | template <typename Ret, typename... Types> struct TFunctionInfo<Ret(Types...)        > { using Fn = Ret(Types...); using CVRef =       int;   }; | ||||||
|  | template <typename Ret, typename... Types> struct TFunctionInfo<Ret(Types...) &      > { using Fn = Ret(Types...); using CVRef =       int&;  }; | ||||||
|  | template <typename Ret, typename... Types> struct TFunctionInfo<Ret(Types...) &&     > { using Fn = Ret(Types...); using CVRef =       int&&; }; | ||||||
|  | template <typename Ret, typename... Types> struct TFunctionInfo<Ret(Types...) const  > { using Fn = Ret(Types...); using CVRef = const int;   }; | ||||||
|  | template <typename Ret, typename... Types> struct TFunctionInfo<Ret(Types...) const& > { using Fn = Ret(Types...); using CVRef = const int&;  }; | ||||||
|  | template <typename Ret, typename... Types> struct TFunctionInfo<Ret(Types...) const&&> { using Fn = Ret(Types...); using CVRef = const int&&; }; | ||||||
|  |  | ||||||
| template <typename T, EFunctionSpecifiers Specifiers> struct TFunctionCallConst; | template <typename F, typename CVRef, size_t InlineSize, size_t InlineAlignment, bool bIsRef> struct TFunctionImpl; | ||||||
| template <typename T> struct TFunctionCallConst<T, EFunctionSpecifiers::None>        { using Type =       T; }; |  | ||||||
| template <typename T> struct TFunctionCallConst<T, EFunctionSpecifiers::LValue>      { using Type =       T; }; |  | ||||||
| template <typename T> struct TFunctionCallConst<T, EFunctionSpecifiers::RValue>      { using Type =       T; }; |  | ||||||
| template <typename T> struct TFunctionCallConst<T, EFunctionSpecifiers::Const>       { using Type = const T; }; |  | ||||||
| template <typename T> struct TFunctionCallConst<T, EFunctionSpecifiers::ConstLValue> { using Type = const T; }; |  | ||||||
| template <typename T> struct TFunctionCallConst<T, EFunctionSpecifiers::ConstRValue> { using Type = const T; }; |  | ||||||
|  |  | ||||||
| template <typename T, EFunctionSpecifiers Specifiers> struct TFunctionCallConstRef; | template <typename Ret, typename... Types, typename CVRef, size_t InlineSize, size_t InlineAlignment, bool bIsRef> | ||||||
| template <typename T> struct TFunctionCallConstRef<T, EFunctionSpecifiers::None>        { using Type =       T& ; }; | struct alignas(InlineAlignment) TFunctionImpl<Ret(Types...), CVRef, InlineSize, InlineAlignment, bIsRef> | ||||||
| template <typename T> struct TFunctionCallConstRef<T, EFunctionSpecifiers::LValue>      { using Type =       T& ; }; |  | ||||||
| template <typename T> struct TFunctionCallConstRef<T, EFunctionSpecifiers::RValue>      { using Type =       T&&; }; |  | ||||||
| template <typename T> struct TFunctionCallConstRef<T, EFunctionSpecifiers::Const>       { using Type = const T& ; }; |  | ||||||
| template <typename T> struct TFunctionCallConstRef<T, EFunctionSpecifiers::ConstLValue> { using Type = const T& ; }; |  | ||||||
| template <typename T> struct TFunctionCallConstRef<T, EFunctionSpecifiers::ConstRValue> { using Type = const T&&; }; |  | ||||||
|  |  | ||||||
| template <typename R, typename... Types, size_t InlineSize, size_t InlineAlignment, EFunctionSpecifiers Specifiers, EFunctionType FunctionType> |  | ||||||
| struct alignas(InlineAlignment) TFunctionImpl<R(Types...), InlineSize, InlineAlignment, Specifiers, FunctionType> |  | ||||||
| { | { | ||||||
| public: | public: | ||||||
|  |  | ||||||
| 	using ResultType = R; | 	using ResultType = Ret; | ||||||
| 	using ArgumentType = TTuple<Types...>; | 	using ArgumentType = TTuple<Types...>; | ||||||
|  |  | ||||||
| 	constexpr TFunctionImpl(nullptr_t = nullptr) requires (FunctionType != EFunctionType::Reference) : Callable(nullptr) { } | 	TFunctionImpl() = default; | ||||||
|  | 	TFunctionImpl(const TFunctionImpl&) = default; | ||||||
| 	TFunctionImpl(const TFunctionImpl& InValue) requires (FunctionType != EFunctionType::Unique) | 	TFunctionImpl(TFunctionImpl&& InValue) = default; | ||||||
| 		: Callable(InValue.Callable), Storage(InValue.Storage) | 	TFunctionImpl& operator=(const TFunctionImpl&) = default; | ||||||
| 	{ } | 	TFunctionImpl& operator=(TFunctionImpl&&) = default; | ||||||
|  |  | ||||||
| 	TFunctionImpl(TFunctionImpl&& InValue) |  | ||||||
| 		: Callable(InValue.Callable), Storage(MoveTemp(InValue.Storage)) |  | ||||||
| 	{ if constexpr (FunctionType != EFunctionType::Reference) InValue.Reset(); } |  | ||||||
| 	 |  | ||||||
| 	template <typename T> requires (!TIsTFunctionImpl<typename TDecay<T>::Type>::Value) && (!TIsTInPlaceType<typename TDecay<T>::Type>::Value) |  | ||||||
| 		&& TIsInvocableResultWithSpecifiers<Specifiers, ResultType, typename TDecay<T>::Type, Types...>::Value |  | ||||||
| 		&& (FunctionType == EFunctionType::Reference || TIsConstructible<typename TDecay<T>::Type, T&&>::Value) |  | ||||||
| 		&& ((FunctionType == EFunctionType::Object && TIsCopyConstructible<typename TDecay<T>::Type>::Value) |  | ||||||
| 			|| (FunctionType == EFunctionType::Unique && TIsMoveConstructible<typename TDecay<T>::Type>::Value) |  | ||||||
| 			|| FunctionType == EFunctionType::Reference) |  | ||||||
| 	FORCEINLINE TFunctionImpl(T&& InValue) |  | ||||||
| 	{ |  | ||||||
| 		using DecayedType = typename TDecay<T>::Type; |  | ||||||
|  |  | ||||||
| 		if constexpr (FunctionType == EFunctionType::Reference) |  | ||||||
| 		{ |  | ||||||
| 			checkf(FFunctionIsBound::F(InValue), TEXT("Cannot bind a null/unbound callable to a TFunctionRef")); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if (!FFunctionIsBound::F(InValue)) Callable = nullptr; |  | ||||||
| 		else EmplaceImpl<DecayedType>(Forward<T>(InValue)); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	template <typename T, typename... ArgTypes> requires (FunctionType != EFunctionType::Reference) |  | ||||||
| 		&& TIsInvocableResultWithSpecifiers<Specifiers, ResultType, typename TDecay<T>::Type, Types...>::Value && TIsConstructible<typename TDecay<T>::Type, ArgTypes...>::Value |  | ||||||
| 		&& ((FunctionType == EFunctionType::Object && TIsCopyConstructible<typename TDecay<T>::Type>::Value) |  | ||||||
| 			|| (FunctionType == EFunctionType::Unique && TIsMoveConstructible<typename TDecay<T>::Type>::Value)) |  | ||||||
| 	FORCEINLINE TFunctionImpl(TInPlaceType<T>, ArgTypes&&... Args) |  | ||||||
| 	{ |  | ||||||
| 		using DecayedType = typename TDecay<T>::Type; |  | ||||||
| 		EmplaceImpl<DecayedType>(Forward<ArgTypes>(Args)...); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// Construct TFunctionRef from TFunction or TFunctionUnique |  | ||||||
| 	template <size_t OtherInlineSize, size_t OtherInlineAlignment, EFunctionType OtherFunctionType> |  | ||||||
| 		requires (FunctionType == EFunctionType::Reference) && (OtherFunctionType != EFunctionType::Reference) && (TIsSame<typename TFunctionCallConst<void, Specifiers>::Type, void>::Value) |  | ||||||
| 	FORCEINLINE TFunctionImpl(TFunctionImpl<R(Types...), OtherInlineSize, OtherInlineAlignment, Specifiers, OtherFunctionType>& InValue) |  | ||||||
| 	{ |  | ||||||
| 		checkf(FFunctionIsBound::F(InValue), TEXT("Cannot bind a null/unbound callable to a TFunctionRef")); |  | ||||||
| 		EmplaceImpl<TFunctionImpl<R(Types...), OtherInlineSize, OtherInlineAlignment, Specifiers, OtherFunctionType>>(InValue); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// Construct TFunctionRef from TFunction or TFunctionUnique |  | ||||||
| 	template <size_t OtherInlineSize, size_t OtherInlineAlignment, EFunctionType OtherFunctionType> |  | ||||||
| 		requires (FunctionType == EFunctionType::Reference) && (OtherFunctionType != EFunctionType::Reference) && (TIsSame<typename TFunctionCallConst<void, Specifiers>::Type, const void>::Value) |  | ||||||
| 	FORCEINLINE TFunctionImpl(const TFunctionImpl<R(Types...), OtherInlineSize, OtherInlineAlignment, Specifiers, OtherFunctionType>& InValue) |  | ||||||
| 	{ |  | ||||||
| 		checkf(FFunctionIsBound::F(InValue), TEXT("Cannot bind a null/unbound callable to a TFunctionRef")); |  | ||||||
| 		EmplaceImpl<TFunctionImpl<R(Types...), OtherInlineSize, OtherInlineAlignment, Specifiers, OtherFunctionType>>(InValue); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	FORCEINLINE TFunctionImpl(const TFunctionImpl<R(Types...), InlineSize, InlineAlignment, Specifiers, EFunctionType::Object>& InValue) requires (FunctionType == EFunctionType::Unique) |  | ||||||
| 		: Callable((*reinterpret_cast<const TFunctionImpl*>(&InValue)).Callable), Storage((*reinterpret_cast<const TFunctionImpl*>(&InValue)).Storage) |  | ||||||
| 	{ } |  | ||||||
|  |  | ||||||
| 	FORCEINLINE TFunctionImpl(TFunctionImpl<R(Types...), InlineSize, InlineAlignment, Specifiers, EFunctionType::Object>&& InValue) requires (FunctionType == EFunctionType::Unique) |  | ||||||
| 		: Callable((*reinterpret_cast<TFunctionImpl*>(&InValue)).Callable), Storage(MoveTemp((*reinterpret_cast<TFunctionImpl*>(&InValue)).Storage)) |  | ||||||
| 	{ InValue.Reset(); } |  | ||||||
|  |  | ||||||
| 	~TFunctionImpl() = default; | 	~TFunctionImpl() = default; | ||||||
|  |  | ||||||
| 	FORCEINLINE TFunctionImpl& operator=(const TFunctionImpl& InValue) requires (FunctionType == EFunctionType::Object) | 	FORCEINLINE ResultType operator()(Types... Args)         requires (TIsSame<CVRef,       int  >::Value) { return CallImpl(Forward<Types>(Args)...); } | ||||||
| 	{ | 	FORCEINLINE ResultType operator()(Types... Args) &       requires (TIsSame<CVRef,       int& >::Value) { return CallImpl(Forward<Types>(Args)...); } | ||||||
| 		AssignImpl(InValue); | 	FORCEINLINE ResultType operator()(Types... Args) &&      requires (TIsSame<CVRef,       int&&>::Value) { return CallImpl(Forward<Types>(Args)...); } | ||||||
| 		return *this; | 	FORCEINLINE ResultType operator()(Types... Args) const   requires (TIsSame<CVRef, const int  >::Value) { return CallImpl(Forward<Types>(Args)...); } | ||||||
| 	} | 	FORCEINLINE ResultType operator()(Types... Args) const&  requires (TIsSame<CVRef, const int& >::Value) { return CallImpl(Forward<Types>(Args)...); } | ||||||
|  | 	FORCEINLINE ResultType operator()(Types... Args) const&& requires (TIsSame<CVRef, const int&&>::Value) { return CallImpl(Forward<Types>(Args)...); } | ||||||
| 	FORCEINLINE TFunctionImpl& operator=(TFunctionImpl&& InValue) requires (FunctionType != EFunctionType::Reference) |  | ||||||
| 	{ |  | ||||||
| 		if (&InValue == this) return *this; |  | ||||||
| 		AssignImpl(MoveTemp(InValue)); |  | ||||||
| 		return *this; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	FORCEINLINE TFunctionImpl& operator=(const TFunctionImpl<R(Types...), InlineSize, InlineAlignment, Specifiers, EFunctionType::Object>& InValue) requires (FunctionType == EFunctionType::Unique) |  | ||||||
| 	{ |  | ||||||
| 		AssignImpl(*reinterpret_cast<const TFunctionImpl*>(&InValue)); |  | ||||||
| 		return *this; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	FORCEINLINE TFunctionImpl& operator=(TFunctionImpl<R(Types...), InlineSize, InlineAlignment, Specifiers, EFunctionType::Object>&& InValue) requires (FunctionType == EFunctionType::Unique) |  | ||||||
| 	{ |  | ||||||
| 		AssignImpl(MoveTemp(*reinterpret_cast<TFunctionImpl*>(&InValue))); |  | ||||||
| 		return *this; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	constexpr TFunctionImpl& operator=(nullptr_t) requires (FunctionType != EFunctionType::Reference) { Reset(); return *this; } |  | ||||||
|  |  | ||||||
| 	template <typename T> requires (FunctionType != EFunctionType::Reference) && (!TIsTFunctionImpl<typename TDecay<T>::Type>::Value) |  | ||||||
| 		&& TIsInvocableResultWithSpecifiers<Specifiers, ResultType, typename TDecay<T>::Type, Types...>::Value |  | ||||||
| 		&& TIsConstructible<typename TDecay<T>::Type, T&&>::Value |  | ||||||
| 		&& ((FunctionType == EFunctionType::Object && TIsCopyConstructible<typename TDecay<T>::Type>::Value) |  | ||||||
| 			|| (FunctionType == EFunctionType::Unique && TIsMoveConstructible<typename TDecay<T>::Type>::Value)) |  | ||||||
| 	FORCEINLINE TFunctionImpl& operator=(T&& InValue) |  | ||||||
| 	{ |  | ||||||
| 		using DecayedType = typename TDecay<T>::Type; |  | ||||||
|  |  | ||||||
| 		if (!FFunctionIsBound::F(InValue)) Reset(); |  | ||||||
| 		else EmplaceImpl<DecayedType>(Forward<T>(InValue)); |  | ||||||
|  |  | ||||||
| 		return *this; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	template <typename T, typename... ArgTypes> requires (FunctionType != EFunctionType::Reference) |  | ||||||
| 		&& TIsInvocableResultWithSpecifiers<Specifiers, ResultType, typename TDecay<T>::Type, Types...>::Value |  | ||||||
| 		&& TIsConstructible<typename TDecay<T>::Type, ArgTypes...>::Value |  | ||||||
| 		&& ((FunctionType == EFunctionType::Object && TIsCopyConstructible<typename TDecay<T>::Type>::Value) |  | ||||||
| 			|| (FunctionType == EFunctionType::Unique && TIsMoveConstructible<typename TDecay<T>::Type>::Value)) |  | ||||||
| 	FORCEINLINE typename TDecay<T>::Type& Emplace(ArgTypes&&... Args) |  | ||||||
| 	{ |  | ||||||
| 		using DecayedType = typename TDecay<T>::Type; |  | ||||||
| 		EmplaceImpl<DecayedType>(Forward<ArgTypes>(Args)...); |  | ||||||
| 		return Target<DecayedType>(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	FORCEINLINE ResultType operator()(Types... Args)         requires (Specifiers == EFunctionSpecifiers::None       ) { return CallImpl(Forward<Types>(Args)...); } |  | ||||||
| 	FORCEINLINE ResultType operator()(Types... Args) &       requires (Specifiers == EFunctionSpecifiers::LValue     ) { return CallImpl(Forward<Types>(Args)...); } |  | ||||||
| 	FORCEINLINE ResultType operator()(Types... Args) &&      requires (Specifiers == EFunctionSpecifiers::RValue     ) { return CallImpl(Forward<Types>(Args)...); } |  | ||||||
| 	FORCEINLINE ResultType operator()(Types... Args) const   requires (Specifiers == EFunctionSpecifiers::Const      ) { return CallImpl(Forward<Types>(Args)...); } |  | ||||||
| 	FORCEINLINE ResultType operator()(Types... Args) const&  requires (Specifiers == EFunctionSpecifiers::ConstLValue) { return CallImpl(Forward<Types>(Args)...); } |  | ||||||
| 	FORCEINLINE ResultType operator()(Types... Args) const&& requires (Specifiers == EFunctionSpecifiers::ConstRValue) { return CallImpl(Forward<Types>(Args)...); } |  | ||||||
|  |  | ||||||
| 	constexpr bool           IsValid() const { return Callable != nullptr; } | 	constexpr bool           IsValid() const { return Callable != nullptr; } | ||||||
| 	constexpr explicit operator bool() const { return Callable != nullptr; } | 	constexpr explicit operator bool() const { return Callable != nullptr; } | ||||||
|  |  | ||||||
| 	FORCEINLINE const FTypeInfo& TargetType() const requires (FunctionType != EFunctionType::Reference) { return IsValid() ? Storage.GetTypeInfo() : Typeid(void); }; | 	FORCEINLINE const type_info& TargetType() const requires (!bIsRef) { return IsValid() ? Storage.GetTypeInfo() : typeid(void); }; | ||||||
|  |  | ||||||
| 	template <typename T> FORCEINLINE       T&  Target() &       requires (FunctionType != EFunctionType::Reference) && TIsSame<T, typename TDecay<T>::Type>::Value && TIsObject<typename TDecay<T>::Type>::Value && (!TIsArray<typename TDecay<T>::Type>::Value) && TIsDestructible<typename TDecay<T>::Type>::Value { return static_cast<      StorageType& >(Storage).template GetValue<T>(); } | 	template <typename T> FORCEINLINE       T&  Target() &       requires (!bIsRef) && TIsSame<T, typename TDecay<T>::Type>::Value && TIsObject<typename TDecay<T>::Type>::Value && (!TIsArray<typename TDecay<T>::Type>::Value) && TIsDestructible<typename TDecay<T>::Type>::Value { return static_cast<      StorageType& >(Storage).template GetValue<T>(); } | ||||||
| 	template <typename T> FORCEINLINE       T&& Target() &&      requires (FunctionType != EFunctionType::Reference) && TIsSame<T, typename TDecay<T>::Type>::Value && TIsObject<typename TDecay<T>::Type>::Value && (!TIsArray<typename TDecay<T>::Type>::Value) && TIsDestructible<typename TDecay<T>::Type>::Value { return static_cast<      StorageType&&>(Storage).template GetValue<T>(); } | 	template <typename T> FORCEINLINE       T&& Target() &&      requires (!bIsRef) && TIsSame<T, typename TDecay<T>::Type>::Value && TIsObject<typename TDecay<T>::Type>::Value && (!TIsArray<typename TDecay<T>::Type>::Value) && TIsDestructible<typename TDecay<T>::Type>::Value { return static_cast<      StorageType&&>(Storage).template GetValue<T>(); } | ||||||
| 	template <typename T> FORCEINLINE const T&  Target() const&  requires (FunctionType != EFunctionType::Reference) && TIsSame<T, typename TDecay<T>::Type>::Value && TIsObject<typename TDecay<T>::Type>::Value && (!TIsArray<typename TDecay<T>::Type>::Value) && TIsDestructible<typename TDecay<T>::Type>::Value { return static_cast<const StorageType& >(Storage).template GetValue<T>(); } | 	template <typename T> FORCEINLINE const T&  Target() const&  requires (!bIsRef) && TIsSame<T, typename TDecay<T>::Type>::Value && TIsObject<typename TDecay<T>::Type>::Value && (!TIsArray<typename TDecay<T>::Type>::Value) && TIsDestructible<typename TDecay<T>::Type>::Value { return static_cast<const StorageType& >(Storage).template GetValue<T>(); } | ||||||
| 	template <typename T> FORCEINLINE const T&& Target() const&& requires (FunctionType != EFunctionType::Reference) && TIsSame<T, typename TDecay<T>::Type>::Value && TIsObject<typename TDecay<T>::Type>::Value && (!TIsArray<typename TDecay<T>::Type>::Value) && TIsDestructible<typename TDecay<T>::Type>::Value { return static_cast<const StorageType&&>(Storage).template GetValue<T>(); } | 	template <typename T> FORCEINLINE const T&& Target() const&& requires (!bIsRef) && TIsSame<T, typename TDecay<T>::Type>::Value && TIsObject<typename TDecay<T>::Type>::Value && (!TIsArray<typename TDecay<T>::Type>::Value) && TIsDestructible<typename TDecay<T>::Type>::Value { return static_cast<const StorageType&&>(Storage).template GetValue<T>(); } | ||||||
|  |  | ||||||
| 	constexpr void Reset() requires (FunctionType != EFunctionType::Reference) { Callable = nullptr; } | 	constexpr void Swap(TFunctionImpl& InValue) requires (!bIsRef) | ||||||
|  |  | ||||||
| 	constexpr void Swap(TFunctionImpl& InValue) requires (FunctionType != EFunctionType::Reference) |  | ||||||
| 	{ | 	{ | ||||||
|  | 		using NAMESPACE_REDCRAFT::Swap; | ||||||
|  |  | ||||||
| 		if (!IsValid() && !InValue.IsValid()) return; | 		if (!IsValid() && !InValue.IsValid()) return; | ||||||
|  |  | ||||||
| 		if (IsValid() && !InValue.IsValid()) | 		if (IsValid() && !InValue.IsValid()) | ||||||
| 		{ | 		{ | ||||||
| 			InValue = MoveTemp(*this); | 			InValue = MoveTemp(*this); | ||||||
| 			Reset(); | 			ResetImpl(); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (InValue.IsValid() && !IsValid()) | 		if (InValue.IsValid() && !IsValid()) | ||||||
| 		{ | 		{ | ||||||
| 			*this = MoveTemp(InValue); | 			*this = MoveTemp(InValue); | ||||||
| 			InValue.Reset(); | 			InValue.ResetImpl(); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		NAMESPACE_REDCRAFT::Swap(Callable, InValue.Callable); | 		Swap(Callable, InValue.Callable); | ||||||
| 		NAMESPACE_REDCRAFT::Swap(Storage, InValue.Storage); | 		Swap(Storage, InValue.Storage); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| private: | private: | ||||||
|  |  | ||||||
| 	using StorageType = typename TConditional<FunctionType == EFunctionType::Reference, typename TFunctionCallConst<void, Specifiers>::Type*, TAny<InlineSize, 1>>::Type; | 	using StorageType = typename TConditional<bIsRef, typename TCopyConst<CVRef, void>::Type*, TAny<InlineSize, 1>>::Type; | ||||||
| 	using StorageRef  = typename TConditional<FunctionType == EFunctionType::Reference, typename TFunctionCallConst<void, Specifiers>::Type*, typename TFunctionCallConstRef<StorageType, Specifiers>::Type&>::Type; | 	using StorageRef  = typename TConditional<bIsRef, typename TCopyConst<CVRef, void>::Type*, typename TCopyCVRef<CVRef, StorageType>::Type&>::Type; | ||||||
|  |  | ||||||
| 	using CallFunc = ResultType(*)(StorageRef, Types&&...); | 	using CallFunc = ResultType(*)(StorageRef, Types&&...); | ||||||
|  |  | ||||||
| 	StorageType Storage; | 	StorageType Storage; | ||||||
| 	CallFunc Callable; | 	CallFunc Callable; | ||||||
|  |  | ||||||
| 	template <typename DecayedType, typename... ArgTypes> |  | ||||||
| 	FORCEINLINE void EmplaceImpl(ArgTypes&&... Args) |  | ||||||
| 	{ |  | ||||||
| 		using CallableType = typename TFunctionCallConst<DecayedType, Specifiers>::Type; |  | ||||||
|  |  | ||||||
| 		if constexpr (FunctionType == EFunctionType::Reference) Storage = ((reinterpret_cast<StorageType>(&Args)), ...); |  | ||||||
| 		else Storage.template Emplace<DecayedType>(Forward<ArgTypes>(Args)...); |  | ||||||
|  |  | ||||||
| 		Callable = [](StorageRef Storage, Types&&... Args) -> ResultType |  | ||||||
| 		{ |  | ||||||
| 			const auto GetFunc = [&Storage]() -> decltype(auto) |  | ||||||
| 			{ |  | ||||||
| 				if constexpr (FunctionType == EFunctionType::Reference) return *reinterpret_cast<CallableType*>(Storage); |  | ||||||
| 				else return Storage.template GetValue<DecayedType>(); |  | ||||||
| 			}; |  | ||||||
|  |  | ||||||
| 			return InvokeResult<R>(Forward<typename TFunctionCallConstRef<CallableType, Specifiers>::Type>(GetFunc()), Forward<Types>(Args)...); |  | ||||||
| 		}; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	FORCEINLINE ResultType CallImpl(Types&&... Args) | 	FORCEINLINE ResultType CallImpl(Types&&... Args) | ||||||
| 	{ | 	{ | ||||||
| 		checkf(IsValid(), TEXT("Attempting to call an unbound TFunction!")); | 		checkf(IsValid(), TEXT("Attempting to call an unbound TFunction!")); | ||||||
| @@ -322,6 +158,34 @@ private: | |||||||
| 		return Callable(Storage, Forward<Types>(Args)...); | 		return Callable(Storage, Forward<Types>(Args)...); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  |  | ||||||
|  | 	template <typename DecayedType, typename... ArgTypes> | ||||||
|  | 	FORCEINLINE void EmplaceImpl(ArgTypes&&... Args) | ||||||
|  | 	{ | ||||||
|  | 		using CallableType = typename TCopyConst<typename TRemoveReference<CVRef>::Type, DecayedType>::Type; | ||||||
|  |  | ||||||
|  | 		if constexpr (bIsRef) Storage = ((reinterpret_cast<StorageType>(AddressOf(Args))), ...); | ||||||
|  | 		else Storage.template Emplace<DecayedType>(Forward<ArgTypes>(Args)...); | ||||||
|  |  | ||||||
|  | 		Callable = [](StorageRef Storage, Types&&... Args) -> ResultType | ||||||
|  | 		{ | ||||||
|  | 			using InvokeType = typename TConditional< | ||||||
|  | 				TIsReference<CVRef>::Value, | ||||||
|  | 				typename TCopyCVRef<CVRef, CallableType>::Type, | ||||||
|  | 				typename TCopyCVRef<CVRef, CallableType>::Type& | ||||||
|  | 			>::Type; | ||||||
|  |  | ||||||
|  | 			const auto GetFunc = [&Storage]() -> InvokeType | ||||||
|  | 			{ | ||||||
|  | 				if constexpr (!bIsRef) return Storage.template GetValue<DecayedType>(); | ||||||
|  | 				else return static_cast<InvokeType>(*reinterpret_cast<CallableType*>(Storage)); | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			return InvokeResult<ResultType>(GetFunc(), Forward<Types>(Args)...); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	FORCEINLINE void AssignImpl(const TFunctionImpl& InValue) | 	FORCEINLINE void AssignImpl(const TFunctionImpl& InValue) | ||||||
| 	{ | 	{ | ||||||
| 		if (InValue.IsValid()) | 		if (InValue.IsValid()) | ||||||
| @@ -329,7 +193,7 @@ private: | |||||||
| 			Callable = InValue.Callable; | 			Callable = InValue.Callable; | ||||||
| 			Storage = InValue.Storage; | 			Storage = InValue.Storage; | ||||||
| 		} | 		} | ||||||
| 		else Reset(); | 		else ResetImpl(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	FORCEINLINE void AssignImpl(TFunctionImpl&& InValue) | 	FORCEINLINE void AssignImpl(TFunctionImpl&& InValue) | ||||||
| @@ -338,69 +202,247 @@ private: | |||||||
| 		{ | 		{ | ||||||
| 			Callable = InValue.Callable; | 			Callable = InValue.Callable; | ||||||
| 			Storage = MoveTemp(InValue.Storage); | 			Storage = MoveTemp(InValue.Storage); | ||||||
| 			InValue.Reset(); | 			InValue.ResetImpl(); | ||||||
| 		} | 		} | ||||||
| 		else Reset(); | 		else ResetImpl(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| }; | 	constexpr void ResetImpl() { Callable = nullptr; } | ||||||
|  |  | ||||||
| template <typename F, size_t InlineSize, size_t InlineAlignment, EFunctionType FunctionType> |  | ||||||
| struct TFunctionSelect; |  | ||||||
|  |  | ||||||
| template <typename R, typename... Types, size_t InlineSize, size_t InlineAlignment, EFunctionType FunctionType> |  | ||||||
| struct TFunctionSelect<R(Types...)        , InlineSize, InlineAlignment, FunctionType> |  | ||||||
| { |  | ||||||
| 	using Type = TFunctionImpl<R(Types...), InlineSize, InlineAlignment, EFunctionSpecifiers::None, FunctionType>; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| template <typename R, typename... Types, size_t InlineSize, size_t InlineAlignment, EFunctionType FunctionType> |  | ||||||
| struct TFunctionSelect<R(Types...) &      , InlineSize, InlineAlignment, FunctionType> |  | ||||||
| { |  | ||||||
| 	using Type = TFunctionImpl<R(Types...), InlineSize, InlineAlignment, EFunctionSpecifiers::LValue, FunctionType>; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| template <typename R, typename... Types, size_t InlineSize, size_t InlineAlignment, EFunctionType FunctionType> |  | ||||||
| struct TFunctionSelect<R(Types...) &&     , InlineSize, InlineAlignment, FunctionType> |  | ||||||
| { |  | ||||||
| 	using Type = TFunctionImpl<R(Types...), InlineSize, InlineAlignment, EFunctionSpecifiers::RValue, FunctionType>; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| template <typename R, typename... Types, size_t InlineSize, size_t InlineAlignment, EFunctionType FunctionType> |  | ||||||
| struct TFunctionSelect<R(Types...) const  , InlineSize, InlineAlignment, FunctionType> |  | ||||||
| { |  | ||||||
| 	using Type = TFunctionImpl<R(Types...), InlineSize, InlineAlignment, EFunctionSpecifiers::Const, FunctionType>; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| template <typename R, typename... Types, size_t InlineSize, size_t InlineAlignment, EFunctionType FunctionType> |  | ||||||
| struct TFunctionSelect<R(Types...) const& , InlineSize, InlineAlignment, FunctionType> |  | ||||||
| { |  | ||||||
| 	using Type = TFunctionImpl<R(Types...), InlineSize, InlineAlignment, EFunctionSpecifiers::ConstLValue, FunctionType>; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| template <typename R, typename... Types, size_t InlineSize, size_t InlineAlignment, EFunctionType FunctionType> |  | ||||||
| struct TFunctionSelect<R(Types...) const&&, InlineSize, InlineAlignment, FunctionType> |  | ||||||
| { |  | ||||||
| 	using Type = TFunctionImpl<R(Types...), InlineSize, InlineAlignment, EFunctionSpecifiers::ConstRValue, FunctionType>; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| NAMESPACE_PRIVATE_END | NAMESPACE_PRIVATE_END | ||||||
|  |  | ||||||
| inline constexpr size_t FUNCTION_DEFAULT_INLINE_SIZE      = ANY_DEFAULT_INLINE_SIZE - sizeof(uintptr); | template <typename F> requires TIsFunction<F>::Value | ||||||
| inline constexpr size_t FUNCTION_DEFAULT_INLINE_ALIGNMENT = ANY_DEFAULT_INLINE_ALIGNMENT; | struct TFunctionRef  | ||||||
|  | 	: public NAMESPACE_PRIVATE::TFunctionImpl< | ||||||
|  | 		typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn, | ||||||
|  | 		typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef, | ||||||
|  | 		FUNCTION_DEFAULT_INLINE_SIZE, | ||||||
|  | 		FUNCTION_DEFAULT_INLINE_ALIGNMENT, | ||||||
|  | 		true> | ||||||
|  | { | ||||||
|  | private: | ||||||
|  |  | ||||||
| template <typename F> | 	using Super = NAMESPACE_PRIVATE::TFunctionImpl< | ||||||
| using TFunctionRef = typename NAMESPACE_PRIVATE::TFunctionSelect<F, FUNCTION_DEFAULT_INLINE_SIZE, FUNCTION_DEFAULT_INLINE_ALIGNMENT, NAMESPACE_PRIVATE::EFunctionType::Reference>::Type; | 		typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn, | ||||||
|  | 		typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef, | ||||||
|  | 		FUNCTION_DEFAULT_INLINE_SIZE, | ||||||
|  | 		FUNCTION_DEFAULT_INLINE_ALIGNMENT, | ||||||
|  | 		true>; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |  | ||||||
|  | 	TFunctionRef() = delete; | ||||||
|  |  | ||||||
|  | 	TFunctionRef(const TFunctionRef& InValue) = default; | ||||||
|  | 	TFunctionRef(TFunctionRef&& InValue) = default; | ||||||
|  |  | ||||||
|  | 	TFunctionRef& operator=(const TFunctionRef& InValue) = delete; | ||||||
|  | 	TFunctionRef& operator=(TFunctionRef&& InValue) = delete; | ||||||
|  |  | ||||||
|  | 	template <typename T> requires (!TIsTFunctionRef<typename TDecay<T>::Type>::Value) && (!TIsTInPlaceType<typename TDecay<T>::Type>::Value) | ||||||
|  | 		&& NAMESPACE_PRIVATE::TIsInvocableSignature<F, typename TDecay<T>::Type>::Value | ||||||
|  | 	FORCEINLINE TFunctionRef(T&& InValue) | ||||||
|  | 	{ | ||||||
|  | 		using DecayedType = typename TDecay<T>::Type; | ||||||
|  | 		checkf(NAMESPACE_PRIVATE::FunctionIsBound(InValue), TEXT("Cannot bind a null/unbound callable to a TFunctionRef")); | ||||||
|  | 		Super::template EmplaceImpl<DecayedType>(Forward<T>(InValue)); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	template <typename T> | ||||||
|  | 	TFunctionRef(const T&&) = delete; | ||||||
|  |  | ||||||
|  | }; | ||||||
|  |  | ||||||
| template <typename F, size_t InlineSize = FUNCTION_DEFAULT_INLINE_SIZE, size_t InlineAlignment = FUNCTION_DEFAULT_INLINE_ALIGNMENT> | template <typename F, size_t InlineSize = FUNCTION_DEFAULT_INLINE_SIZE, size_t InlineAlignment = FUNCTION_DEFAULT_INLINE_ALIGNMENT> | ||||||
| using TFunction = typename NAMESPACE_PRIVATE::TFunctionSelect<F, InlineSize, InlineAlignment, NAMESPACE_PRIVATE::EFunctionType::Object>::Type; | 	requires TIsFunction<F>::Value && (Memory::IsValidAlignment(InlineAlignment)) | ||||||
|  | struct TFunction  | ||||||
|  | 	: public NAMESPACE_PRIVATE::TFunctionImpl< | ||||||
|  | 		typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn, | ||||||
|  | 		typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef, | ||||||
|  | 		InlineSize, | ||||||
|  | 		InlineAlignment, | ||||||
|  | 		false> | ||||||
|  | { | ||||||
|  | private: | ||||||
|  |  | ||||||
|  | 	using Super = NAMESPACE_PRIVATE::TFunctionImpl< | ||||||
|  | 		typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn, | ||||||
|  | 		typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef, | ||||||
|  | 		InlineSize, | ||||||
|  | 		InlineAlignment, | ||||||
|  | 		false>; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |  | ||||||
|  | 	constexpr TFunction(nullptr_t = nullptr) { Super::ResetImpl(); } | ||||||
|  |  | ||||||
|  | 	FORCEINLINE TFunction(const TFunction& InValue) = default; | ||||||
|  | 	FORCEINLINE TFunction(TFunction&& InValue) : Super(MoveTemp(InValue)) { InValue.ResetImpl(); } | ||||||
|  |  | ||||||
|  | 	FORCEINLINE TFunction& operator=(const TFunction& InValue) | ||||||
|  | 	{ | ||||||
|  | 		Super::AssignImpl(InValue); | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	FORCEINLINE TFunction& operator=(TFunction&& InValue) | ||||||
|  | 	{ | ||||||
|  | 		if (&InValue == this) return *this; | ||||||
|  | 		Super::AssignImpl(MoveTemp(InValue)); | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	template <typename T> requires (!TIsTInPlaceType<typename TDecay<T>::Type>::Value) | ||||||
|  | 		&& (!TIsTFunctionRef<typename TDecay<T>::Type>::Value) && (!TIsTFunction<typename TDecay<T>::Type>::Value) && (!TIsTUniqueFunction<typename TDecay<T>::Type>::Value) | ||||||
|  | 		&& TIsConstructible<typename TDecay<T>::Type, T&&>::Value && TIsCopyConstructible<typename TDecay<T>::Type>::Value | ||||||
|  | 		&& NAMESPACE_PRIVATE::TIsInvocableSignature<F, typename TDecay<T>::Type>::Value | ||||||
|  | 	FORCEINLINE TFunction(T&& InValue) | ||||||
|  | 	{ | ||||||
|  | 		using DecayedType = typename TDecay<T>::Type; | ||||||
|  | 		if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) Super::ResetImpl(); | ||||||
|  | 		else Super::template EmplaceImpl<DecayedType>(Forward<T>(InValue)); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	template <typename T, typename... ArgTypes> requires NAMESPACE_PRIVATE::TIsInvocableSignature<F, typename TDecay<T>::Type>::Value | ||||||
|  | 		&& TIsConstructible<typename TDecay<T>::Type, ArgTypes...>::Value && TIsCopyConstructible<typename TDecay<T>::Type>::Value | ||||||
|  | 	FORCEINLINE TFunction(TInPlaceType<T>, ArgTypes&&... Args) | ||||||
|  | 	{ | ||||||
|  | 		using DecayedType = typename TDecay<T>::Type; | ||||||
|  | 		Super::template EmplaceImpl<DecayedType>(Forward<ArgTypes>(Args)...); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	constexpr TFunction& operator=(nullptr_t) { Super::ResetImpl(); return *this; } | ||||||
|  |  | ||||||
|  | 	template <typename T> requires NAMESPACE_PRIVATE::TIsInvocableSignature<F, typename TDecay<T>::Type>::Value | ||||||
|  | 		&& (!TIsTFunctionRef<typename TDecay<T>::Type>::Value) && (!TIsTFunction<typename TDecay<T>::Type>::Value) && (!TIsTUniqueFunction<typename TDecay<T>::Type>::Value) | ||||||
|  | 		&& TIsConstructible<typename TDecay<T>::Type, T&&>::Value && TIsCopyConstructible<typename TDecay<T>::Type>::Value | ||||||
|  | 	FORCEINLINE TFunction& operator=(T&& InValue) | ||||||
|  | 	{ | ||||||
|  | 		using DecayedType = typename TDecay<T>::Type; | ||||||
|  |  | ||||||
|  | 		if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) Super::ResetImpl(); | ||||||
|  | 		else Super::template EmplaceImpl<DecayedType>(Forward<T>(InValue)); | ||||||
|  |  | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	template <typename T, typename... ArgTypes> requires NAMESPACE_PRIVATE::TIsInvocableSignature<F, typename TDecay<T>::Type>::Value | ||||||
|  | 		&& TIsConstructible<typename TDecay<T>::Type, ArgTypes...>::Value&& TIsCopyConstructible<typename TDecay<T>::Type>::Value | ||||||
|  | 	FORCEINLINE typename TDecay<T>::Type& Emplace(ArgTypes&&... Args) | ||||||
|  | 	{ | ||||||
|  | 		using DecayedType = typename TDecay<T>::Type; | ||||||
|  | 		Super::template EmplaceImpl<DecayedType>(Forward<ArgTypes>(Args)...); | ||||||
|  | 		return Super::template Target<DecayedType>(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	constexpr void Reset() { Super::ResetImpl(); } | ||||||
|  |  | ||||||
|  | }; | ||||||
|  |  | ||||||
| template <typename F, size_t InlineSize = FUNCTION_DEFAULT_INLINE_SIZE, size_t InlineAlignment = FUNCTION_DEFAULT_INLINE_ALIGNMENT> | template <typename F, size_t InlineSize = FUNCTION_DEFAULT_INLINE_SIZE, size_t InlineAlignment = FUNCTION_DEFAULT_INLINE_ALIGNMENT> | ||||||
| using TUniqueFunction = typename NAMESPACE_PRIVATE::TFunctionSelect<F, InlineSize, InlineAlignment, NAMESPACE_PRIVATE::EFunctionType::Unique>::Type; | 	requires TIsFunction<F>::Value && (Memory::IsValidAlignment(InlineAlignment)) | ||||||
|  | struct TUniqueFunction | ||||||
|  | 	: public NAMESPACE_PRIVATE::TFunctionImpl< | ||||||
|  | 		typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn, | ||||||
|  | 		typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef, | ||||||
|  | 		InlineSize, | ||||||
|  | 		InlineAlignment, | ||||||
|  | 	false> | ||||||
|  | { | ||||||
|  | private: | ||||||
|  |  | ||||||
| template <typename T> struct TIsTFunctionRef    : NAMESPACE_PRIVATE::TIsTFunctionRef<T>    { }; | 	using Super = NAMESPACE_PRIVATE::TFunctionImpl< | ||||||
| template <typename T> struct TIsTFunction       : NAMESPACE_PRIVATE::TIsTFunction<T>       { }; | 		typename NAMESPACE_PRIVATE::TFunctionInfo<F>::Fn, | ||||||
| template <typename T> struct TIsTUniqueFunction : NAMESPACE_PRIVATE::TIsTUniqueFunction<T> { }; | 		typename NAMESPACE_PRIVATE::TFunctionInfo<F>::CVRef, | ||||||
|  | 		InlineSize, | ||||||
|  | 		InlineAlignment, | ||||||
|  | 		false>; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |  | ||||||
|  | 	constexpr TUniqueFunction(nullptr_t = nullptr) { Super::ResetImpl(); } | ||||||
|  |  | ||||||
|  | 	FORCEINLINE TUniqueFunction(const TUniqueFunction& InValue) = delete; | ||||||
|  | 	TUniqueFunction(TUniqueFunction&& InValue) : Super(MoveTemp(InValue)) { InValue.ResetImpl(); } | ||||||
|  |  | ||||||
|  | 	FORCEINLINE TUniqueFunction& operator=(const TUniqueFunction& InValue) = delete; | ||||||
|  | 	FORCEINLINE TUniqueFunction& operator=(TUniqueFunction&& InValue) | ||||||
|  | 	{ | ||||||
|  | 		if (&InValue == this) return *this; | ||||||
|  | 		Super::AssignImpl(MoveTemp(InValue)); | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	FORCEINLINE TUniqueFunction(const TFunction<F, InlineSize, InlineAlignment>& InValue) | ||||||
|  | 		: Super(*reinterpret_cast<const TUniqueFunction*>(&InValue)) | ||||||
|  | 	{ } | ||||||
|  |  | ||||||
|  | 	FORCEINLINE TUniqueFunction(TFunction<F, InlineSize, InlineAlignment>&& InValue) | ||||||
|  | 		: Super(MoveTemp(*reinterpret_cast<const TUniqueFunction*>(&InValue))) | ||||||
|  | 	{ | ||||||
|  | 		InValue.Reset(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	FORCEINLINE TUniqueFunction& operator=(const TFunction<F, InlineSize, InlineAlignment>& InValue) | ||||||
|  | 	{ | ||||||
|  | 		Super::AssignImpl(*reinterpret_cast<const TUniqueFunction*>(&InValue)); | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	FORCEINLINE TUniqueFunction& operator=(TFunction<F, InlineSize, InlineAlignment>&& InValue) | ||||||
|  | 	{ | ||||||
|  | 		Super::AssignImpl(MoveTemp(*reinterpret_cast<TUniqueFunction*>(&InValue))); | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	template <typename T> requires (!TIsTInPlaceType<typename TDecay<T>::Type>::Value) | ||||||
|  | 		&& (!TIsTFunctionRef<typename TDecay<T>::Type>::Value) && (!TIsTFunction<typename TDecay<T>::Type>::Value) && (!TIsTUniqueFunction<typename TDecay<T>::Type>::Value) | ||||||
|  | 		&& TIsConstructible<typename TDecay<T>::Type, T&&>::Value && TIsMoveConstructible<typename TDecay<T>::Type>::Value | ||||||
|  | 		&& NAMESPACE_PRIVATE::TIsInvocableSignature<F, typename TDecay<T>::Type>::Value | ||||||
|  | 	FORCEINLINE TUniqueFunction(T&& InValue) | ||||||
|  | 	{ | ||||||
|  | 		using DecayedType = typename TDecay<T>::Type; | ||||||
|  | 		if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) Super::ResetImpl(); | ||||||
|  | 		else Super::template EmplaceImpl<DecayedType>(Forward<T>(InValue)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	template <typename T, typename... ArgTypes> requires NAMESPACE_PRIVATE::TIsInvocableSignature<F, typename TDecay<T>::Type>::Value | ||||||
|  | 		&& TIsConstructible<typename TDecay<T>::Type, ArgTypes...>::Value && TIsMoveConstructible<typename TDecay<T>::Type>::Value | ||||||
|  | 	FORCEINLINE TUniqueFunction(TInPlaceType<T>, ArgTypes&&... Args) | ||||||
|  | 	{ | ||||||
|  | 		using DecayedType = typename TDecay<T>::Type; | ||||||
|  | 		Super::template EmplaceImpl<DecayedType>(Forward<ArgTypes>(Args)...); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	constexpr TUniqueFunction& operator=(nullptr_t) { Super::ResetImpl(); return *this; } | ||||||
|  |  | ||||||
|  | 	template <typename T> requires NAMESPACE_PRIVATE::TIsInvocableSignature<F, typename TDecay<T>::Type>::Value | ||||||
|  | 		&& (!TIsTFunctionRef<typename TDecay<T>::Type>::Value) && (!TIsTFunction<typename TDecay<T>::Type>::Value) && (!TIsTUniqueFunction<typename TDecay<T>::Type>::Value) | ||||||
|  | 		&& TIsConstructible<typename TDecay<T>::Type, T&&>::Value&& TIsMoveConstructible<typename TDecay<T>::Type>::Value | ||||||
|  | 	FORCEINLINE TUniqueFunction& operator=(T&& InValue) | ||||||
|  | 	{ | ||||||
|  | 		using DecayedType = typename TDecay<T>::Type; | ||||||
|  |  | ||||||
|  | 		if (!NAMESPACE_PRIVATE::FunctionIsBound(InValue)) Super::ResetImpl(); | ||||||
|  | 		else Super::template EmplaceImpl<DecayedType>(Forward<T>(InValue)); | ||||||
|  |  | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	template <typename T, typename... ArgTypes> requires NAMESPACE_PRIVATE::TIsInvocableSignature<F, typename TDecay<T>::Type>::Value | ||||||
|  | 		&& TIsConstructible<typename TDecay<T>::Type, ArgTypes...>::Value&& TIsMoveConstructible<typename TDecay<T>::Type>::Value | ||||||
|  | 	FORCEINLINE typename TDecay<T>::Type& Emplace(ArgTypes&&... Args) | ||||||
|  | 	{ | ||||||
|  | 		using DecayedType = typename TDecay<T>::Type; | ||||||
|  | 		Super::template EmplaceImpl<DecayedType>(Forward<ArgTypes>(Args)...); | ||||||
|  | 		return Super::template Target<DecayedType>(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	constexpr void Reset() { Super::ResetImpl(); } | ||||||
|  |  | ||||||
|  | }; | ||||||
|  |  | ||||||
| template <typename F> | template <typename F> | ||||||
| constexpr bool operator==(const TFunctionRef<F>& LHS, nullptr_t) | constexpr bool operator==(const TFunctionRef<F>& LHS, nullptr_t) | ||||||
| @@ -426,51 +468,51 @@ static_assert(sizeof(TUniqueFunction<void()>) == 64, "The byte size of TUniqueFu | |||||||
| NAMESPACE_PRIVATE_BEGIN | NAMESPACE_PRIVATE_BEGIN | ||||||
|  |  | ||||||
| template <typename F> | template <typename F> | ||||||
| struct NotFunctionType | struct TNotFunction | ||||||
| { | { | ||||||
| 	F Func; | 	F Storage; | ||||||
|  |  | ||||||
| 	NotFunctionType(const NotFunctionType&) = default; | 	TNotFunction(const TNotFunction&) = default; | ||||||
| 	NotFunctionType(NotFunctionType&&) = default; | 	TNotFunction(TNotFunction&&) = default; | ||||||
|  |  | ||||||
| 	template <typename InF> | 	template <typename InF> | ||||||
| 	constexpr NotFunctionType(InF&& InFunc) : Func(Forward<InF>(InFunc)) { } | 	constexpr TNotFunction(InF&& InFunc) : Storage(Forward<InF>(InFunc)) { } | ||||||
|  |  | ||||||
| 	template <typename... Types> requires TIsInvocable<F&, Types&&...>::Value | 	template <typename... Types> requires TIsInvocable<F&, Types&&...>::Value | ||||||
| 	constexpr auto operator()(Types&&... Args) & | 	constexpr auto operator()(Types&&... Args) & | ||||||
| 		-> decltype(!Invoke(Func, Forward<Types>(Args)...)) | 		-> decltype(!Invoke(Storage, Forward<Types>(Args)...)) | ||||||
| 	{ | 	{ | ||||||
| 		return !Invoke(Func, Forward<Types>(Args)...); | 		return !Invoke(Storage, Forward<Types>(Args)...); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	template <typename... Types> requires TIsInvocable<F&&, Types&&...>::Value | 	template <typename... Types> requires TIsInvocable<F&&, Types&&...>::Value | ||||||
| 	constexpr auto operator()(Types&&... Args) && | 	constexpr auto operator()(Types&&... Args) && | ||||||
| 		-> decltype(!Invoke(MoveTemp(Func), Forward<Types>(Args)...)) | 		-> decltype(!Invoke(MoveTemp(Storage), Forward<Types>(Args)...)) | ||||||
| 	{ | 	{ | ||||||
| 		return !Invoke(MoveTemp(Func), Forward<Types>(Args)...); | 		return !Invoke(MoveTemp(Storage), Forward<Types>(Args)...); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	template <typename... Types> requires TIsInvocable<const F&, Types&&...>::Value | 	template <typename... Types> requires TIsInvocable<const F&, Types&&...>::Value | ||||||
| 	constexpr auto operator()(Types&&... Args) const& | 	constexpr auto operator()(Types&&... Args) const& | ||||||
| 		-> decltype(!Invoke(Func, Forward<Types>(Args)...)) | 		-> decltype(!Invoke(Storage, Forward<Types>(Args)...)) | ||||||
| 	{ | 	{ | ||||||
| 		return !Invoke(Func, Forward<Types>(Args)...); | 		return !Invoke(Storage, Forward<Types>(Args)...); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	template <typename... Types> requires TIsInvocable<const F&&, Types&&...>::Value | 	template <typename... Types> requires TIsInvocable<const F&&, Types&&...>::Value | ||||||
| 	constexpr auto operator()(Types&&... Args) const&& | 	constexpr auto operator()(Types&&... Args) const&& | ||||||
| 		-> decltype(!Invoke(MoveTemp(Func), Forward<Types>(Args)...)) | 		-> decltype(!Invoke(MoveTemp(Storage), Forward<Types>(Args)...)) | ||||||
| 	{ | 	{ | ||||||
| 		return !Invoke(MoveTemp(Func), Forward<Types>(Args)...); | 		return !Invoke(MoveTemp(Storage), Forward<Types>(Args)...); | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| NAMESPACE_PRIVATE_END | NAMESPACE_PRIVATE_END | ||||||
|  |  | ||||||
| template <typename F> | template <typename F> | ||||||
| constexpr NAMESPACE_PRIVATE::NotFunctionType<typename TDecay<F>::Type> NotFn(F&& Func) | constexpr NAMESPACE_PRIVATE::TNotFunction<typename TDecay<F>::Type> NotFn(F&& Func) | ||||||
| { | { | ||||||
| 	return NAMESPACE_PRIVATE::NotFunctionType<typename TDecay<F>::Type>(Forward<F>(Func)); | 	return NAMESPACE_PRIVATE::TNotFunction<typename TDecay<F>::Type>(Forward<F>(Func)); | ||||||
| } | } | ||||||
|  |  | ||||||
| NAMESPACE_MODULE_END(Utility) | NAMESPACE_MODULE_END(Utility) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user