From: <ric...@us...> - 2009-11-10 19:22:24
|
Revision: 1052 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1052&view=rev Author: rich_sposato Date: 2009-11-10 19:22:16 +0000 (Tue, 10 Nov 2009) Log Message: ----------- Implemented patch 2893162 to allow dynamic-casting with SmartPtr and StrongPtr. Modified Paths: -------------- trunk/include/loki/SmartPtr.h trunk/include/loki/StrongPtr.h trunk/src/StrongPtr.cpp Modified: trunk/include/loki/SmartPtr.h =================================================================== --- trunk/include/loki/SmartPtr.h 2009-11-02 22:45:51 UTC (rev 1051) +++ trunk/include/loki/SmartPtr.h 2009-11-10 19:22:16 UTC (rev 1052) @@ -194,9 +194,9 @@ // Destroys the data stored // (Destruction might be taken over by the OwnershipPolicy) - // - // If your compiler gives you a warning in this area while - // compiling the tests, it is on purpose, please ignore it. + // + // If your compiler gives you a warning in this area while + // compiling the tests, it is on purpose, please ignore it. void Destroy() { delete pointee_; @@ -1172,6 +1172,45 @@ 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 @@ > 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 @@ } } + /// 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 Modified: trunk/include/loki/StrongPtr.h =================================================================== --- trunk/include/loki/StrongPtr.h 2009-11-02 22:45:51 UTC (rev 1051) +++ trunk/include/loki/StrongPtr.h 2009-11-10 19:22:16 UTC (rev 1052) @@ -564,6 +564,8 @@ 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 @@ 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 @@ 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 @@ 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 @@ } } + /// 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 @@ 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 |