feat(memory): add InOutPtr and the corresponding testing
This commit is contained in:
parent
73b5305d34
commit
c634c2757c
@ -7,6 +7,7 @@
|
|||||||
#include "Memory/SharedPointer.h"
|
#include "Memory/SharedPointer.h"
|
||||||
#include "Memory/MemoryOperator.h"
|
#include "Memory/MemoryOperator.h"
|
||||||
#include "Memory/ObserverPointer.h"
|
#include "Memory/ObserverPointer.h"
|
||||||
|
#include "Memory/InOutPointer.h"
|
||||||
#include "Miscellaneous/AssertionMacros.h"
|
#include "Miscellaneous/AssertionMacros.h"
|
||||||
|
|
||||||
NAMESPACE_REDCRAFT_BEGIN
|
NAMESPACE_REDCRAFT_BEGIN
|
||||||
@ -25,6 +26,7 @@ void TestMemory()
|
|||||||
TestUniquePointer();
|
TestUniquePointer();
|
||||||
TestSharedPointer();
|
TestSharedPointer();
|
||||||
TestObserverPointer();
|
TestObserverPointer();
|
||||||
|
TestInOutPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestAlignment()
|
void TestAlignment()
|
||||||
@ -1098,6 +1100,33 @@ void TestObserverPointer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestInOutPointer()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
TUniquePtr<int64> Temp;
|
||||||
|
|
||||||
|
[](int64** InPtr) { *InPtr = new int64; } (OutPtr(Temp));
|
||||||
|
always_check(Temp.IsValid());
|
||||||
|
|
||||||
|
Temp.Reset();
|
||||||
|
|
||||||
|
[](int64** InPtr) { *InPtr = new int64; } (OutPtr(Temp, TDefaultDelete<int64>()));
|
||||||
|
always_check(Temp.IsValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TUniquePtr<int64> Temp = MakeUnique<int64>(2485800585);
|
||||||
|
|
||||||
|
[](int64** InPtr) { always_check(**InPtr == 2485800585); delete* InPtr; *InPtr = new int64; } (InOutPtr(Temp));
|
||||||
|
always_check(Temp.IsValid());
|
||||||
|
|
||||||
|
Temp = MakeUnique<int64>(2821859274);
|
||||||
|
|
||||||
|
[](int64** InPtr) { always_check(**InPtr == 2821859274); delete* InPtr; *InPtr = new int64; } (InOutPtr(Temp, TDefaultDelete<int64>()));
|
||||||
|
always_check(Temp.IsValid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NAMESPACE_END(Testing)
|
NAMESPACE_END(Testing)
|
||||||
|
|
||||||
NAMESPACE_MODULE_END(Utility)
|
NAMESPACE_MODULE_END(Utility)
|
||||||
|
78
Redcraft.Utility/Source/Public/Memory/InOutPointer.h
Normal file
78
Redcraft.Utility/Source/Public/Memory/InOutPointer.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#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 <typename RT, typename ST>
|
||||||
|
using TRawPointer = TConditional<CVoid<RT>, typename TPointerTraits<TRemoveCVRef<ST>>::ElementType*, RT>;
|
||||||
|
|
||||||
|
template <bool bEnableInput, typename RT, typename ST, typename... Ts>
|
||||||
|
class FInOutPtr final : private FSingleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit FInOutPtr(ST& InPtr, Ts&&... Args) requires (!bEnableInput)
|
||||||
|
: SPointer(InPtr), Tuple(nullptr, Forward<Ts>(Args)...)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
explicit FInOutPtr(ST& InPtr, Ts&&... Args) requires (bEnableInput)
|
||||||
|
: SPointer(InPtr), Tuple(InPtr.Release(), Forward<Ts>(Args)...)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
~FInOutPtr()
|
||||||
|
{
|
||||||
|
if constexpr (requires(RT* RPtr, ST& SPtr, Ts&&... Args) { SPtr.Reset(RPtr, Forward<Ts>(Args)...); })
|
||||||
|
{
|
||||||
|
Tuple.Apply([this](Ts&&... Args) { SPointer.Reset(Forward<Ts>(Args)...); });
|
||||||
|
}
|
||||||
|
else if constexpr (CConstructibleFrom<ST, RT, Ts...> && CMoveAssignable<ST>)
|
||||||
|
{
|
||||||
|
SPointer = Tuple.template Construct<ST>();
|
||||||
|
}
|
||||||
|
else check_no_entry();
|
||||||
|
}
|
||||||
|
|
||||||
|
operator RT*() { return &Tuple.First; }
|
||||||
|
operator void**() requires (!CSameAs<void*, RT>) { return &Tuple.First; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ST& SPointer;
|
||||||
|
TTuple< RT, Ts&&...> Tuple;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
NAMESPACE_PRIVATE_END
|
||||||
|
|
||||||
|
template <typename RT = void, typename ST, typename... Ts> requires ((CVoid<RT>) || (CPointer<RT>)
|
||||||
|
&& (requires(NAMESPACE_PRIVATE::TRawPointer<RT, ST>* RPtr, ST& SPtr, Ts&&... Args) { SPtr.Reset(RPtr, Forward<Ts>(Args)...); })
|
||||||
|
|| (CConstructibleFrom<ST, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, Ts...> && CMoveAssignable<ST>)
|
||||||
|
&& requires { typename TPointerTraits<TRemoveCV<ST>>::ElementType; })
|
||||||
|
auto OutPtr(ST& InPtr, Ts&&... Args)
|
||||||
|
{
|
||||||
|
return NAMESPACE_PRIVATE::FInOutPtr<false, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, ST, Ts...>(InPtr, Forward<Ts>(Args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename RT = void, typename ST, typename... Ts> requires ((CVoid<RT>) || (CPointer<RT>)
|
||||||
|
&& (requires(NAMESPACE_PRIVATE::TRawPointer<RT, ST>* RPtr, ST& SPtr, Ts&&... Args) { SPtr.Reset(RPtr, Forward<Ts>(Args)...); })
|
||||||
|
|| (CConstructibleFrom<ST, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, Ts...> && CMoveAssignable<ST>)
|
||||||
|
&& requires(ST& SPtr) { { SPtr.Release() } -> CConvertibleTo<NAMESPACE_PRIVATE::TRawPointer<RT, ST>>; }
|
||||||
|
&& requires { typename TPointerTraits<TRemoveCV<ST>>::ElementType; })
|
||||||
|
auto InOutPtr(ST& InPtr, Ts&&... Args)
|
||||||
|
{
|
||||||
|
return NAMESPACE_PRIVATE::FInOutPtr<true, NAMESPACE_PRIVATE::TRawPointer<RT, ST>, ST, Ts...>(InPtr, Forward<Ts>(Args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
NAMESPACE_MODULE_END(Utility)
|
||||||
|
NAMESPACE_MODULE_END(Redcraft)
|
||||||
|
NAMESPACE_REDCRAFT_END
|
@ -17,6 +17,7 @@ REDCRAFTUTILITY_API void TestPointerTraits();
|
|||||||
REDCRAFTUTILITY_API void TestUniquePointer();
|
REDCRAFTUTILITY_API void TestUniquePointer();
|
||||||
REDCRAFTUTILITY_API void TestSharedPointer();
|
REDCRAFTUTILITY_API void TestSharedPointer();
|
||||||
REDCRAFTUTILITY_API void TestObserverPointer();
|
REDCRAFTUTILITY_API void TestObserverPointer();
|
||||||
|
REDCRAFTUTILITY_API void TestInOutPointer();
|
||||||
|
|
||||||
NAMESPACE_END(Testing)
|
NAMESPACE_END(Testing)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user