/******************************************************************************/
/* REFERENCE-COUNTING HELPERS - INLINE CODE ***********************************/
/******************************************************************************/

#ifndef _H_EBCL_INLINE_REFCOUNT
#define _H_EBCL_INLINE_REFCOUNT
#include <ebcl/RefCount.hh>
namespace ebcl {


/*= T_ReferenceCountedClass ==================================================*/

template< bool B >
inline T_ReferenceCountedClass< B >::T_ReferenceCountedClass( ) noexcept
	: referenceCounter_{ 0 }
{ }

template< bool B >
inline void T_ReferenceCountedClass< B >::increaseReferences_( ) noexcept
{
	referenceCounter_ ++;
}

template< bool B >
inline bool T_ReferenceCountedClass< B >::decreaseReferences_( ) noexcept
{
	return ( -- referenceCounter_ ) == 0;
}


/*= T_RcPtr ==================================================================*/

template< typename T >
inline T_RcPtr< T >::T_RcPtr( ) noexcept
	: target_{ nullptr }
{ }

template< typename T >
inline T_RcPtr< T >::~T_RcPtr( ) noexcept
{
	clear( );
}

template< typename T >
inline void T_RcPtr< T >::clear( ) noexcept
{
	if ( target_ && target_->decreaseReferences_( ) ) {
		delete target_;
	}
	target_ = nullptr;
}

/*----------------------------------------------------------------------------*/

template< typename T >
inline T_RcPtr< T >::T_RcPtr(
		T_RcPtr< T > const& other ) noexcept
	: target_{ other.target_ }
{
	if ( target_ ) {
		target_->increaseReferences_( );
	}
}

template< typename T >
template<
	typename Q ,
	T_EnableForChild< T , Q >
> inline T_RcPtr< T >::T_RcPtr(
		T_RcPtr< Q > const& other ) noexcept
	: target_{ other.target_ }
{
	if ( target_ ) {
		target_->increaseReferences_( );
	}
}

template< typename T >
template<
	typename Q ,
	T_EnableForParent< T , Q >
> inline T_RcPtr< T >::T_RcPtr(
		T_RcPtr< Q > const& other )
	: target_{ nullptr }
{
	Q* const p{ other.target_ };
	if ( p != nullptr ) {
		target_ = dynamic_cast< T* >( p );
		if ( target_ == nullptr ) {
			throw std::bad_cast( );
		}
		target_->increaseReferences_( );
	}
}

/*----------------------------------------------------------------------------*/

template< typename T >
template<
	typename Q ,
	T_EnableForChild< T , Q >
> inline T_RcPtr< T >::T_RcPtr(
		T_RcPtr< Q >&& other ) noexcept
	: target_{ nullptr }
{
	std::swap( target_ , other.target_ );
}

template< typename T >
template<
	typename Q ,
	T_EnableForParent< T , Q >
> inline T_RcPtr< T >::T_RcPtr(
		T_RcPtr< Q >&& other )
	: target_{ nullptr }
{
	Q* const p{ other.target_ };
	if ( p != nullptr ) {
		target_ = dynamic_cast< T* >( p );
		if ( target_ == nullptr ) {
			throw std::bad_cast( );
		}
		other.target_ = nullptr;
	}
}


} // namespace ebcl
#endif // _H_EBCL_INLINE_REFCOUNT