diff --git a/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp b/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp index 4508fd3..afcab32 100644 --- a/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp +++ b/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp @@ -9,6 +9,7 @@ NAMESPACE_MODULE_BEGIN(Utility) void TestTemplates() { TestInvoke(); + TestReferenceWrapper(); TestMiscellaneous(); } @@ -45,6 +46,26 @@ void TestInvoke() always_check(TempE == 123); } +void TestReferenceWrapper() +{ + typedef int32(*FuncType)(int32, int32, int32); + FuncType TempA = [](int32 A, int32 B, int32 C) -> int32 { return A * B * C; }; + TReferenceWrapper TempB(TempA); + always_check(TempB(1, 1, 1) == 1); + TempB.Get() = &TestFunctionA; + always_check(TempA(1, 1, 1) == 3); + + int32 ArrayA[3] = { 1, 2, 3 }; + TReferenceWrapper ArrayB[3] = { ArrayA[1], ArrayA[0], ArrayA[2] }; + always_check(ArrayB[0] == 2); + always_check(ArrayB[1] == 1); + always_check(ArrayB[2] == 3); + for (int32& Element : ArrayB) Element *= 2; + always_check(ArrayA[0] == 2); + always_check(ArrayA[1] == 4); + always_check(ArrayA[2] == 6); +} + NAMESPACE_UNNAMED_BEGIN template diff --git a/Redcraft.Utility/Source/Public/Templates/ReferenceWrapper.h b/Redcraft.Utility/Source/Public/Templates/ReferenceWrapper.h new file mode 100644 index 0000000..250c092 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Templates/ReferenceWrapper.h @@ -0,0 +1,45 @@ +#pragma once + +#include "CoreTypes.h" +#include "Templates/Invoke.h" +#include "Templates/Utility.h" +#include "TypeTraits/TypeTraits.h" + +NAMESPACE_REDCRAFT_BEGIN +NAMESPACE_MODULE_BEGIN(Redcraft) +NAMESPACE_MODULE_BEGIN(Utility) + +template +class TReferenceWrapper +{ +public: + + using Type = T; + + template requires !TIsSame::Type>::Value + constexpr TReferenceWrapper(U&& Object) : Ptr(AddressOf(Forward(Object))) { } + + TReferenceWrapper(const TReferenceWrapper&) = default; + TReferenceWrapper& operator=(const TReferenceWrapper& x) = default; + + constexpr operator T&() const { return *Ptr; } + constexpr T& Get() const { return *Ptr; } + + template + constexpr TInvokeResult::Type operator()(Types&&... Args) const + { + return Invoke(Get(), Forward(Args)...); + } + +private: + + T* Ptr; + +}; + +template +TReferenceWrapper(T&) -> TReferenceWrapper; + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Templates/Templates.h b/Redcraft.Utility/Source/Public/Templates/Templates.h index 8326b94..67ceb48 100644 --- a/Redcraft.Utility/Source/Public/Templates/Templates.h +++ b/Redcraft.Utility/Source/Public/Templates/Templates.h @@ -5,3 +5,4 @@ #include "Templates/Container.h" #include "Templates/Noncopyable.h" #include "Templates/Invoke.h" +#include "Templates/ReferenceWrapper.h" diff --git a/Redcraft.Utility/Source/Public/Testing/TemplatesTesting.h b/Redcraft.Utility/Source/Public/Testing/TemplatesTesting.h index 6c0963b..e6758fa 100644 --- a/Redcraft.Utility/Source/Public/Testing/TemplatesTesting.h +++ b/Redcraft.Utility/Source/Public/Testing/TemplatesTesting.h @@ -8,6 +8,7 @@ NAMESPACE_MODULE_BEGIN(Utility) void REDCRAFTUTILITY_API TestTemplates(); void REDCRAFTUTILITY_API TestInvoke(); +void REDCRAFTUTILITY_API TestReferenceWrapper(); void REDCRAFTUTILITY_API TestMiscellaneous(); NAMESPACE_MODULE_END(Utility)