Emmanuel BENOîT
a4a2a9eda4
* Added == and != operators; they can only be used if the referenced types are from the same hierarchy * Tests for the above
324 lines
6.6 KiB
C++
324 lines
6.6 KiB
C++
/******************************************************************************/
|
|
/* 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;
|
|
}
|
|
|
|
template< bool B >
|
|
inline uint32_t T_ReferenceCountedClass< B >::getReferenceCount( ) const noexcept
|
|
{
|
|
return uint32_t{ referenceCounter_ };
|
|
}
|
|
|
|
|
|
/*= 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 >
|
|
template< typename... AT >
|
|
inline T_RcPtr< T > T_RcPtr< T >::New(
|
|
AT&& ... arguments )
|
|
{
|
|
T* const obj{ new T( std::forward< AT >( arguments ) ... ) };
|
|
T_RcPtr< T > ptr;
|
|
ptr.setTarget_( obj );
|
|
return ptr;
|
|
}
|
|
|
|
template< typename T >
|
|
inline T_RcPtr< T > T_RcPtr< T >::FromRaw(
|
|
T* ptr ) noexcept
|
|
{
|
|
assert( ptr->getReferenceCount( ) == 0 );
|
|
T_RcPtr< T > rv;
|
|
ptr->increaseReferences_( );
|
|
rv.target_ = ptr;
|
|
return rv;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
template< typename T >
|
|
inline void T_RcPtr< T >::setTarget_(
|
|
T_Target* t ) noexcept
|
|
{
|
|
assert( target_ == nullptr );
|
|
if ( t ) {
|
|
t->increaseReferences_( );
|
|
}
|
|
target_ = t;
|
|
}
|
|
|
|
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_{ nullptr }
|
|
{
|
|
setTarget_( other.target_ );
|
|
}
|
|
|
|
template< typename T >
|
|
template<
|
|
typename Q ,
|
|
T_EnableForChild< T , Q >
|
|
> inline T_RcPtr< T >::T_RcPtr(
|
|
T_RcPtr< Q > const& other ) noexcept
|
|
: target_{ nullptr }
|
|
{
|
|
setTarget_( other.target_ );
|
|
}
|
|
|
|
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 >
|
|
inline T_RcPtr< T >& T_RcPtr< T >::operator= (
|
|
T_Self const& other ) noexcept
|
|
{
|
|
clear( );
|
|
setTarget_( other.target_ );
|
|
return *this;
|
|
}
|
|
|
|
template< typename T >
|
|
template<
|
|
typename Q ,
|
|
T_EnableForChild< T , Q >
|
|
> inline T_RcPtr< T >& T_RcPtr< T >::operator= (
|
|
T_RcPtr< Q > const& other ) noexcept
|
|
{
|
|
clear( );
|
|
setTarget_( other.target_ );
|
|
return *this;
|
|
}
|
|
|
|
template< typename T >
|
|
template<
|
|
typename Q ,
|
|
T_EnableForParent< T , Q >
|
|
> inline T_RcPtr< T >& T_RcPtr< T >::operator= (
|
|
T_RcPtr< Q > const& other )
|
|
{
|
|
clear( );
|
|
if ( other.target_ ) {
|
|
T* const nt{ dynamic_cast< T* >( other.target_ ) };
|
|
if ( nt == nullptr ) {
|
|
throw std::bad_cast( );
|
|
}
|
|
setTarget_( nt );
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
template< typename T >
|
|
template<
|
|
typename Q ,
|
|
T_EnableForChild< T , Q >
|
|
> inline T_RcPtr< T >::T_RcPtr(
|
|
T_RcPtr< Q >&& other ) noexcept
|
|
: target_{ nullptr }
|
|
{
|
|
T* const ptr{ (T*) other.target_ };
|
|
other.target_ = nullptr;
|
|
target_ = ptr;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
template< typename T >
|
|
template<
|
|
typename Q ,
|
|
T_EnableForChild< T , Q >
|
|
> inline T_RcPtr< T >& T_RcPtr< T >::operator= (
|
|
T_RcPtr< Q >&& other ) noexcept
|
|
{
|
|
clear( );
|
|
target_ = other.target_;
|
|
other.target_ = nullptr;
|
|
return *this;
|
|
}
|
|
|
|
template< typename T >
|
|
template<
|
|
typename Q ,
|
|
T_EnableForParent< T , Q >
|
|
> inline T_RcPtr< T >& T_RcPtr< T >::operator= (
|
|
T_RcPtr< Q >&& other )
|
|
{
|
|
clear( );
|
|
if ( other.target_ ) {
|
|
T* const nt{ dynamic_cast< T* >( other.target_ ) };
|
|
if ( nt == nullptr ) {
|
|
throw std::bad_cast( );
|
|
}
|
|
other.target_ = nullptr;
|
|
target_ = nt;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
template< typename T >
|
|
inline T_RcPtr< T > T_RcPtr< T >::swap(
|
|
T_RcPtr< T >& other ) noexcept
|
|
{
|
|
std::swap( target_ , other.target_ );
|
|
return *this;
|
|
}
|
|
|
|
template< typename T >
|
|
inline void swap( T_RcPtr< T >& lhs ,
|
|
T_RcPtr< T >& rhs ) noexcept
|
|
{
|
|
lhs.swap( rhs );
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
template< typename T >
|
|
inline T_RcPtr< T >::operator bool ( ) const noexcept
|
|
{
|
|
return target_ != nullptr;
|
|
}
|
|
|
|
template< typename T >
|
|
inline bool T_RcPtr< T >::operator! ( ) const noexcept
|
|
{
|
|
return target_ == nullptr;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
template< typename T >
|
|
inline T_RcPtr< T >::operator T* ( ) const noexcept
|
|
{
|
|
return target_;
|
|
}
|
|
|
|
template< typename T >
|
|
inline T* T_RcPtr< T >::get( ) const noexcept
|
|
{
|
|
return target_;
|
|
}
|
|
|
|
template< typename T >
|
|
inline T* T_RcPtr< T >::operator -> ( ) const
|
|
{
|
|
assert( target_ != nullptr );
|
|
return target_;
|
|
}
|
|
|
|
template< typename T >
|
|
inline T& T_RcPtr< T >::operator * ( ) const
|
|
{
|
|
assert( target_ != nullptr );
|
|
return *target_;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
template< typename T >
|
|
template<
|
|
typename Q ,
|
|
T_EnableForHierarchy< T , Q >
|
|
> inline bool T_RcPtr< T >::operator== (
|
|
T_RcPtr< Q > const& p ) const noexcept
|
|
{
|
|
return (char const*) this == (char const*) &p
|
|
|| (char const*) p.target_ == (char const*) target_;
|
|
}
|
|
|
|
template< typename T >
|
|
template<
|
|
typename Q ,
|
|
T_EnableForHierarchy< T , Q >
|
|
> inline bool T_RcPtr< T >::operator!= (
|
|
T_RcPtr< Q > const& p ) const noexcept
|
|
{
|
|
return (char const*) this != (char const*) &p
|
|
&& (char const*) p.target_ != (char const*) target_;
|
|
}
|
|
|
|
|
|
} // namespace ebcl
|
|
#endif // _H_EBCL_INLINE_REFCOUNT
|