feat(templates): add TRetainedRef and the corresponding testing

This commit is contained in:
_Redstone_c_ 2023-01-20 21:21:26 +08:00
parent 2ef2c4a729
commit 1b2ea5c2a6
3 changed files with 85 additions and 5 deletions

View File

@ -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<const int64> InRef) { } };
int64 IntA;
FTestRetainedRef TempA(IntA);
// FTestRetainedRef TempB(114514);
}
NAMESPACE_END(Testing)

View File

@ -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<const FThing> InThing) : Ref(InThing) { }
*
* void DoSomething() { Ref.Something(); }
*
* FThing& Ref;
* };
*
*/
template <typename T>
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 <typename T>
struct TRetainedRef<const T>
{
/** 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

View File

@ -16,3 +16,4 @@
#include "Templates/Atomic.h"
#include "Templates/ScopeHelper.h"
#include "Templates/PropagateConst.h"
#include "Templates/RetainedReference.h"