|
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.
|