#ifndef ARBUTILS_BORROWED_PTR_HPP #define ARBUTILS_BORROWED_PTR_HPP #include namespace ArbUt::Memory { /// A borrowed pointer is used to indicate a pointer that is not owned by an object, but instead borrowed from /// another owning object that is assumed to always be kept alive during the entire lifetime of the borrowing /// object. template class borrowed_ptr { private: T* _raw; public: inline borrowed_ptr() : _raw(nullptr){}; inline borrowed_ptr(T* ptr) : _raw(ptr){}; inline borrowed_ptr(const borrowed_ptr& other) : _raw(other._raw){}; inline borrowed_ptr(const std::unique_ptr& other) : _raw(other.get()){}; ~borrowed_ptr() = default; inline borrowed_ptr& operator=(const borrowed_ptr& rhs) { _raw = rhs._raw; return *this; } inline T* operator->() const noexcept { return _raw; } inline T* GetRaw() const noexcept { return _raw; } inline bool operator==(const borrowed_ptr& rhs) const { return _raw == rhs._raw; } inline bool operator!=(const borrowed_ptr& rhs) const { return _raw != rhs._raw; } [[nodiscard]] inline constexpr bool IsNull() const noexcept { return _raw == nullptr; } template inline borrowed_ptr As() const { auto cast = dynamic_cast(_raw); return borrowed_ptr(cast); } template inline bool TryAs(borrowed_ptr& out) const { auto cast = dynamic_cast(_raw); if (cast == nullptr) return false; out = borrowed_ptr(cast); return true; } template inline borrowed_ptr ForceAs() const { auto cast = reinterpret_cast(_raw); return borrowed_ptr(cast); } }; } #endif // ARBUTILS_BORROWED_PTR_HPP