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

View File

@ -58,9 +58,20 @@ namespace Nz
* \return ObjectHandle to this
*/
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>
void HandledObject<T>::InitHandleData()
{

View File

@ -22,6 +22,8 @@ namespace Nz
public:
ObjectHandle();
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(ObjectHandle&& handle) noexcept;
~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 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<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
*
* \param handle ObjectHandle to move into this
*/
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);
}
/*!
* \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>
const ObjectHandle<T> ObjectHandle<T>::InvalidHandle;
}