#pragma once
|
|
|
|
#include <type_traits>
|
|
|
|
namespace vlc
|
|
{
|
|
template<typename T> class IntrusivePtr
|
|
{
|
|
public:
|
|
IntrusivePtr() noexcept = default;
|
|
|
|
IntrusivePtr(T* ptr, bool own = true) : m_ptr(ptr)
|
|
{
|
|
if (own)
|
|
{
|
|
intrusiveIncRef(m_ptr);
|
|
}
|
|
}
|
|
|
|
IntrusivePtr(const IntrusivePtr& src)
|
|
{
|
|
*this = src;
|
|
}
|
|
|
|
IntrusivePtr& operator = (const IntrusivePtr& src)
|
|
{
|
|
intrusiveDecRef(m_ptr);
|
|
|
|
m_ptr = src.m_ptr;
|
|
intrusiveIncRef(m_ptr);
|
|
|
|
return *this;
|
|
}
|
|
|
|
template<typename DerivedType> IntrusivePtr(const IntrusivePtr<DerivedType>& src)
|
|
{
|
|
*this = src;
|
|
}
|
|
|
|
template<typename DerivedType> IntrusivePtr& operator = (const IntrusivePtr<DerivedType>& src)
|
|
{
|
|
static_assert(std::is_base_of<T, DerivedType>::value, "Type of source pointer should be derived from this type");
|
|
|
|
intrusiveDecRef(m_ptr);
|
|
|
|
m_ptr = static_cast<T*>(src.get());
|
|
intrusiveIncRef(m_ptr);
|
|
|
|
return *this;
|
|
}
|
|
|
|
IntrusivePtr(IntrusivePtr&& src)
|
|
{
|
|
swap(src);
|
|
}
|
|
|
|
IntrusivePtr& operator = (IntrusivePtr&& src)
|
|
{
|
|
swap(src);
|
|
|
|
return *this;
|
|
}
|
|
|
|
~IntrusivePtr()
|
|
{
|
|
intrusiveDecRef(m_ptr);
|
|
}
|
|
|
|
explicit operator bool() const
|
|
{
|
|
return get() != nullptr;
|
|
}
|
|
|
|
void swap(IntrusivePtr& r)
|
|
{
|
|
std::swap(m_ptr, r.m_ptr);
|
|
}
|
|
|
|
void reset(T* ptr = nullptr, bool own = true)
|
|
{
|
|
IntrusivePtr(ptr, own).swap(*this);
|
|
}
|
|
|
|
T* operator -> () const
|
|
{
|
|
assert(m_ptr);
|
|
return m_ptr;
|
|
}
|
|
|
|
T& operator * () const
|
|
{
|
|
assert(m_ptr);
|
|
return *m_ptr;
|
|
}
|
|
|
|
T* release()
|
|
{
|
|
T* result = nullptr;
|
|
std::swap(result, m_ptr);
|
|
intrusiveDecRef(result);
|
|
return result;
|
|
}
|
|
|
|
T* get() const
|
|
{
|
|
return m_ptr;
|
|
}
|
|
|
|
template<typename DerivedType> DerivedType* cast()
|
|
{
|
|
return static_cast<DerivedType*>(m_ptr);
|
|
}
|
|
|
|
template<typename DerivedType> const DerivedType* cast() const
|
|
{
|
|
return static_cast<const DerivedType*>(m_ptr);
|
|
}
|
|
|
|
private:
|
|
T* m_ptr = nullptr;
|
|
};
|
|
|
|
template<typename T, typename... Args> IntrusivePtr<T> make_intrusive(Args&&... args)
|
|
{
|
|
return IntrusivePtr<T>(new T(std::forward<Args>(args)...));
|
|
}
|
|
}
|