Redcraft/Redcraft.Utility/Source/Public/Templates/RetainedReference.h

74 lines
1.8 KiB
C++

#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