#pragma once #include "CoreTypes.h" #include "Templates/Utility.h" #include "TypeTraits/Invocable.h" #include "Templates/Noncopyable.h" #include "TypeTraits/CompositeType.h" #include "TypeTraits/Miscellaneous.h" #include "TypeTraits/SupportedOperations.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) /** The class template is a general-purpose scope guard intended to call its callback function when a scope is exited. */ template requires (CDestructible) class TScopeCallback final : public FNoncopyable { public: /** Initializes the callback function with a function or function object. */ template requires (!CSameAs, TScopeCallback> && CConstructibleFrom) FORCEINLINE constexpr explicit TScopeCallback(InF&& Func) : Storage(Forward(Func)), bIsActive(true) { } /** Move constructor. Initializes the stored object with the one in other. */ FORCEINLINE constexpr TScopeCallback(TScopeCallback&& InValue) requires (CMoveConstructible) : Storage(MoveTemp(InValue.Storage)), bIsActive(InValue.bIsActive) { InValue.Release(); } /** Calls the callback function if the TScopeCallback is active, then destroys the stored object. */ FORCEINLINE constexpr ~TScopeCallback() { if (bIsActive) Storage(); } /** Makes the TScopeCallback inactive. */ FORCEINLINE constexpr void Release() { bIsActive = false; } /** @return a const reference to the stored object. */ FORCEINLINE constexpr const F& Get() const { return Storage; } private: F Storage; bool bIsActive; }; template TScopeCallback(F) -> TScopeCallback; /** The class template is a general-purpose scope guard intended to make sure a value is restored when a scope is exited. */ template requires (CCopyConstructible && CCopyAssignable && CMoveAssignable && CDestructible) class TGuardValue final : public FNoncopyable { public: /** Initializes the TGuardValue with a reference. */ FORCEINLINE constexpr TGuardValue(T& InReference) : Reference(InReference), OldValue(InReference), bIsActive(true) { } /** Initializes the TGuardValue with a reference and assign a new value to the reference. */ template requires (CAssignableFrom) FORCEINLINE constexpr TGuardValue(T& InReference, U&& InValue) : Reference(InReference), OldValue(InReference), bIsActive(true) { InReference = InValue; } /** Move constructor. Initializes the referenced value and old value with the one in other. */ FORCEINLINE constexpr TGuardValue(TGuardValue&& InValue) requires (CMoveConstructible) : Reference(InValue.Reference), OldValue(MoveTemp(InValue.OldValue)), bIsActive(InValue.bIsActive) { InValue.Release(); } /** Restore the referenced value if the TGuardValue is active, then destroys the old value. */ FORCEINLINE constexpr ~TGuardValue() { if (bIsActive) Reference = MoveTemp(OldValue); } /** Makes the TGuardValue inactive. */ FORCEINLINE constexpr void Release() { bIsActive = false; } /** @return a const reference to the old value. */ FORCEINLINE constexpr const T& Get() const { return OldValue; } private: T& Reference; T OldValue; bool bIsActive; }; template TGuardValue(T&) -> TGuardValue; template TGuardValue(T&, U&&) -> TGuardValue; /** Commonly used to make sure a value is incremented, and then decremented when a scope is exited. */ template requires (requires(T& Value) { ++Value; --Value; }) class TScopeCounter : public FNoncopyable { public: /** Initializes the TScopeCounter with a reference and increments it. */ FORCEINLINE constexpr TScopeCounter(T& InReference) : Reference(InReference) { ++Reference; } /** Decrements the referenced value. */ FORCEINLINE constexpr ~TScopeCounter() { --Reference; } /** @return a const reference to the value. */ FORCEINLINE constexpr const T& Get() const { return Reference; } private: T& Reference; }; template TScopeCounter(T&) -> TScopeCounter; NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END