Implemented patch 2893162 to allow dynamic-casting with SmartPtr and StrongPtr.

git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@1052 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
rich_sposato 2009-11-10 19:22:16 +00:00
parent d54996dbba
commit 9e3a736929
3 changed files with 242 additions and 36 deletions

View file

@ -1172,6 +1172,45 @@ namespace Loki
typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
#endif
/// SmartPtr uses this helper class to specify the dynamic-caster constructor.
class DynamicCastHelper {};
/// Private constructor is only used for dynamic-casting.
template
<
typename T1,
template < class > class OP1,
class CP1,
template < class > class KP1,
template < class > class SP1,
template < class > class CNP1
>
SmartPtr( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs, const DynamicCastHelper & helper )
{
(void)helper; // do void cast to remove compiler warning.
// Dynamic casting from T1 to T and saving result in `this''s pointer
PointerType p = dynamic_cast< PointerType >( GetImplRef( rhs ) );
GetImplRef( *this ) = OP::Clone( p );
}
/// Private constructor is only used for dynamic-casting.
template
<
typename T1,
template < class > class OP1,
class CP1,
template < class > class KP1,
template < class > class SP1,
template < class > class CNP1
>
SmartPtr( SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs, const DynamicCastHelper & helper )
{
(void)helper; // do void cast to remove compiler warning.
// Dynamic casting from T1 to T and saving result in `this''s pointer
PointerType p = dynamic_cast< PointerType >( GetImplRef( rhs ) );
GetImplRef( *this ) = OP::Clone( p );
}
public:
SmartPtr()
@ -1206,7 +1245,9 @@ namespace Loki
>
SmartPtr(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
{ GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
{
GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
}
template
<
@ -1285,6 +1326,40 @@ namespace Loki
}
}
/// Dynamically-casts parameter pointer to the type specified by this SmartPtr type.
template
<
typename T1,
template < class > class OP1,
class CP1,
template < class > class KP1,
template < class > class SP1,
template < class > class CNP1
>
SmartPtr & DynamicCastFrom( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
{
SmartPtr temp( rhs, DynamicCastHelper() );
temp.Swap( *this );
return *this;
}
/// Dynamically-casts parameter pointer to the type specified by this SmartPtr type.
template
<
typename T1,
template < class > class OP1,
class CP1,
template < class > class KP1,
template < class > class SP1,
template < class > class CNP1
>
SmartPtr & DynamicCastFrom( SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
{
SmartPtr temp( rhs, DynamicCastHelper() );
temp.Swap( *this );
return *this;
}
#ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
// old non standard in class definition of friends

View file

@ -564,6 +564,8 @@ protected:
Increment( strong );
}
TwoRefCounts( const TwoRefCounts & rhs, bool isNull, bool strong );
/** The destructor does not need to do anything since the call to
ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which
this dtor would have done.
@ -664,6 +666,24 @@ protected:
Increment( strong );
}
LockableTwoRefCounts( const LockableTwoRefCounts & rhs, bool isNull, bool strong ) :
m_counts( ( isNull ) ? NULL : rhs.m_counts )
{
if ( isNull )
{
void * temp = ThreadSafePointerAllocator::operator new(
sizeof(Loki::Private::LockableTwoRefCountInfo) );
#ifdef DO_EXTRA_LOKI_TESTS
assert( temp != 0 );
#endif
m_counts = new ( temp ) Loki::Private::LockableTwoRefCountInfo( strong );
}
else
{
Increment( strong );
}
}
/** The destructor does not need to do anything since the call to
ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which
this dtor would have done.
@ -789,6 +809,8 @@ protected:
TwoRefLinks( const TwoRefLinks & rhs, bool strong );
TwoRefLinks( const TwoRefLinks & rhs, bool isNull, bool strong );
bool Release( bool strong );
void Swap( TwoRefLinks & rhs );
@ -893,6 +915,49 @@ private:
typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
#endif
/// StrongPtr uses this helper class to specify the dynamic-caster constructor.
class DynamicCastHelper {};
/// Private constructor is only used for dynamic-casting.
template
<
typename T1,
bool S1,
class OP1,
class CP1,
template < class > class KP1,
template < class > class RP1,
template < class > class DP1,
template < class > class CNP1
>
StrongPtr( const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs,
bool isNull, const DynamicCastHelper & helper )
// Dynamic casting from T1 to T and saving result in ownership policy.
: OP( rhs, isNull, Strong )
{
(void)helper; // do void cast to remove compiler warning.
}
/// Private constructor is only used for dynamic-casting.
template
<
typename T1,
bool S1,
class OP1,
class CP1,
template < class > class KP1,
template < class > class RP1,
template < class > class DP1,
template < class > class CNP1
>
StrongPtr( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs,
bool isNull, const DynamicCastHelper & helper )
// Dynamic casting from T1 to T and saving result in ownership policy.
: OP( rhs, isNull, Strong )
{
(void)helper; // do void cast to remove compiler warning.
}
public:
StrongPtr( void ) : OP( Strong )
@ -1032,6 +1097,56 @@ public:
}
}
/// Dynamically-casts parameter pointer to the type specified by this SmartPtr type.
template
<
typename T1,
bool S1,
class OP1,
class CP1,
template < class > class KP1,
template < class > class RP1,
template < class > class DP1,
template < class > class CNP1
>
StrongPtr & DynamicCastFrom( const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
{
typedef typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::PointerType RightPointerType;
const StrongPtr & sp = reinterpret_cast< const StrongPtr & >( rhs );
PointerType p = sp.GetPointer();
const RightPointerType rp = reinterpret_cast< const RightPointerType >( p );
p = dynamic_cast< const PointerType >( rp );
const bool isNull = ( NULL == p );
StrongPtr temp( rhs, isNull, DynamicCastHelper() );
Swap( temp );
return *this;
}
/// Dynamically-casts parameter pointer to the type specified by this SmartPtr type.
template
<
typename T1,
bool S1,
class OP1,
class CP1,
template < class > class KP1,
template < class > class RP1,
template < class > class DP1,
template < class > class CNP1
>
StrongPtr & DynamicCastFrom( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
{
typedef typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::PointerType RightPointerType;
StrongPtr & sp = reinterpret_cast< StrongPtr & >( rhs );
PointerType p = sp.GetPointer();
RightPointerType rp = reinterpret_cast< RightPointerType >( p );
p = dynamic_cast< PointerType >( rp );
const bool isNull = ( NULL == p );
StrongPtr temp( rhs, isNull, DynamicCastHelper() );
Swap( temp );
return *this;
}
#ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
// old non standard in class definition of friends
@ -1663,35 +1778,4 @@ inline bool operator >= ( U * lhs,
namespace std
{
////////////////////////////////////////////////////////////////////////////////
/// specialization of std::less for StrongPtr
/// \ingroup SmartPointerGroup
////////////////////////////////////////////////////////////////////////////////
template
<
typename T,
bool S,
class OP,
class CP,
template < class > class KP,
template < class > class RP,
template < class > class DP,
template < class > class CNP
>
struct less< Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > >
: public binary_function<
Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >,
Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >, bool >
{
bool operator () (
const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs,
const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) const
{
return ( lhs < rhs );
}
};
}
////////////////////////////////////////////////////////////////////////////////
#endif // end file guardian
/// specialization of std::less for StroeTracker@Private@Loki@@@std@@@std@@QBEXABV123@@Z??_C@_1BBK@FOBGIJMK@?$AAs?$AAt?$AAd?$AA?3?$AA?3?$AAl?$AAi?$AAs?$AAt?$AA?$DM?$AAc?$AAl?$AAa?$AAs?$AAs?$AA?5?$AAL?$AAo?$AAk?$AAi?$AA?3?$AA?3?$AAP?$AAr?$AAi?$AAv?$AAa?$AAt?$AAe?$AA?3?$AA?3?$AAL@??_C@_1DI@MDELDGPI@?$AAl?$AAi?$AAs?$AAt?$AA?5?$AAi?$AAt?$AAe?$AAr?$AAa?$AAt?$AAo?$AAr?$AAs?$AA?5?$AAi?$AAn?$AAc?$AAo?$AAm?$AAp?$AAa?$AAt?$AAi?$AAb?$AAl?$AAe?$AA?$AA@??$_Debug_lt_pred@P6A_NPBVLifetimeTracker@Private@Loki@@0@ZPAV123@PAV123@@std@@YA_NP6A_NPBVLifetimeTracker@Private@Loki@@0@ZAAPAV123@2PB_WI@Z

View file

@ -57,6 +57,24 @@ TwoRefCounts::TwoRefCounts( const void * p, bool strong )
// ----------------------------------------------------------------------------
TwoRefCounts::TwoRefCounts( const TwoRefCounts & rhs, bool isNull, bool strong )
: m_counts( ( isNull ) ? NULL : rhs.m_counts )
{
if ( isNull )
{
void * temp = SmallObject<>::operator new(
sizeof(Loki::Private::TwoRefCountInfo) );
assert( temp != 0 );
m_counts = new ( temp ) Loki::Private::TwoRefCountInfo( strong );
}
else
{
Increment( strong );
}
}
// ----------------------------------------------------------------------------
void TwoRefCounts::Increment( bool strong )
{
if ( strong )
@ -147,6 +165,35 @@ TwoRefLinks::TwoRefLinks( const TwoRefLinks & rhs, bool strong )
// ----------------------------------------------------------------------------
TwoRefLinks::TwoRefLinks( const TwoRefLinks & rhs, bool isNull, bool strong )
: m_pointer( ( isNull ) ? 0 : rhs.m_pointer )
, m_prev( ( isNull ) ? 0 : const_cast< TwoRefLinks * >( &rhs ) )
, m_next( ( isNull ) ? 0 : rhs.m_next )
, m_strong( strong )
{
if ( isNull )
{
m_prev = m_next = this;
}
else
{
m_prev->m_next = this;
m_next->m_prev = this;
#ifdef DO_EXTRA_LOKI_TESTS
assert( m_prev->HasPrevNode( this ) );
assert( m_next->HasNextNode( this ) );
assert( rhs.m_next->HasNextNode( this ) );
assert( rhs.m_prev->HasPrevNode( this ) );
assert( CountPrevCycle( this ) == CountNextCycle( this ) );
assert( CountPrevCycle( this ) == CountNextCycle( &rhs ) );
assert( AllNodesHaveSamePointer() );
#endif
}
}
// ----------------------------------------------------------------------------
void TwoRefLinks::SetPointer( void * p )
{
TwoRefLinks * node = m_prev;