From 1b2ea5c2a6effb2948fc54a59c37dc9a12bcf1cf Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Fri, 20 Jan 2023 21:21:26 +0800 Subject: [PATCH] feat(templates): add TRetainedRef and the corresponding testing --- .../Private/Testing/TemplatesTesting.cpp | 16 ++-- .../Public/Templates/RetainedReference.h | 73 +++++++++++++++++++ .../Source/Public/Templates/Templates.h | 1 + 3 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 Redcraft.Utility/Source/Public/Templates/RetainedReference.h diff --git a/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp b/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp index 2c3d8e8..0d68e86 100644 --- a/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp +++ b/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp @@ -1475,8 +1475,8 @@ void TestPropagateConst() { struct FTestA { - void Check(bool bFlag) { check(!bFlag); } - void Check(bool bFlag) const { check(bFlag); } + void Check(bool bFlag) { always_check(!bFlag); } + void Check(bool bFlag) const { always_check( bFlag); } }; struct FTestB @@ -1504,9 +1504,9 @@ void TestPropagateConst() TempA = TempB; TempB = TempC; - check(TempA.IsValid()); - check(TempA == &IntA); - check(TempB == TempC); + always_check(TempA.IsValid()); + always_check(TempA == &IntA); + always_check(TempB == TempC); } } @@ -1544,6 +1544,12 @@ void TestMiscTemplates() always_check(TestFunctionB(AddressOf(ObjectA)) == 0); always_check(AddressOf(TestMiscTemplates) == &TestMiscTemplates); + struct FTestRetainedRef { explicit FTestRetainedRef(TRetainedRef InRef) { } }; + + int64 IntA; + FTestRetainedRef TempA(IntA); +// FTestRetainedRef TempB(114514); + } NAMESPACE_END(Testing) diff --git a/Redcraft.Utility/Source/Public/Templates/RetainedReference.h b/Redcraft.Utility/Source/Public/Templates/RetainedReference.h new file mode 100644 index 0000000..b633f86 --- /dev/null +++ b/Redcraft.Utility/Source/Public/Templates/RetainedReference.h @@ -0,0 +1,73 @@ +#pragma once + +#include "CoreTypes.h" +#include "Templates/Utility.h" +#include "TypeTraits/TypeTraits.h" + +NAMESPACE_REDCRAFT_BEGIN +NAMESPACE_MODULE_BEGIN(Redcraft) +NAMESPACE_MODULE_BEGIN(Utility) + +/** + * A helper class which replaces T& as a function parameter when the reference is + * intended to be retained by the function (e.g. as a class member). The benefit + * of this class is that it is a compile error to pass an rvalue which might otherwise + * bind to a const reference, which is dangerous when the reference is retained. + * + * struct FRAIIType + * { + * explicit FRAIIType(TRetainedRef InThing) : Ref(InThing) { } + * + * void DoSomething() { Ref.Something(); } + * + * FThing& Ref; + * }; + * + */ +template +struct TRetainedRef +{ + /** Retain a non-const lvalue reference. */ + FORCEINLINE constexpr TRetainedRef(T& InRef) : Ref(InRef) { } + + /** Can't retain a rvalue reference. */ + TRetainedRef(const T& ) = delete; + TRetainedRef( T&&) = delete; + TRetainedRef(const T&&) = delete; + + /** @return The managed reference. */ + FORCEINLINE constexpr operator T&() const { return Ref; } + FORCEINLINE constexpr T& Get() const { return Ref; } + +private: + + T& Ref; + +}; + +template +struct TRetainedRef +{ + /** Retain a non-const lvalue reference. */ + FORCEINLINE constexpr TRetainedRef(T& InRef) : Ref(InRef) { } + + /** Retain a const lvalue reference. */ + FORCEINLINE constexpr TRetainedRef(const T& InRef) : Ref(InRef) { } + + /** Can't retain a rvalue reference. */ + TRetainedRef( T&&) = delete; + TRetainedRef(const T&&) = delete; + + /** @return The managed reference. */ + FORCEINLINE constexpr operator const T&() const { return Ref; } + FORCEINLINE constexpr const T& Get() const { return Ref; } + +private: + + const T& Ref; + +}; + +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 5039e9f..7318a61 100644 --- a/Redcraft.Utility/Source/Public/Templates/Templates.h +++ b/Redcraft.Utility/Source/Public/Templates/Templates.h @@ -16,3 +16,4 @@ #include "Templates/Atomic.h" #include "Templates/ScopeHelper.h" #include "Templates/PropagateConst.h" +#include "Templates/RetainedReference.h"