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:
parent
d54996dbba
commit
9e3a736929
3 changed files with 242 additions and 36 deletions
|
@ -194,9 +194,9 @@ namespace Loki
|
||||||
|
|
||||||
// Destroys the data stored
|
// Destroys the data stored
|
||||||
// (Destruction might be taken over by the OwnershipPolicy)
|
// (Destruction might be taken over by the OwnershipPolicy)
|
||||||
//
|
//
|
||||||
// If your compiler gives you a warning in this area while
|
// If your compiler gives you a warning in this area while
|
||||||
// compiling the tests, it is on purpose, please ignore it.
|
// compiling the tests, it is on purpose, please ignore it.
|
||||||
void Destroy()
|
void Destroy()
|
||||||
{
|
{
|
||||||
delete pointee_;
|
delete pointee_;
|
||||||
|
@ -1172,6 +1172,45 @@ namespace Loki
|
||||||
typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
|
typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
|
||||||
#endif
|
#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:
|
public:
|
||||||
|
|
||||||
SmartPtr()
|
SmartPtr()
|
||||||
|
@ -1206,7 +1245,9 @@ namespace Loki
|
||||||
>
|
>
|
||||||
SmartPtr(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
|
SmartPtr(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
|
||||||
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
||||||
{ GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
|
{
|
||||||
|
GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
template
|
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
|
#ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
|
||||||
|
|
||||||
// old non standard in class definition of friends
|
// old non standard in class definition of friends
|
||||||
|
|
|
@ -564,6 +564,8 @@ protected:
|
||||||
Increment( strong );
|
Increment( strong );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TwoRefCounts( const TwoRefCounts & rhs, bool isNull, bool strong );
|
||||||
|
|
||||||
/** The destructor does not need to do anything since the call to
|
/** The destructor does not need to do anything since the call to
|
||||||
ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which
|
ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which
|
||||||
this dtor would have done.
|
this dtor would have done.
|
||||||
|
@ -664,6 +666,24 @@ protected:
|
||||||
Increment( strong );
|
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
|
/** The destructor does not need to do anything since the call to
|
||||||
ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which
|
ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which
|
||||||
this dtor would have done.
|
this dtor would have done.
|
||||||
|
@ -789,6 +809,8 @@ protected:
|
||||||
|
|
||||||
TwoRefLinks( const TwoRefLinks & rhs, bool strong );
|
TwoRefLinks( const TwoRefLinks & rhs, bool strong );
|
||||||
|
|
||||||
|
TwoRefLinks( const TwoRefLinks & rhs, bool isNull, bool strong );
|
||||||
|
|
||||||
bool Release( bool strong );
|
bool Release( bool strong );
|
||||||
|
|
||||||
void Swap( TwoRefLinks & rhs );
|
void Swap( TwoRefLinks & rhs );
|
||||||
|
@ -893,6 +915,49 @@ private:
|
||||||
typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
|
typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
|
||||||
#endif
|
#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:
|
public:
|
||||||
|
|
||||||
StrongPtr( void ) : OP( Strong )
|
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
|
#ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
|
||||||
|
|
||||||
// old non standard in class definition of friends
|
// old non standard in class definition of friends
|
||||||
|
@ -1663,35 +1778,4 @@ inline bool operator >= ( U * lhs,
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// specialization of std::less for StrongPtr
|
/// specialization of std::less for StroeTracker@Private@Loki@@@std@@@std@@QBEXABV123@@Z |