128 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#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)...));
 | 
						|
	}
 | 
						|
}
 |