ObjectHandle: Fix handling of <T>

This commit is contained in:
Jérôme Leclercq 2021-03-19 09:55:36 +01:00
parent 8ec11d6193
commit 48ab2a4b04
4 changed files with 99 additions and 15 deletions

View File

@ -37,7 +37,10 @@ namespace Nz
HandledObject(HandledObject&& object) noexcept; HandledObject(HandledObject&& object) noexcept;
~HandledObject(); ~HandledObject();
ObjectHandle<T> CreateHandle(); template<typename U = T>
ObjectHandle<U> CreateHandle();
std::shared_ptr<const Detail::HandleData> GetHandleData();
HandledObject& operator=(const HandledObject& object); HandledObject& operator=(const HandledObject& object);
HandledObject& operator=(HandledObject&& object) noexcept; HandledObject& operator=(HandledObject&& object) noexcept;
@ -48,7 +51,6 @@ namespace Nz
void UnregisterAllHandles() noexcept; void UnregisterAllHandles() noexcept;
private: private:
std::shared_ptr<const Detail::HandleData> GetHandleData();
void InitHandleData(); void InitHandleData();
std::shared_ptr<Detail::HandleData> m_handleData; std::shared_ptr<Detail::HandleData> m_handleData;

View File

@ -58,9 +58,20 @@ namespace Nz
* \return ObjectHandle to this * \return ObjectHandle to this
*/ */
template<typename T> template<typename T>
ObjectHandle<T> HandledObject<T>::CreateHandle() template<typename U>
ObjectHandle<U> HandledObject<T>::CreateHandle()
{ {
return ObjectHandle<T>(static_cast<T*>(this)); static_assert(std::is_base_of_v<T, U>, "Cannot retrieve a handle for a non-related class");
return ObjectHandle<U>(static_cast<U*>(this));
}
template<typename T>
std::shared_ptr<const Detail::HandleData> HandledObject<T>::GetHandleData()
{
if (!m_handleData)
InitHandleData();
return std::shared_ptr<const Detail::HandleData>(m_handleData);
} }
/*! /*!
@ -112,15 +123,6 @@ namespace Nz
} }
} }
template<typename T>
std::shared_ptr<const Detail::HandleData> HandledObject<T>::GetHandleData()
{
if (!m_handleData)
InitHandleData();
return std::shared_ptr<const Detail::HandleData>(m_handleData);
}
template<typename T> template<typename T>
void HandledObject<T>::InitHandleData() void HandledObject<T>::InitHandleData()
{ {

View File

@ -22,6 +22,8 @@ namespace Nz
public: public:
ObjectHandle(); ObjectHandle();
explicit ObjectHandle(T* object); explicit ObjectHandle(T* object);
template<typename U> ObjectHandle(const ObjectHandle<U>& ref);
template<typename U> ObjectHandle(ObjectHandle<U>&& ref);
ObjectHandle(const ObjectHandle& handle) = default; ObjectHandle(const ObjectHandle& handle) = default;
ObjectHandle(ObjectHandle&& handle) noexcept; ObjectHandle(ObjectHandle&& handle) noexcept;
~ObjectHandle(); ~ObjectHandle();
@ -78,6 +80,11 @@ namespace Nz
template<typename T> bool operator>=(const T& lhs, const ObjectHandle<T>& rhs); template<typename T> bool operator>=(const T& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator>=(const ObjectHandle<T>& lhs, const T& rhs); template<typename T> bool operator>=(const ObjectHandle<T>& lhs, const T& rhs);
template<typename T, typename U> ObjectHandle<T> ConstRefCast(const ObjectHandle<U>& ref);
template<typename T, typename U> ObjectHandle<T> DynamicRefCast(const ObjectHandle<U>& ref);
template<typename T, typename U> ObjectHandle<T> ReinterpretRefCast(const ObjectHandle<U>& ref);
template<typename T, typename U> ObjectHandle<T> StaticRefCast(const ObjectHandle<U>& ref);
template<typename T> struct PointedType<ObjectHandle<T>> { using type = T; }; template<typename T> struct PointedType<ObjectHandle<T>> { using type = T; };
template<typename T> struct PointedType<const ObjectHandle<T>> { using type = T; }; template<typename T> struct PointedType<const ObjectHandle<T>> { using type = T; };
} }

View File

@ -26,15 +26,34 @@ namespace Nz
{ {
} }
template<typename T>
template<typename U>
ObjectHandle<T>::ObjectHandle(const ObjectHandle<U>& ref) :
m_handleData(ref.m_handleData)
{
static_assert(std::is_base_of_v<T, U>, "Can only implicitly convert from a derived to a base");
}
template<typename T>
template<typename U>
ObjectHandle<T>::ObjectHandle(ObjectHandle<U>&& ref) :
m_handleData(std::move(ref.m_handleData))
{
ref.m_handleData = Detail::HandleData::GetEmptyObject();
static_assert(std::is_base_of_v<T, U>, "Can only implicitly convert from a derived to a base");
}
/*! /*!
* \brief Constructs a ObjectHandle object by move semantic * \brief Constructs a ObjectHandle object by move semantic
* *
* \param handle ObjectHandle to move into this * \param handle ObjectHandle to move into this
*/ */
template<typename T> template<typename T>
ObjectHandle<T>::ObjectHandle(ObjectHandle&& handle) noexcept ObjectHandle<T>::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); 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<typename T, typename U>
ObjectHandle<T> ConstRefCast(const ObjectHandle<U>& ref)
{
return ObjectHandle<T>(const_cast<T*>(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<typename T, typename U>
ObjectHandle<T> DynamicRefCast(const ObjectHandle<U>& ref)
{
return ObjectHandle<T>(dynamic_cast<T*>(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<typename T, typename U>
ObjectHandle<T> ReinterpretRefCast(const ObjectHandle<U>& ref)
{
return ObjectHandle<T>(static_cast<T*>(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<typename T, typename U>
ObjectHandle<T> StaticRefCast(const ObjectHandle<U>& ref)
{
return ObjectHandle<T>(static_cast<T*>(ref.GetObject()));
}
template<typename T> template<typename T>
const ObjectHandle<T> ObjectHandle<T>::InvalidHandle; const ObjectHandle<T> ObjectHandle<T>::InvalidHandle;
} }