mirror of
https://github.com/worldforge/cyphesis
synced 2026-08-13 12:26:04 -04:00
269 lines
5.6 KiB
C++
269 lines
5.6 KiB
C++
/*
|
|
Copyright (C) 2018 Erik Ogenvik
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#ifndef CYPHESIS_REF_H
|
|
#define CYPHESIS_REF_H
|
|
|
|
#include <memory>
|
|
|
|
template<typename T>
|
|
class Ref
|
|
{
|
|
public:
|
|
template<class U> friend
|
|
class Ref;
|
|
|
|
constexpr Ref();
|
|
|
|
constexpr Ref(const Ref& rhs);
|
|
|
|
constexpr Ref(Ref&& rhs) noexcept;
|
|
|
|
/* implicit */
|
|
constexpr Ref(T* entity);
|
|
|
|
/**
|
|
* This allows us to create a new Ref from a Ref for a subclass.
|
|
*/
|
|
/* implicit */
|
|
template<class TSubclass>
|
|
constexpr operator Ref<TSubclass>() const noexcept
|
|
{
|
|
return Ref<TSubclass>(m_inner);
|
|
}
|
|
|
|
/**
|
|
* This allows us to create a new Ref from a Ref for a subclass.
|
|
*/
|
|
/* implicit */
|
|
template<class TSubclass>
|
|
constexpr operator Ref<const TSubclass>() const noexcept
|
|
{
|
|
return Ref<const TSubclass>(m_inner);
|
|
}
|
|
|
|
~Ref();
|
|
|
|
constexpr Ref<T>& operator=(T* rhs);
|
|
|
|
constexpr Ref& operator=(const Ref&);
|
|
|
|
/**
|
|
* This operator allows us to assign a Ref for a subclass to this.
|
|
*
|
|
* Like this:
|
|
* Ref<SuperClass> r;
|
|
* r = Ref<SubClass>();
|
|
*
|
|
*/
|
|
template<class TSubclass>
|
|
constexpr Ref& operator=(const Ref<TSubclass>& rhs)
|
|
{
|
|
if (rhs.get()) {
|
|
rhs.get()->incRef();
|
|
}
|
|
if (this->m_inner) {
|
|
this->m_inner->decRef();
|
|
}
|
|
this->m_inner = rhs.m_inner;
|
|
return *this;
|
|
}
|
|
|
|
constexpr Ref& operator=(Ref&&) noexcept;
|
|
|
|
/**
|
|
* This operator allows us to move a Ref for a subclass to this.
|
|
*
|
|
* Like this:
|
|
* Ref<SuperClass> r;
|
|
* r = std::move(Ref<SubClass>());
|
|
*
|
|
*/
|
|
template<class TSubclass>
|
|
constexpr Ref& operator=(Ref<TSubclass>&& rhs) noexcept
|
|
{
|
|
|
|
if (this->m_inner) {
|
|
this->m_inner->decRef();
|
|
}
|
|
this->m_inner = rhs.m_inner;
|
|
rhs.m_inner = nullptr;
|
|
|
|
return *this;
|
|
}
|
|
|
|
constexpr T& operator*() const
|
|
{
|
|
return *m_inner;
|
|
}
|
|
|
|
constexpr T* operator->() const
|
|
{
|
|
return m_inner;
|
|
}
|
|
|
|
constexpr T* get() const
|
|
{
|
|
return m_inner;
|
|
}
|
|
|
|
constexpr explicit operator bool() const
|
|
{
|
|
return (m_inner != nullptr);
|
|
}
|
|
|
|
constexpr bool operator!() const
|
|
{
|
|
return (m_inner == nullptr);
|
|
}
|
|
|
|
constexpr bool operator==(const Ref& e) const
|
|
{
|
|
return (m_inner == e.m_inner);
|
|
}
|
|
|
|
template<class TSubclass>
|
|
constexpr bool operator==(const Ref<TSubclass>& e) const
|
|
{
|
|
return (m_inner == e.get());
|
|
}
|
|
|
|
constexpr bool operator==(const T* e) const
|
|
{
|
|
return (m_inner == e);
|
|
}
|
|
|
|
constexpr bool operator!=(const Ref& e) const
|
|
{
|
|
return (m_inner != e.m_inner);
|
|
}
|
|
|
|
template<class TSubclass>
|
|
constexpr bool operator!=(const Ref<TSubclass>& e) const
|
|
{
|
|
return (m_inner != e.get());
|
|
}
|
|
|
|
constexpr bool operator!=(const T* e) const
|
|
{
|
|
return (m_inner != e);
|
|
}
|
|
|
|
constexpr bool operator<(const Ref& e) const
|
|
{
|
|
return (m_inner < e.m_inner);
|
|
}
|
|
|
|
constexpr explicit operator T*() const;
|
|
|
|
protected:
|
|
T* m_inner;
|
|
|
|
};
|
|
|
|
template<typename T>
|
|
constexpr Ref<T>::Ref()
|
|
: m_inner(nullptr)
|
|
{
|
|
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr Ref<T>::Ref(const Ref& rhs)
|
|
: m_inner(rhs.m_inner)
|
|
{
|
|
if (this->m_inner) {
|
|
this->m_inner->incRef();
|
|
}
|
|
}
|
|
|
|
|
|
template<typename T>
|
|
constexpr Ref<T>::Ref(Ref&& rhs) noexcept
|
|
: m_inner(rhs.m_inner)
|
|
{
|
|
rhs.m_inner = nullptr;
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr Ref<T>::Ref(T* entity)
|
|
: m_inner(entity)
|
|
{
|
|
if (this->m_inner) {
|
|
this->m_inner->incRef();
|
|
}
|
|
}
|
|
|
|
template<typename T>
|
|
Ref<T>::~Ref()
|
|
{
|
|
if (this->m_inner) {
|
|
this->m_inner->decRef();
|
|
}
|
|
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr Ref<T>& Ref<T>::operator=(T* rhs)
|
|
{
|
|
if (rhs) {
|
|
rhs->incRef();
|
|
}
|
|
if (this->m_inner) {
|
|
this->m_inner->decRef();
|
|
}
|
|
this->m_inner = rhs;
|
|
return *this;
|
|
}
|
|
|
|
|
|
template<typename T>
|
|
constexpr Ref<T>& Ref<T>::operator=(const Ref<T>& rhs)
|
|
{
|
|
if (rhs.m_inner) {
|
|
rhs.m_inner->incRef();
|
|
}
|
|
if (this->m_inner) {
|
|
this->m_inner->decRef();
|
|
}
|
|
this->m_inner = rhs.m_inner;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr Ref<T>& Ref<T>::operator=(Ref<T>&& rhs) noexcept
|
|
{
|
|
if (this != &rhs) {
|
|
if (this->m_inner) {
|
|
this->m_inner->decRef();
|
|
}
|
|
this->m_inner = rhs.m_inner;
|
|
rhs.m_inner = nullptr;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
template<typename T>
|
|
constexpr Ref<T>::operator T*() const
|
|
{
|
|
return m_inner;
|
|
}
|
|
|
|
|
|
#endif //CYPHESIS_REF_H
|