NazaraEngine/include/Nazara/Core/ObjectRef.inl

561 lines
13 KiB
C++

// Copyright (C) 2024 Jérôme "SirLynix" 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/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>