#pragma once #include "CoreTypes.h" #include "Templates/Utility.h" #include "Templates/TypeHash.h" #include "Memory/PointerTraits.h" #include "TypeTraits/TypeTraits.h" #include "Miscellaneous/Compare.h" NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) template requires (CObject && !CBoundedArray) class TObserverPtr; NAMESPACE_PRIVATE_BEGIN template struct TIsTObserverPtr : FFalse { }; template struct TIsTObserverPtr> : FTrue { }; NAMESPACE_PRIVATE_END template concept CTObserverPtr = NAMESPACE_PRIVATE::TIsTObserverPtr>::Value; template requires (CObject && !CBoundedArray) class TObserverPtr { public: using ElementType = T; FORCEINLINE constexpr TObserverPtr() : Pointer(nullptr) { } FORCEINLINE constexpr TObserverPtr(nullptr_t) : TObserverPtr() { } FORCEINLINE constexpr explicit TObserverPtr(T* InPtr) : Pointer(InPtr) { } FORCEINLINE constexpr TObserverPtr(const TObserverPtr&) = default; FORCEINLINE constexpr TObserverPtr(TObserverPtr&&) = default; template requires (CConvertibleTo && !CArray) FORCEINLINE constexpr TObserverPtr(TObserverPtr InValue) : Pointer(InValue.Pointer) { } FORCEINLINE constexpr ~TObserverPtr() = default; FORCEINLINE constexpr TObserverPtr& operator=(const TObserverPtr&) = default; FORCEINLINE constexpr TObserverPtr& operator=(TObserverPtr&&) = default; NODISCARD friend FORCEINLINE constexpr bool operator==(const TObserverPtr& LHS, const TObserverPtr& RHS) { return LHS.Get() == RHS.Get(); } NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TObserverPtr& LHS, const TObserverPtr& RHS) { return LHS.Get() <=> RHS.Get(); } NODISCARD FORCEINLINE constexpr bool operator==(T* InPtr) const& { return Get() == InPtr; } NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(T* InPtr) const& { return Get() <=> InPtr; } NODISCARD FORCEINLINE constexpr T* Release() { return Exchange(Pointer, nullptr); } FORCEINLINE constexpr void Reset(T* InPtr = nullptr) { Pointer = InPtr; } NODISCARD FORCEINLINE constexpr T* Get() const { return Pointer; } NODISCARD FORCEINLINE constexpr bool IsValid() const { return Get() != nullptr; } NODISCARD FORCEINLINE constexpr explicit operator bool() const { return Get() != nullptr; } NODISCARD FORCEINLINE constexpr T& operator*() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return *Get(); } NODISCARD FORCEINLINE constexpr T* operator->() const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get(); } NODISCARD FORCEINLINE constexpr explicit operator ElementType*() const { return Get(); } NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(const TObserverPtr& A) { return GetTypeHash(A.Get()); } friend FORCEINLINE constexpr void Swap(TObserverPtr& A, TObserverPtr& B) { Swap(A.Pointer, B.Pointer); } private: T* Pointer; template requires (CObject && !CBoundedArray) friend class TObserverPtr; }; template class TObserverPtr { public: using ElementType = T; FORCEINLINE constexpr TObserverPtr() : Pointer(nullptr) { } FORCEINLINE constexpr TObserverPtr(nullptr_t) : TObserverPtr() { } template requires (CPointer && CConvertibleTo(*)[], T(*)[]>) FORCEINLINE constexpr explicit TObserverPtr(U InPtr) : Pointer(InPtr) { } FORCEINLINE constexpr TObserverPtr(const TObserverPtr&) = default; FORCEINLINE constexpr TObserverPtr(TObserverPtr&&) = default; template requires (CConvertibleTo(*)[], T(*)[]> && CArray) FORCEINLINE constexpr TObserverPtr(TObserverPtr InValue) : Pointer(InValue.Pointer) { } FORCEINLINE constexpr ~TObserverPtr() = default; FORCEINLINE constexpr TObserverPtr& operator=(const TObserverPtr&) = default; FORCEINLINE constexpr TObserverPtr& operator=(TObserverPtr&&) = default; NODISCARD friend FORCEINLINE constexpr bool operator==(const TObserverPtr& LHS, const TObserverPtr& RHS) { return LHS.Get() == RHS.Get(); } NODISCARD friend FORCEINLINE constexpr strong_ordering operator<=>(const TObserverPtr& LHS, const TObserverPtr& RHS) { return LHS.Get() <=> RHS.Get(); } template requires (CNullPointer || (CPointer && CConvertibleTo(*)[], T(*)[]>)) NODISCARD FORCEINLINE constexpr bool operator==(U InPtr) const& { return Get() == InPtr; } template requires (CNullPointer || (CPointer && CConvertibleTo(*)[], T(*)[]>)) NODISCARD FORCEINLINE constexpr strong_ordering operator<=>(U InPtr) const& { return Get() <=> InPtr; } NODISCARD FORCEINLINE constexpr T* Release() { return Exchange(Pointer, nullptr); } template requires (CNullPointer || (CPointer && CConvertibleTo(*)[], T(*)[]>)) FORCEINLINE constexpr void Reset(U InPtr = nullptr) { Pointer = InPtr; } NODISCARD FORCEINLINE constexpr T* Get() const { return Pointer; } NODISCARD FORCEINLINE constexpr bool IsValid() const { return Get() != nullptr; } NODISCARD FORCEINLINE constexpr explicit operator bool() const { return Get() != nullptr; } NODISCARD FORCEINLINE constexpr T& operator[](size_t Index) const { checkf(IsValid(), TEXT("Read access violation. Please check IsValid().")); return Get()[Index]; } NODISCARD FORCEINLINE constexpr explicit operator ElementType*() const { return Get(); } NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash(const TObserverPtr& A) { return GetTypeHash(A.Get()); } friend FORCEINLINE constexpr void Swap(TObserverPtr& A, TObserverPtr& B) { Swap(A.Pointer, B.Pointer); } private: T* Pointer; template requires (CObject && !CBoundedArray) friend class TObserverPtr; }; template requires (CObject && !CBoundedArray) NODISCARD FORCEINLINE constexpr TObserverPtr MakeObserver(TRemoveExtent* InPtr) { return TObserverPtr(InPtr); } DEFINE_TPointerTraits(TObserverPtr); NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END