#ifndef ARBUTILS___BORROWEDPTR_HPP #define ARBUTILS___BORROWEDPTR_HPP #include <cstddef> #include <memory> #include "../Ensure.hpp" namespace ArbUt { /// @brief A borrowed pointer is used to indicate a pointer that is not owned by its holder. As with all Arbutils /// pointers, this cannot be assigned null. Use an OptionalBorrowedPtr for pointers that can be null. /// @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 T> class BorrowedPtr { private: T* _raw; public: inline BorrowedPtr<T>() {} /// @brief Initialise a BorrowedPtr with a specific raw pointer. inline BorrowedPtr<T>(T* ptr) : _raw(ptr) { EnsureNotNull(ptr); }; /// @brief Initialise a BorrowedPtr from a copy. inline BorrowedPtr<T>(const BorrowedPtr<T>& other) : _raw(other._raw){}; /// @brief Initialise a BorrowedPtr with a std unique_ptr. inline BorrowedPtr<T>(const std::unique_ptr<T>& other) : _raw(other.get()){}; #if !WINDOWS // This doesn't work on mingw-w64 for some reason BorrowedPtr<T>(std::nullptr_t) = delete; #endif ~BorrowedPtr() noexcept = default; /// @brief Copy operator. inline BorrowedPtr<T>& operator=(const BorrowedPtr<T>& rhs) { if (this == &rhs) { return *this; } _raw = rhs._raw; return *this; } /// @brief Assign operator with raw pointer. inline BorrowedPtr<T>& operator=(T* rhs) { if (_raw == rhs) { return *this; } EnsureNotNull(rhs); _raw = rhs; return *this; } /// @brief Don't allow nullptr assignments inline BorrowedPtr<T>& operator=(std::nullptr_t) = delete; /// @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 noexcept { 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<T>& rhs) const noexcept { return _raw == rhs._raw; } /// @brief Check equality of pointers inline bool operator==(T* rhs) const noexcept { return _raw == rhs; } /// @brief Delete comparison with nullptr, BorrowedPtr can't be null inline bool operator==(std::nullptr_t) const = delete; /// @brief Check equality of two BorrowedPtr objects inline bool operator!=(const BorrowedPtr<T>& rhs) const noexcept { return _raw != rhs._raw; } /// @brief Check equality of pointers inline bool operator!=(T* rhs) const noexcept { return _raw != rhs; } /// @brief Delete comparison with nullptr, BorrowedPtr can't be null inline bool operator!=(std::nullptr_t) const = delete; /// @brief Returns a const version of the underlying pointer. inline BorrowedPtr<const T> Const() const noexcept { return BorrowedPtr<const T>(_raw); } /// @brief Casts the underlying pointer to another type using dynamic_cast. template <class TCast> inline BorrowedPtr<TCast> As() const { auto cast = dynamic_cast<TCast*>(_raw); return BorrowedPtr<TCast>(cast); } /// @brief Try to cast the underlying pointer to another type using dynamic_cast. template <class TCast> inline bool TryAs(BorrowedPtr<TCast>& out) const noexcept { auto cast = dynamic_cast<TCast*>(_raw); if (cast == nullptr) return false; out = BorrowedPtr<TCast>(cast); return true; } /// @brief Force cast the underlying pointer to another type using reinterpret_cast. template <class TCast> inline BorrowedPtr<TCast> ForceAs() const noexcept { auto cast = reinterpret_cast<TCast*>(_raw); return BorrowedPtr<TCast>(cast); } /// @brief Implicit cast to retrieve raw pointer. inline operator T*() const noexcept { return _raw; } }; } namespace std { /// @brief Helper class for allowing hashing of BorrowedPtr. template <class T> struct hash<ArbUt::BorrowedPtr<T>> { /// @brief Returns a hash of for a borrowed Pointer. Effectively just the raw memory address. /// @param k A borrowed pointer. /// @return The hash of the borrowed pointer. std::size_t operator()(const ArbUt::BorrowedPtr<T>& k) const { return (size_t)k.GetRaw(); } }; } #endif // ARBUTILS___BORROWEDPTR_HPP