From: <ric...@us...> - 2011-09-20 22:33:40
|
Revision: 1109 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1109&view=rev Author: rich_sposato Date: 2011-09-20 22:33:34 +0000 (Tue, 20 Sep 2011) Log Message: ----------- Added array handling to SmartPtr. Modified Paths: -------------- trunk/include/loki/SmartPtr.h trunk/src/SmartPtr.cpp Modified: trunk/include/loki/SmartPtr.h =================================================================== --- trunk/include/loki/SmartPtr.h 2011-09-20 18:38:13 UTC (rev 1108) +++ trunk/include/loki/SmartPtr.h 2011-09-20 22:33:34 UTC (rev 1109) @@ -355,7 +355,46 @@ inline typename LockedStorage<T>::StoredType& GetImplRef(LockedStorage<T>& sp) { return sp.pointee_; } + namespace Private + { + //////////////////////////////////////////////////////////////////////////////// + /// \class DeleteArrayBase + /// + /// \ingroup StrongPointerDeleteGroup + /// Base class used only by the DeleteArray policy class. This stores the + /// number of elements in an array of shared objects. + //////////////////////////////////////////////////////////////////////////////// + + class DeleteArrayBase + { + public: + + inline size_t GetArrayCount( void ) const { return m_itemCount; } + + protected: + + DeleteArrayBase( void ) : m_itemCount( 0 ) {} + + explicit DeleteArrayBase( size_t itemCount ) : m_itemCount( itemCount ) {} + + DeleteArrayBase( const DeleteArrayBase & that ) : m_itemCount( that.m_itemCount ) {} + + void Swap( DeleteArrayBase & rhs ); + + void OnInit( const void * p ) const; + + void OnCheckRange( size_t index ) const; + + private: + + size_t m_itemCount; + + }; + + } + + //////////////////////////////////////////////////////////////////////////////// /// \class ArrayStorage /// @@ -365,7 +404,7 @@ template <class T> - class ArrayStorage + class ArrayStorage : public ::Loki::Private::DeleteArrayBase { public: @@ -376,26 +415,30 @@ protected: - ArrayStorage() : pointee_(Default()) + ArrayStorage() : DeleteArrayBase(), pointee_(Default()) {} // The storage policy doesn't initialize the stored pointer // which will be initialized by the OwnershipPolicy's Clone fn - ArrayStorage(const ArrayStorage&) : pointee_(0) + ArrayStorage( const ArrayStorage & that ) : DeleteArrayBase( that ), pointee_( 0 ) {} template <class U> - ArrayStorage(const ArrayStorage<U>&) : pointee_(0) + ArrayStorage( const ArrayStorage< U >& that ) : DeleteArrayBase( that ), pointee_( 0 ) {} - explicit ArrayStorage(const StoredType& p) : pointee_(p) {} + ArrayStorage( const StoredType & p, size_t count ) : DeleteArrayBase( count ), + pointee_( p ) {} PointerType operator->() const { return pointee_; } ReferenceType operator*() const { return *pointee_; } - void Swap(ArrayStorage& rhs) - { std::swap(pointee_, rhs.pointee_); } + void Swap( ArrayStorage & rhs ) + { + DeleteArrayBase::Swap( rhs ); + ::std::swap( pointee_, rhs.pointee_ ); + } // Accessors template <class F> @@ -844,6 +887,8 @@ NoCheck() {} + NoCheck( const NoCheck & ) {} + template <class P1> NoCheck(const NoCheck<P1>&) {} @@ -878,6 +923,8 @@ AssertCheck() {} + AssertCheck( const AssertCheck & ) {} + template <class P1> AssertCheck(const AssertCheck<P1>&) {} @@ -916,6 +963,8 @@ AssertCheckStrict() {} + AssertCheckStrict( const AssertCheckStrict & ) {} + template <class U> AssertCheckStrict(const AssertCheckStrict<U>&) {} @@ -972,6 +1021,8 @@ RejectNullStatic() {} + RejectNullStatic( const RejectNullStatic & ) {} + template <class P1> RejectNullStatic(const RejectNullStatic<P1>&) {} @@ -1022,6 +1073,8 @@ RejectNull() {} + RejectNull( const RejectNull & ) {} + template <class P1> RejectNull(const RejectNull<P1>&) {} @@ -1058,6 +1111,8 @@ RejectNullStrict() {} + RejectNullStrict( const RejectNullStrict & ) {} + template <class P1> RejectNullStrict(const RejectNullStrict<P1>&) {} @@ -1245,6 +1300,16 @@ KP::OnInit(GetImpl(*this)); } + /** This constructor was designed to only work with the ArrayStorage policy. Using it with + any other Delete policies will cause compiler errors. Call it with this syntax: + "ThingyPtr sp2( new Thingy[ 4 ], 4 );" so SmartPtr can do range checking on the number of elements. + */ + SmartPtr( ImplicitArg p, size_t itemCount ) : SP( p, itemCount ) + { + KP::OnInit( GetImpl( *this ) ); + SP::OnInit( GetImpl( *this ) ); + } + SmartPtr(CopyArg& rhs) : SP(rhs), OP(rhs), KP(rhs), CP(rhs) { KP::OnDereference( GetImpl( rhs ) ); @@ -1333,6 +1398,21 @@ return *this; } + /** This function is equivalent to an assignment operator for SmartPtr's that use the + DeleteArray policy where the programmer needs to write the equivalent of "sp = new P;". + With DeleteArray, the programmer should write "sp.Assign( new [5] Thingy, 5 );" so the + SmartPtr knows how many elements are in the array. + */ + SmartPtr & Assign( T * p, size_t itemCount ) + { + if ( GetImpl( *this ) != p ) + { + SmartPtr temp( p, itemCount ); + Swap( temp ); + } + return *this; + } + void Swap(SmartPtr& rhs) { OP::Swap(rhs); @@ -1465,6 +1545,30 @@ return SP::operator*(); } + /** operator[] returns a reference to an modifiable object. If the index is greater than or + equal to the number of elements, the function will throw a std::out_of_range exception. + This only works with DeleteArray policy. Any other policy will cause a compiler error. + */ + ReferenceType operator [] ( size_t index ) + { + PointerType p = SP::operator->(); + KP::OnDereference( p ); + SP::OnCheckRange( index ); + return p[ index ]; + } + + /** operator[] returns a reference to a const object. If the index is greater than or + equal to the number of elements, the function will throw a std::out_of_range exception. + This only works with DeleteArray policy. Any other policy will cause a compiler error. + */ + ConstReferenceType operator [] ( size_t index ) const + { + ConstPointerType p = SP::operator->(); + KP::OnDereference( p ); + SP::OnCheckRange( index ); + return p[ index ]; + } + bool operator!() const // Enables "if (!sp) ..." { return GetImpl(*this) == 0; } Modified: trunk/src/SmartPtr.cpp =================================================================== --- trunk/src/SmartPtr.cpp 2011-09-20 18:38:13 UTC (rev 1108) +++ trunk/src/SmartPtr.cpp 2011-09-20 22:33:34 UTC (rev 1109) @@ -21,6 +21,9 @@ #include <cassert> +#include <stdexcept> +#include <string> + //#define DO_EXTRA_LOKI_TESTS #ifdef DO_EXTRA_LOKI_TESTS #include <iostream> @@ -37,6 +40,45 @@ // ---------------------------------------------------------------------------- +void DeleteArrayBase::Swap( DeleteArrayBase & rhs ) +{ + assert( NULL != this ); + + const size_t temp = m_itemCount; + m_itemCount = rhs.m_itemCount; + rhs.m_itemCount = temp; +} + +// ---------------------------------------------------------------------------- + +void DeleteArrayBase::OnInit( const void * p ) const +{ + assert( NULL != this ); + if ( NULL == p ) + { + assert( 0 == m_itemCount ); + } + else + { + assert( 0 < m_itemCount ); + } +} + +// ---------------------------------------------------------------------------- + +void DeleteArrayBase::OnCheckRange( size_t index ) const +{ + assert( NULL != this ); + + if ( index < m_itemCount ) + return; + + const ::std::string message( "index out of range in ::Loki::DeleteArrayBase::OnCheckRange" ); + throw ::std::out_of_range( message ); +} + +// ---------------------------------------------------------------------------- + RefLinkedBase::RefLinkedBase( const RefLinkedBase & rhs ) : prev_( &rhs ), next_( rhs.next_ ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |