Added array handling to SmartPtr.
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@1109 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
419efb2c20
commit
80a07d19e8
2 changed files with 153 additions and 7 deletions
|
@ -355,6 +355,45 @@ namespace Loki
|
||||||
inline typename LockedStorage<T>::StoredType& GetImplRef(LockedStorage<T>& sp)
|
inline typename LockedStorage<T>::StoredType& GetImplRef(LockedStorage<T>& sp)
|
||||||
{ return sp.pointee_; }
|
{ 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
|
/// \class ArrayStorage
|
||||||
|
@ -365,7 +404,7 @@ namespace Loki
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class ArrayStorage
|
class ArrayStorage : public ::Loki::Private::DeleteArrayBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -376,26 +415,30 @@ namespace Loki
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
ArrayStorage() : pointee_(Default())
|
ArrayStorage() : DeleteArrayBase(), pointee_(Default())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// The storage policy doesn't initialize the stored pointer
|
// The storage policy doesn't initialize the stored pointer
|
||||||
// which will be initialized by the OwnershipPolicy's Clone fn
|
// 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>
|
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_; }
|
PointerType operator->() const { return pointee_; }
|
||||||
|
|
||||||
ReferenceType operator*() const { return *pointee_; }
|
ReferenceType operator*() const { return *pointee_; }
|
||||||
|
|
||||||
void Swap(ArrayStorage& rhs)
|
void Swap( ArrayStorage & rhs )
|
||||||
{ std::swap(pointee_, rhs.pointee_); }
|
{
|
||||||
|
DeleteArrayBase::Swap( rhs );
|
||||||
|
::std::swap( pointee_, rhs.pointee_ );
|
||||||
|
}
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
template <class F>
|
template <class F>
|
||||||
|
@ -844,6 +887,8 @@ namespace Loki
|
||||||
NoCheck()
|
NoCheck()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
NoCheck( const NoCheck & ) {}
|
||||||
|
|
||||||
template <class P1>
|
template <class P1>
|
||||||
NoCheck(const NoCheck<P1>&)
|
NoCheck(const NoCheck<P1>&)
|
||||||
{}
|
{}
|
||||||
|
@ -878,6 +923,8 @@ namespace Loki
|
||||||
AssertCheck()
|
AssertCheck()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
AssertCheck( const AssertCheck & ) {}
|
||||||
|
|
||||||
template <class P1>
|
template <class P1>
|
||||||
AssertCheck(const AssertCheck<P1>&)
|
AssertCheck(const AssertCheck<P1>&)
|
||||||
{}
|
{}
|
||||||
|
@ -916,6 +963,8 @@ namespace Loki
|
||||||
AssertCheckStrict()
|
AssertCheckStrict()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
AssertCheckStrict( const AssertCheckStrict & ) {}
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
AssertCheckStrict(const AssertCheckStrict<U>&)
|
AssertCheckStrict(const AssertCheckStrict<U>&)
|
||||||
{}
|
{}
|
||||||
|
@ -972,6 +1021,8 @@ namespace Loki
|
||||||
RejectNullStatic()
|
RejectNullStatic()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
RejectNullStatic( const RejectNullStatic & ) {}
|
||||||
|
|
||||||
template <class P1>
|
template <class P1>
|
||||||
RejectNullStatic(const RejectNullStatic<P1>&)
|
RejectNullStatic(const RejectNullStatic<P1>&)
|
||||||
{}
|
{}
|
||||||
|
@ -1022,6 +1073,8 @@ namespace Loki
|
||||||
RejectNull()
|
RejectNull()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
RejectNull( const RejectNull & ) {}
|
||||||
|
|
||||||
template <class P1>
|
template <class P1>
|
||||||
RejectNull(const RejectNull<P1>&)
|
RejectNull(const RejectNull<P1>&)
|
||||||
{}
|
{}
|
||||||
|
@ -1058,6 +1111,8 @@ namespace Loki
|
||||||
RejectNullStrict()
|
RejectNullStrict()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
RejectNullStrict( const RejectNullStrict & ) {}
|
||||||
|
|
||||||
template <class P1>
|
template <class P1>
|
||||||
RejectNullStrict(const RejectNullStrict<P1>&)
|
RejectNullStrict(const RejectNullStrict<P1>&)
|
||||||
{}
|
{}
|
||||||
|
@ -1245,6 +1300,16 @@ namespace Loki
|
||||||
KP::OnInit(GetImpl(*this));
|
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)
|
SmartPtr(CopyArg& rhs) : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
||||||
{
|
{
|
||||||
KP::OnDereference( GetImpl( rhs ) );
|
KP::OnDereference( GetImpl( rhs ) );
|
||||||
|
@ -1333,6 +1398,21 @@ namespace Loki
|
||||||
return *this;
|
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)
|
void Swap(SmartPtr& rhs)
|
||||||
{
|
{
|
||||||
OP::Swap(rhs);
|
OP::Swap(rhs);
|
||||||
|
@ -1465,6 +1545,30 @@ namespace Loki
|
||||||
return SP::operator*();
|
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) ..."
|
bool operator!() const // Enables "if (!sp) ..."
|
||||||
{ return GetImpl(*this) == 0; }
|
{ return GetImpl(*this) == 0; }
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
//#define DO_EXTRA_LOKI_TESTS
|
//#define DO_EXTRA_LOKI_TESTS
|
||||||
#ifdef DO_EXTRA_LOKI_TESTS
|
#ifdef DO_EXTRA_LOKI_TESTS
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -37,6 +40,45 @@ namespace Private
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
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 ) :
|
RefLinkedBase::RefLinkedBase( const RefLinkedBase & rhs ) :
|
||||||
prev_( &rhs ),
|
prev_( &rhs ),
|
||||||
next_( rhs.next_ )
|
next_( rhs.next_ )
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue