diff --git a/include/Nazara/Core/HandledObject.hpp b/include/Nazara/Core/HandledObject.hpp index 390a4e612..c2bd59d0c 100644 --- a/include/Nazara/Core/HandledObject.hpp +++ b/include/Nazara/Core/HandledObject.hpp @@ -37,7 +37,10 @@ namespace Nz HandledObject(HandledObject&& object) noexcept; ~HandledObject(); - ObjectHandle CreateHandle(); + template + ObjectHandle CreateHandle(); + + std::shared_ptr GetHandleData(); HandledObject& operator=(const HandledObject& object); HandledObject& operator=(HandledObject&& object) noexcept; @@ -48,7 +51,6 @@ namespace Nz void UnregisterAllHandles() noexcept; private: - std::shared_ptr GetHandleData(); void InitHandleData(); std::shared_ptr m_handleData; diff --git a/include/Nazara/Core/HandledObject.inl b/include/Nazara/Core/HandledObject.inl index ed0115f5b..8f1e497a0 100644 --- a/include/Nazara/Core/HandledObject.inl +++ b/include/Nazara/Core/HandledObject.inl @@ -58,9 +58,20 @@ namespace Nz * \return ObjectHandle to this */ template - ObjectHandle HandledObject::CreateHandle() + template + ObjectHandle HandledObject::CreateHandle() { - return ObjectHandle(static_cast(this)); + static_assert(std::is_base_of_v, "Cannot retrieve a handle for a non-related class"); + return ObjectHandle(static_cast(this)); + } + + template + std::shared_ptr HandledObject::GetHandleData() + { + if (!m_handleData) + InitHandleData(); + + return std::shared_ptr(m_handleData); } /*! @@ -112,15 +123,6 @@ namespace Nz } } - template - std::shared_ptr HandledObject::GetHandleData() - { - if (!m_handleData) - InitHandleData(); - - return std::shared_ptr(m_handleData); - } - template void HandledObject::InitHandleData() { diff --git a/include/Nazara/Core/ObjectHandle.hpp b/include/Nazara/Core/ObjectHandle.hpp index e2e72f185..6d62dc582 100644 --- a/include/Nazara/Core/ObjectHandle.hpp +++ b/include/Nazara/Core/ObjectHandle.hpp @@ -22,6 +22,8 @@ namespace Nz public: ObjectHandle(); explicit ObjectHandle(T* object); + template ObjectHandle(const ObjectHandle& ref); + template ObjectHandle(ObjectHandle&& ref); ObjectHandle(const ObjectHandle& handle) = default; ObjectHandle(ObjectHandle&& handle) noexcept; ~ObjectHandle(); @@ -78,6 +80,11 @@ namespace Nz template bool operator>=(const T& lhs, const ObjectHandle& rhs); template bool operator>=(const ObjectHandle& lhs, const T& rhs); + template ObjectHandle ConstRefCast(const ObjectHandle& ref); + template ObjectHandle DynamicRefCast(const ObjectHandle& ref); + template ObjectHandle ReinterpretRefCast(const ObjectHandle& ref); + template ObjectHandle StaticRefCast(const ObjectHandle& ref); + template struct PointedType> { using type = T; }; template struct PointedType> { using type = T; }; } diff --git a/include/Nazara/Core/ObjectHandle.inl b/include/Nazara/Core/ObjectHandle.inl index fc43fdffe..1a3d09b9b 100644 --- a/include/Nazara/Core/ObjectHandle.inl +++ b/include/Nazara/Core/ObjectHandle.inl @@ -26,15 +26,34 @@ namespace Nz { } + template + template + ObjectHandle::ObjectHandle(const ObjectHandle& ref) : + m_handleData(ref.m_handleData) + { + static_assert(std::is_base_of_v, "Can only implicitly convert from a derived to a base"); + } + + template + template + ObjectHandle::ObjectHandle(ObjectHandle&& ref) : + m_handleData(std::move(ref.m_handleData)) + { + ref.m_handleData = Detail::HandleData::GetEmptyObject(); + + static_assert(std::is_base_of_v, "Can only implicitly convert from a derived to a base"); + } + /*! * \brief Constructs a ObjectHandle object by move semantic * * \param handle ObjectHandle to move into this */ template - ObjectHandle::ObjectHandle(ObjectHandle&& handle) noexcept + ObjectHandle::ObjectHandle(ObjectHandle&& handle) noexcept : + m_handleData(std::move(handle.m_handleData)) { - Reset(std::move(handle)); + handle.m_handleData = Detail::HandleData::GetEmptyObject(); } /*! @@ -457,6 +476,60 @@ namespace Nz return !(lhs < rhs); } + /*! + * \brief Casts an ObjectHandle from one type to another using static_cast + * \return Reference to the casted object + * + * \param ref The reference to convert + * + * \remark It is an undefined behavior to cast between incompatible types + */ + template + ObjectHandle ConstRefCast(const ObjectHandle& ref) + { + return ObjectHandle(const_cast(ref.GetObject())); + } + + /*! + * \brief Casts an ObjectHandle from one type to another using static_cast + * \return Reference to the casted object + * + * \param ref The reference to convert + */ + template + ObjectHandle DynamicRefCast(const ObjectHandle& ref) + { + return ObjectHandle(dynamic_cast(ref.GetObject())); + } + + /*! + * \brief Casts an ObjectHandle from one type to another using static_cast + * \return Reference to the casted object + * + * \param ref The reference to convert + * + * \remark It is an undefined behavior to cast between incompatible types + */ + template + ObjectHandle ReinterpretRefCast(const ObjectHandle& ref) + { + return ObjectHandle(static_cast(ref.GetObject())); + } + + /*! + * \brief Casts an ObjectHandle from one type to another using static_cast + * \return Reference to the casted object + * + * \param ref The reference to convert + * + * \remark It is an undefined behavior to cast between incompatible types + */ + template + ObjectHandle StaticRefCast(const ObjectHandle& ref) + { + return ObjectHandle(static_cast(ref.GetObject())); + } + template const ObjectHandle ObjectHandle::InvalidHandle; }