#ifndef ARBUTILS_BORROWEDPTR_HPP #define ARBUTILS_BORROWEDPTR_HPP #include #include "../Assert.hpp" namespace ArbUt { /// @brief A borrowed pointer is used to indicate a pointer that is not owned by its holder. /// @details 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 BorrowedPtr { private: T* _raw; public: /// @brief Initialise a BorrowedPtr with a null pointer. inline BorrowedPtr() noexcept : _raw(nullptr){}; /// @brief Initialise a BorrowedPtr with a specific raw pointer. inline BorrowedPtr(T* ptr) noexcept : _raw(ptr){}; /// @brief Initialise a BorrowedPtr from a copy. inline BorrowedPtr(const BorrowedPtr& other) noexcept : _raw(other._raw){}; /// @brief Initialise a BorrowedPtr with a std unique_ptr. inline BorrowedPtr(const std::unique_ptr& other) noexcept : _raw(other.get()){}; ~BorrowedPtr() noexcept = default; /// @brief Copy operator. inline BorrowedPtr& operator=(const BorrowedPtr& rhs) noexcept { if(this == &rhs) return *this; _raw = rhs._raw; return *this; } /// @brief Operator for access into underlying pointer. /// @warning Note that this asserts that the underlying pointer is not null first, to prevent segfaults. inline T* operator->() const { AssertNotNull(_raw); return _raw; } /// @brief Get the raw underlying pointer. inline T* GetRaw() const noexcept { return _raw; } /// @brief Check equality of two BorrowedPtr objects inline bool operator==(const BorrowedPtr& rhs) const noexcept { return _raw == rhs._raw; } /// @brief Check equality of two BorrowedPtr objects inline bool operator!=(const BorrowedPtr& rhs) const noexcept { return _raw != rhs._raw; } /// @brief Returns whether the underlying pointer is a nullptr or not. [[nodiscard]] inline constexpr bool IsNull() const noexcept { return _raw == nullptr; } /// @brief Returns a const version of the underlying pointer. inline BorrowedPtr Const() const noexcept { return BorrowedPtr(_raw); } /// @brief Casts the underlying pointer to another type using dynamic_cast. template inline BorrowedPtr As() const { auto cast = dynamic_cast(_raw); return BorrowedPtr(cast); } /// @brief Try to cast the underlying pointer to another type using dynamic_cast. template inline bool TryAs(BorrowedPtr& out) const noexcept { auto cast = dynamic_cast(_raw); if (cast == nullptr) return false; out = BorrowedPtr(cast); return true; } /// @brief Force cast the underlying pointer to another type using reinterpret_cast. template inline BorrowedPtr ForceAs() const noexcept { auto cast = reinterpret_cast(_raw); return BorrowedPtr(cast); } }; } namespace std { /// @brief Helper class for allowing hashing of BorrowedPtr. template struct hash> { std::size_t operator()(const ArbUt::BorrowedPtr& k) const { return (size_t)k.GetRaw(); } }; } #endif // ARBUTILS_BORROWEDPTR_HPP