562 lines
13 KiB
C++
562 lines
13 KiB
C++
// 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 <Nazara/Core/ObjectRef.hpp>
|
|
#include <Nazara/Core/Initializer.hpp>
|
|
#include <Nazara/Core/Debug.hpp>
|
|
|
|
namespace Nz
|
|
{
|
|
/*!
|
|
* \ingroup core
|
|
* \class Nz::ObjectRef
|
|
* \brief Core class that represents a reference to an object
|
|
*/
|
|
|
|
/*!
|
|
* \brief Constructs a ObjectRef object by default
|
|
*/
|
|
template<typename T>
|
|
ObjectRef<T>::ObjectRef() :
|
|
m_object(nullptr)
|
|
{
|
|
}
|
|
|
|
/*!
|
|
* \brief Constructs a ObjectRef object with a pointer to an object
|
|
*
|
|
* \param object Pointer to handle like a reference (can be nullptr)
|
|
*/
|
|
template<typename T>
|
|
ObjectRef<T>::ObjectRef(T* object) :
|
|
m_object(object)
|
|
{
|
|
if (m_object)
|
|
m_object->AddReference();
|
|
}
|
|
|
|
/*!
|
|
* \brief Constructs a ObjectRef object by assignation
|
|
*
|
|
* \param ref ObjectRef to assign into this
|
|
*/
|
|
template<typename T>
|
|
ObjectRef<T>::ObjectRef(const ObjectRef& ref) :
|
|
m_object(ref.m_object)
|
|
{
|
|
if (m_object)
|
|
m_object->AddReference();
|
|
}
|
|
|
|
/*!
|
|
* \brief Constructs a ObjectRef<U> object from another type of ObjectRef
|
|
*
|
|
* \param ref ObjectRef of type U to convert to type T
|
|
*/
|
|
template<typename T>
|
|
template<typename U>
|
|
ObjectRef<T>::ObjectRef(const ObjectRef<U>& ref) :
|
|
ObjectRef(ref.Get())
|
|
{
|
|
}
|
|
|
|
/*!
|
|
* \brief Constructs a ObjectRef object by move semantic
|
|
*
|
|
* \param ref ObjectRef to move into this
|
|
*/
|
|
template<typename T>
|
|
ObjectRef<T>::ObjectRef(ObjectRef&& ref) noexcept :
|
|
m_object(ref.m_object)
|
|
{
|
|
ref.m_object = nullptr; // We steal the reference
|
|
}
|
|
|
|
/*!
|
|
* \brief Destructs the object (remove a reference to the object when shared)
|
|
*/
|
|
template<typename T>
|
|
ObjectRef<T>::~ObjectRef()
|
|
{
|
|
if (m_object)
|
|
m_object->RemoveReference();
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the underlying pointer
|
|
* \return Underlying pointer
|
|
*/
|
|
template<typename T>
|
|
T* ObjectRef<T>::Get() const
|
|
{
|
|
return m_object;
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks whether the reference is valid
|
|
* \return true if reference is not nullptr
|
|
*/
|
|
template<typename T>
|
|
bool ObjectRef<T>::IsValid() const
|
|
{
|
|
return m_object != nullptr;
|
|
}
|
|
|
|
/*!
|
|
* \brief Releases the handle of the pointer
|
|
* \return Underlying pointer
|
|
*/
|
|
template<typename T>
|
|
T* ObjectRef<T>::Release()
|
|
{
|
|
if (m_object)
|
|
m_object->RemoveReference();
|
|
|
|
T* object = m_object;
|
|
m_object = nullptr;
|
|
|
|
return object;
|
|
}
|
|
|
|
/*!
|
|
* \brief Resets the content of the ObjectRef with another pointer
|
|
* \return true if old handle is destroyed
|
|
*/
|
|
template<typename T>
|
|
bool ObjectRef<T>::Reset(T* object)
|
|
{
|
|
bool destroyed = false;
|
|
if (m_object != object)
|
|
{
|
|
if (m_object)
|
|
destroyed = m_object->RemoveReference();
|
|
|
|
m_object = object;
|
|
if (m_object)
|
|
m_object->AddReference();
|
|
}
|
|
|
|
return destroyed;
|
|
}
|
|
|
|
/*!
|
|
* \brief Swaps the content of the two ObjectRef
|
|
* \return A reference to this
|
|
*
|
|
* \param ref ObjectRef to swap
|
|
*/
|
|
template<typename T>
|
|
ObjectRef<T>& ObjectRef<T>::Swap(ObjectRef& ref)
|
|
{
|
|
std::swap(m_object, ref.m_object);
|
|
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
* \brief Converts the ObjectRef to bool
|
|
* \return true if reference is not nullptr
|
|
*
|
|
* \see IsValid
|
|
*/
|
|
template<typename T>
|
|
ObjectRef<T>::operator bool() const
|
|
{
|
|
return IsValid();
|
|
}
|
|
|
|
/*!
|
|
* \brief Dereferences the ObjectRef
|
|
* \return Underlying pointer
|
|
*/
|
|
template<typename T>
|
|
ObjectRef<T>::operator T*() const
|
|
{
|
|
return m_object;
|
|
}
|
|
|
|
/*!
|
|
* \brief Dereferences the ObjectRef
|
|
* \return Underlying pointer
|
|
*/
|
|
template<typename T>
|
|
T* ObjectRef<T>::operator->() const
|
|
{
|
|
return m_object;
|
|
}
|
|
|
|
/*!
|
|
* \brief Assigns the object into this
|
|
* \return A reference to this
|
|
*
|
|
* \param object Pointer to handle like a reference (can be nullptr)
|
|
*/
|
|
template<typename T>
|
|
ObjectRef<T>& ObjectRef<T>::operator=(T* object)
|
|
{
|
|
Reset(object);
|
|
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the reference of the ObjectRef with the handle from another
|
|
* \return A reference to this
|
|
*
|
|
* \param ref The other ObjectRef
|
|
*/
|
|
template<typename T>
|
|
ObjectRef<T>& ObjectRef<T>::operator=(const ObjectRef& ref)
|
|
{
|
|
Reset(ref.m_object);
|
|
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the reference of the ObjectRef from another type of ObjectRef
|
|
* \return A reference to this
|
|
*
|
|
* \param ref ObjectRef of type U to convert
|
|
*/
|
|
template<typename T>
|
|
template<typename U>
|
|
ObjectRef<T>& ObjectRef<T>::operator=(const ObjectRef<U>& ref)
|
|
{
|
|
static_assert(std::is_convertible<U*, T*>::value, "U is not implicitly convertible to T");
|
|
|
|
Reset(ref.Get());
|
|
|
|
return *this;
|
|
}
|
|
|
|
/*!
|
|
* \brief Moves the ObjectRef into this
|
|
* \return A reference to this
|
|
*
|
|
* \param ref ObjectRef to move in this
|
|
*/
|
|
template<typename T>
|
|
ObjectRef<T>& ObjectRef<T>::operator=(ObjectRef&& ref) noexcept
|
|
{
|
|
Reset();
|
|
|
|
std::swap(m_object, ref.m_object);
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
/*!
|
|
* \brief Checks whether the first object handle is equal to the second object handle
|
|
* \return true if it is the case
|
|
*
|
|
* \param lhs ObjectRef to compare in left hand side
|
|
* \param rhs ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator==(const ObjectRef<T>& lhs, const ObjectRef<T>& rhs)
|
|
{
|
|
return lhs.Get() == rhs.Get();
|
|
}
|
|
|
|
/*!
|
|
* \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 ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator==(const T& lhs, const ObjectRef<T>& rhs)
|
|
{
|
|
return &lhs == rhs.Get();
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks whether the object handle is equal to the second object
|
|
* \return true if it is the case
|
|
*
|
|
* \param lhs ObjectRef to compare in left hand side
|
|
* \param rhs Object to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator==(const ObjectRef<T>& lhs, const T& rhs)
|
|
{
|
|
return lhs.Get() == &rhs;
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks whether the first object handle is equal to the second object handle
|
|
* \return false if it is the case
|
|
*
|
|
* \param lhs ObjectRef to compare in left hand side
|
|
* \param rhs ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator!=(const ObjectRef<T>& lhs, const ObjectRef<T>& 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 ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator!=(const T& lhs, const ObjectRef<T>& 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 ObjectRef to compare in left hand side
|
|
* \param rhs Object to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator!=(const ObjectRef<T>& 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 ObjectRef to compare in left hand side
|
|
* \param rhs ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator<(const ObjectRef<T>& lhs, const ObjectRef<T>& rhs)
|
|
{
|
|
return lhs.Get() < rhs.Get();
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks whether the first object handle is less than the second object handle
|
|
* \return true if it is the case
|
|
*
|
|
* \param lhs ObjectRef to compare in left hand side
|
|
* \param rhs ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator<(const T& lhs, const ObjectRef<T>& rhs)
|
|
{
|
|
return &lhs < rhs.Get();
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks whether the first object handle is less than the second object handle
|
|
* \return true if it is the case
|
|
*
|
|
* \param lhs ObjectRef to compare in left hand side
|
|
* \param rhs ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator<(const ObjectRef<T>& lhs, const T& rhs)
|
|
{
|
|
return lhs.Get() < &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 ObjectRef to compare in left hand side
|
|
* \param rhs ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator<=(const ObjectRef<T>& lhs, const ObjectRef<T>& 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 ObjectRef to compare in left hand side
|
|
* \param rhs ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator<=(const T& lhs, const ObjectRef<T>& 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 ObjectRef to compare in left hand side
|
|
* \param rhs ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator<=(const ObjectRef<T>& 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 ObjectRef to compare in left hand side
|
|
* \param rhs ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator>(const ObjectRef<T>& lhs, const ObjectRef<T>& 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 ObjectRef to compare in left hand side
|
|
* \param rhs ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator>(const T& lhs, const ObjectRef<T>& 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 ObjectRef to compare in left hand side
|
|
* \param rhs ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator>(const ObjectRef<T>& 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 ObjectRef to compare in left hand side
|
|
* \param rhs ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator>=(const ObjectRef<T>& lhs, const ObjectRef<T>& 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 ObjectRef to compare in left hand side
|
|
* \param rhs ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator>=(const T& lhs, const ObjectRef<T>& 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 ObjectRef to compare in left hand side
|
|
* \param rhs ObjectRef to compare in right hand side
|
|
*/
|
|
template<typename T>
|
|
bool operator>=(const ObjectRef<T>& lhs, const T& rhs)
|
|
{
|
|
return !(lhs < rhs);
|
|
}
|
|
|
|
/*!
|
|
* \brief Casts an ObjectRef 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>
|
|
ObjectRef<T> ConstRefCast(const ObjectRef<U>& ref)
|
|
{
|
|
return ObjectRef<T>(const_cast<T*>(ref.Get()));
|
|
}
|
|
|
|
/*!
|
|
* \brief Casts an ObjectRef 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>
|
|
ObjectRef<T> DynamicRefCast(const ObjectRef<U>& ref)
|
|
{
|
|
return ObjectRef<T>(dynamic_cast<T*>(ref.Get()));
|
|
}
|
|
|
|
/*!
|
|
* \brief Casts an ObjectRef 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>
|
|
ObjectRef<T> ReinterpretRefCast(const ObjectRef<U>& ref)
|
|
{
|
|
return ObjectRef<T>(static_cast<T*>(ref.Get()));
|
|
}
|
|
|
|
/*!
|
|
* \brief Casts an ObjectRef 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>
|
|
ObjectRef<T> StaticRefCast(const ObjectRef<U>& ref)
|
|
{
|
|
return ObjectRef<T>(static_cast<T*>(ref.Get()));
|
|
}
|
|
}
|
|
|
|
namespace std
|
|
{
|
|
template<typename T>
|
|
struct hash<Nz::ObjectRef<T>>
|
|
{
|
|
/*!
|
|
* \ingroup core
|
|
* \brief Gives a hash representation of the object, specialisation of std
|
|
* \return Hash of the ObjectRef
|
|
*
|
|
* \param object Object to hash
|
|
*/
|
|
|
|
size_t operator()(const Nz::ObjectRef<T>& object) const
|
|
{
|
|
hash<T*> h;
|
|
return h(object.Get());
|
|
}
|
|
};
|
|
}
|
|
|
|
#include <Nazara/Core/DebugOff.hpp>
|