#pragma once #include "CoreTypes.h" #include "Templates/Invoke.h" #include "Templates/Utility.h" #include "Templates/Optional.h" #include "TypeTraits/TypeTraits.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) /** * TReferenceWrapper is a class template that wraps a reference object. * It is frequently used as a mechanism to store references inside standard * containers which cannot normally hold references. */ template requires (CObject || CFunction) class TReferenceWrapper final { public: using Type = ReferencedType; /** Constructs a new reference wrapper. */ template requires (CConvertibleTo) FORCEINLINE constexpr TReferenceWrapper(T&& Object) { ReferencedType& Reference = Forward(Object); Pointer = AddressOf(Reference); } /** Copies/moves content of other into a new instance. */ FORCEINLINE constexpr TReferenceWrapper(const TReferenceWrapper&) = default; FORCEINLINE constexpr TReferenceWrapper(TReferenceWrapper&&) = default; /** Converting copy constructor. */ template requires (CConvertibleTo) FORCEINLINE constexpr TReferenceWrapper(const TReferenceWrapper& InValue) : Pointer(InValue.Pointer) { } /** Assign a value to the referenced object. */ template requires (CAssignableFrom) FORCEINLINE constexpr TReferenceWrapper& operator=(T&& Object) { Get() = Forward(Object); return *this; } /** Remove the assignment operator, as rebinding is not allowed. */ FORCEINLINE constexpr TReferenceWrapper& operator=(const TReferenceWrapper&) = delete; FORCEINLINE constexpr TReferenceWrapper& operator=(TReferenceWrapper&&) = delete; /** @return The stored reference. */ FORCEINLINE constexpr ReferencedType& Get() const { return *Pointer; } FORCEINLINE constexpr operator ReferencedType&() const { return *Pointer; } /** Calls the Callable object, reference to which is stored. */ template FORCEINLINE constexpr TInvokeResult operator()(Ts&&... Args) const { return Invoke(Get(), Forward(Args)...); } /** Overloads the GetTypeHash algorithm for TReferenceWrapper. */ NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(TReferenceWrapper A) requires (CHashable) { return GetTypeHash(A.Get()); } /** Overloads the Swap algorithm for TReferenceWrapper. */ friend FORCEINLINE constexpr void Swap(TReferenceWrapper A, TReferenceWrapper B) requires (CSwappable) { Swap(A.Get(), B.Get()); } private: ReferencedType* Pointer; template requires (CObject || CFunction) friend class TReferenceWrapper; }; template TReferenceWrapper(T&) -> TReferenceWrapper; template void Ref(const T&&) = delete; template FORCEINLINE constexpr TReferenceWrapper Ref(T& InValue) { return TReferenceWrapper(InValue); } template FORCEINLINE constexpr TReferenceWrapper Ref(TReferenceWrapper InValue) { return Ref(InValue.Get()); } template FORCEINLINE constexpr TReferenceWrapper Ref(const T& InValue) { return TReferenceWrapper(InValue); } template FORCEINLINE constexpr TReferenceWrapper Ref(TReferenceWrapper InValue) { return Ref(InValue.Get()); } NAMESPACE_PRIVATE_BEGIN template struct TIsTReferenceWrapperImpl : FFalse { }; template struct TIsTReferenceWrapperImpl> : FTrue { }; template struct TUnwrapReferenceImpl { using Type = T; }; template struct TUnwrapReferenceImpl> { using Type = T&; }; template struct TUnwrapRefDecayImpl { using Type = typename TUnwrapReferenceImpl>::Type; }; NAMESPACE_PRIVATE_END template concept CTReferenceWrapper = NAMESPACE_PRIVATE::TIsTReferenceWrapperImpl>::Value; template using TUnwrapReference = typename NAMESPACE_PRIVATE::TUnwrapReferenceImpl::Type; template using TUnwrapRefDecay = typename NAMESPACE_PRIVATE::TUnwrapRefDecayImpl::Type; NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END