// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Misc/AssertionMacros.h" #include #include template struct TRelativePtr { static constexpr OffsetType NullValue = std::numeric_limits::max(); static_assert(std::is_integral_v, "Offset type must be a signed integer"); explicit TRelativePtr() : Offset(NullValue) {} explicit TRelativePtr(nullptr_t) : Offset(NullValue) {} explicit TRelativePtr(const void* BasePtr, const void* ThisPtr) { Reset(BasePtr, ThisPtr); } explicit operator bool() const { return Offset != NullValue; } T* Resolve(const void* BasePtr) const { return Offset == NullValue ? nullptr : reinterpret_cast(static_cast(const_cast(BasePtr)) + Offset); } template U* Resolve(const void* BasePtr) const { return static_cast(Resolve(BasePtr)); } void Reset(nullptr_t) { Offset = NullValue; } void Reset(const void* BasePtr, const void* ThisPtr) { const uintptr_t Base = reinterpret_cast(BasePtr); const uintptr_t This = reinterpret_cast(ThisPtr); if (This >= Base) { const uintptr_t OffsetPtr = This - Base; checkf(OffsetPtr >= 0 && OffsetPtr < std::numeric_limits::max(), TEXT("Attempting to create a relative pointer outside the bounds of its capacity.")); Offset = static_cast(OffsetPtr); } else if constexpr (std::is_signed_v) { const uintptr_t OffsetPtr = Base - This; checkf(OffsetPtr >= 0 && OffsetPtr < std::numeric_limits::max(), TEXT("Attempting to create a relative pointer outside the bounds of its capacity.")); Offset = -static_cast(OffsetPtr); } else { checkf(false, TEXT("Attempting to assign a negative offset to an unsigned relative pointer!!")); } } private: OffsetType Offset; };