// Copyright (C) 2021 Jérôme "Lynix" Leclercq (lynix680@gmail.com) // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include #include namespace Nz { /*! * \ingroup core * \class Nz::ObjectHandle * \brief Core class that represents a object handle */ /*! * \brief Constructs a ObjectHandle object with a pointer to an object * * \param object Pointer to handle like an object (can be nullptr) */ template ObjectHandle::ObjectHandle() : m_handleData(Detail::HandleData::GetEmptyObject()) { } template template ObjectHandle::ObjectHandle(const ObjectHandle& ref) : m_handleData(ref.m_handleData) { static_assert(std::is_base_of::value, "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::value, "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 : m_handleData(std::move(handle.m_handleData)) { handle.m_handleData = Detail::HandleData::GetEmptyObject(); } /*! * \brief Constructs a ObjectHandle object with a pointer to an object * * \param object Pointer to handle like an object (can be nullptr) */ template ObjectHandle::ObjectHandle(T* object) { Reset(object); } /*! * \brief Destructs the object and calls reset with nullptr * * \see Reset */ template ObjectHandle::~ObjectHandle() { Reset(nullptr); } /*! * \brief Gets the underlying object * \return Underlying object */ template T* ObjectHandle::GetObject() const { return static_cast(m_handleData->object); } /*! * \brief Checks whether the object is valid * \return true if object is not nullptr */ template bool ObjectHandle::IsValid() const { return m_handleData->object != nullptr; } /*! * \brief Resets the content of the ObjectHandle with another object * * \param object Object to handle */ template void ObjectHandle::Reset(T* object) { if (object) m_handleData = object->GetHandleData(); else m_handleData = Detail::HandleData::GetEmptyObject(); } /*! * \brief Resets the content of this with another object * * \param handle New object to handle */ template void ObjectHandle::Reset(const ObjectHandle& handle) { m_handleData = handle.m_handleData; } /*! * \brief Resets the content of this with another object by move semantic * * \param handle New object to handle to move into this */ template void ObjectHandle::Reset(ObjectHandle&& handle) noexcept { m_handleData = std::move(handle.m_handleData); handle.m_handleData = Detail::HandleData::GetEmptyObject(); } /*! * \brief Swaps the content of the two ObjectHandle * \return A reference to this * * \param handle ObjectHandle to swap */ template ObjectHandle& ObjectHandle::Swap(ObjectHandle& handle) { // We do the swap std::swap(m_handleData, handle.m_handleData); return *this; } /*! * \brief Gives a string representation * \return A string representation of the object "ObjectHandle(object representation) or Null" */ template std::string ObjectHandle::ToString() const { std::ostringstream ss; ss << *this; return ss.str(); } /*! * \brief Converts the ObjectHandle to bool * \return true if reference is not nullptr * * \see IsValid */ template ObjectHandle::operator bool() const { return IsValid(); } /*! * \brief Dereferences the ObjectHandle * \return Underlying pointer */ template ObjectHandle::operator T*() const { return GetObject(); } /*! * \brief Dereferences the ObjectHandle * \return Underlying pointer */ template T* ObjectHandle::operator->() const { return GetObject(); } /*! * \brief Assigns the entity into this * \return A reference to this * * \param entity Pointer to handle like an object (can be nullptr) */ template ObjectHandle& ObjectHandle::operator=(T* object) { Reset(object); return *this; } /*! * \brief Moves the ObjectHandle into this * \return A reference to this * * \param handle ObjectHandle to move in this */ template ObjectHandle& ObjectHandle::operator=(ObjectHandle&& handle) noexcept { Reset(std::move(handle)); return *this; } /*! * \brief Output operator * \return The stream * * \param out The stream * \param handle The ObjectHandle to output */ template std::ostream& operator<<(std::ostream& out, const ObjectHandle& handle) { out << "ObjectHandle("; if (handle.IsValid()) out << handle->ToString(); else out << "Null"; out << ')'; return out; } /*! * \brief Checks whether the first object handle is equal to the second object handle * \return true if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator==(const ObjectHandle& lhs, const ObjectHandle& rhs) { return lhs.GetObject() == rhs.GetObject(); } /*! * \brief Checks whether the object is equal to the second object handle * \return true if it is the case * * \param lhs Object to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator==(const T& lhs, const ObjectHandle& rhs) { return &lhs == rhs.GetObject(); } /*! * \brief Checks whether the object handle is equal to the second object * \return true if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs Object to compare in right hand side */ template bool operator==(const ObjectHandle& lhs, const T& rhs) { return lhs.GetObject() == &rhs; } /*! * \brief Checks whether the first object handle is equal to the second object handle * \return false if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator!=(const ObjectHandle& lhs, const ObjectHandle& rhs) { return !(lhs == rhs); } /*! * \brief Checks whether the object is equal to the second object handle * \return false if it is the case * * \param lhs Object to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator!=(const T& lhs, const ObjectHandle& rhs) { return !(lhs == rhs); } /*! * \brief Checks whether the object handle is equal to the second object * \return false if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs Object to compare in right hand side */ template bool operator!=(const ObjectHandle& lhs, const T& rhs) { return !(lhs == rhs); } /*! * \brief Checks whether the first object handle is less than the second object handle * \return true if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator<(const ObjectHandle& lhs, const ObjectHandle& rhs) { return lhs.GetObject() < rhs.GetObject(); } /*! * \brief Checks whether the first object handle is less than the second object handle * \return true if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator<(const T& lhs, const ObjectHandle& rhs) { return &lhs < rhs.GetObject(); } /*! * \brief Checks whether the first object handle is less than the second object handle * \return true if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator<(const ObjectHandle& lhs, const T& rhs) { return lhs.GetObject() < &rhs; } /*! * \brief Checks whether the first object handle is less or equal than the second object handle * \return true if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator<=(const ObjectHandle& lhs, const ObjectHandle& rhs) { return !(lhs > rhs); } /*! * \brief Checks whether the first object handle is less or equal than the second object handle * \return true if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator<=(const T& lhs, const ObjectHandle& rhs) { return !(lhs > rhs); } /*! * \brief Checks whether the first object handle is less or equal than the second object handle * \return true if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator<=(const ObjectHandle& lhs, const T& rhs) { return !(lhs > rhs); } /*! * \brief Checks whether the first object handle is greather than the second object handle * \return true if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator>(const ObjectHandle& lhs, const ObjectHandle& rhs) { return rhs < lhs; } /*! * \brief Checks whether the first object handle is greather than the second object handle * \return true if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator>(const T& lhs, const ObjectHandle& rhs) { return rhs < lhs; } /*! * \brief Checks whether the first object handle is greather than the second object handle * \return true if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator>(const ObjectHandle& lhs, const T& rhs) { return rhs < lhs; } /*! * \brief Checks whether the first object handle is greather or equal than the second object handle * \return true if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator>=(const ObjectHandle& lhs, const ObjectHandle& rhs) { return !(lhs < rhs); } /*! * \brief Checks whether the first object handle is greather or equal than the second object handle * \return true if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator>=(const T& lhs, const ObjectHandle& rhs) { return !(lhs < rhs); } /*! * \brief Checks whether the first object handle is greather or equal than the second object handle * \return true if it is the case * * \param lhs ObjectHandle to compare in left hand side * \param rhs ObjectHandle to compare in right hand side */ template bool operator>=(const ObjectHandle& lhs, const T& 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 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; } namespace std { /*! * \brief Swaps two ObjectHandle, specialisation of std * * \param lhs First object handle * \param rhs Second object handle */ template void swap(Nz::ObjectHandle& lhs, Nz::ObjectHandle& rhs) { lhs.Swap(rhs); } } #include