#pragma once #include "CoreTypes.h" #include "Templates/Tuple.h" #include "Templates/Utility.h" #include "Memory/PointerTraits.h" #include "Templates/Noncopyable.h" #include "TypeTraits/TypeTraits.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_PRIVATE_BEGIN template using TRawPointer = TConditional, typename TPointerTraits>::ElementType*, RT>; template class FInOutPtr final : private FSingleton { public: explicit FInOutPtr(ST& InPtr, Ts&&... Args) requires (!bEnableInput) : SPointer(InPtr), Tuple(nullptr, Forward(Args)...) { } explicit FInOutPtr(ST& InPtr, Ts&&... Args) requires (bEnableInput) : SPointer(InPtr), Tuple(InPtr.Release(), Forward(Args)...) { } ~FInOutPtr() { if constexpr (requires(RT* RPtr, ST& SPtr, Ts&&... Args) { SPtr.Reset(RPtr, Forward(Args)...); }) { Tuple.Apply([this](Ts&&... Args) { SPointer.Reset(Forward(Args)...); }); } else if constexpr (CConstructibleFrom && CMoveAssignable) { SPointer = Tuple.template Construct(); } else check_no_entry(); } operator RT*() { return &Tuple.First; } operator void**() requires (!CSameAs) { return &Tuple.First; } private: ST& SPointer; TTuple< RT, Ts&&...> Tuple; }; NAMESPACE_PRIVATE_END template requires ((CVoid) || (CPointer) && (requires(NAMESPACE_PRIVATE::TRawPointer* RPtr, ST& SPtr, Ts&&... Args) { SPtr.Reset(RPtr, Forward(Args)...); }) || (CConstructibleFrom, Ts...> && CMoveAssignable) && requires { typename TPointerTraits>::ElementType; }) auto OutPtr(ST& InPtr, Ts&&... Args) { return NAMESPACE_PRIVATE::FInOutPtr, ST, Ts...>(InPtr, Forward(Args)...); } template requires ((CVoid) || (CPointer) && (requires(NAMESPACE_PRIVATE::TRawPointer* RPtr, ST& SPtr, Ts&&... Args) { SPtr.Reset(RPtr, Forward(Args)...); }) || (CConstructibleFrom, Ts...> && CMoveAssignable) && requires(ST& SPtr) { { SPtr.Release() } -> CConvertibleTo>; } && requires { typename TPointerTraits>::ElementType; }) auto InOutPtr(ST& InPtr, Ts&&... Args) { return NAMESPACE_PRIVATE::FInOutPtr, ST, Ts...>(InPtr, Forward(Args)...); } NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END