mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-07-29 20:37:13 +02:00
This commit was generated by cvs2svn to compensate for changes in r4,
which included commits to RCS files with non-trunk default branches. [SVN r7621]
This commit is contained in:
369
include/boost/smart_ptr.hpp
Normal file
369
include/boost/smart_ptr.hpp
Normal file
@ -0,0 +1,369 @@
|
||||
// Boost smart_ptr.hpp header file -----------------------------------------//
|
||||
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. Permission to copy,
|
||||
// use, modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided "as is"
|
||||
// without express or implied warranty, and with no claim as to its
|
||||
// suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 22 Jun 00 Remove #if continuations to fix GCC 2.95.2 problem (Beman Dawes)
|
||||
// 1 Feb 00 Additional shared_ptr BOOST_NO_MEMBER_TEMPLATES workarounds
|
||||
// (Dave Abrahams)
|
||||
// 31 Dec 99 Condition tightened for no member template friend workaround
|
||||
// (Dave Abrahams)
|
||||
// 30 Dec 99 Moved BOOST_NMEMBER_TEMPLATES compatibility code to config.hpp
|
||||
// (Dave Abrahams)
|
||||
// 30 Nov 99 added operator ==, operator !=, and std::swap and std::less
|
||||
// specializations for shared types (Darin Adler)
|
||||
// 11 Oct 99 replaced op[](int) with op[](std::size_t) (Ed Brey, Valentin
|
||||
// Bonnard), added shared_ptr workaround for no member template
|
||||
// friends (Matthew Langston)
|
||||
// 25 Sep 99 added shared_ptr::swap and shared_array::swap (Luis Coelho).
|
||||
// 20 Jul 99 changed name to smart_ptr.hpp, #include <boost/config.hpp>,
|
||||
// #include <boost/utility.hpp> and use boost::noncopyable
|
||||
// 17 May 99 remove scoped_array and shared_array operator*() as
|
||||
// unnecessary (Beman Dawes)
|
||||
// 14 May 99 reorder code so no effects when bad_alloc thrown (Abrahams/Dawes)
|
||||
// 13 May 99 remove certain throw() specifiers to avoid generated try/catch
|
||||
// code cost (Beman Dawes)
|
||||
// 11 May 99 get() added, conversion to T* placed in macro guard (Valentin
|
||||
// Bonnard, Dave Abrahams, and others argued for elimination
|
||||
// of the automatic conversion)
|
||||
// 28 Apr 99 #include <memory> fix (Valentin Bonnard)
|
||||
// 28 Apr 99 rename transfer() to share() for clarity (Dave Abrahams)
|
||||
// 28 Apr 99 remove unsafe shared_array template conversions(Valentin Bonnard)
|
||||
// 28 Apr 99 p(r) changed to p(r.px) for clarity (Dave Abrahams)
|
||||
// 21 Apr 99 reset() self assignment fix (Valentin Bonnard)
|
||||
// 21 Apr 99 dispose() provided to improve clarity (Valentin Bonnard)
|
||||
// 27 Apr 99 leak when new throws fixes (Dave Abrahams)
|
||||
// 21 Oct 98 initial Version (Greg Colvin/Beman Dawes)
|
||||
|
||||
#ifndef BOOST_SMART_PTR_HPP
|
||||
#define BOOST_SMART_PTR_HPP
|
||||
|
||||
#include <boost/config.hpp> // for broken compiler workarounds
|
||||
#include <cstddef> // for std::size_t
|
||||
#include <memory> // for std::auto_ptr
|
||||
#include <algorithm> // for std::swap
|
||||
#include <boost/utility.hpp> // for boost::noncopyable
|
||||
#include <functional> // for std::less
|
||||
|
||||
namespace boost {
|
||||
|
||||
// scoped_ptr --------------------------------------------------------------//
|
||||
|
||||
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
|
||||
// of the object pointed to, either on destruction of the scoped_ptr or via
|
||||
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
|
||||
// see shared_ptr (below) or std::auto_ptr if your needs are more complex.
|
||||
|
||||
template<typename T> class scoped_ptr : noncopyable {
|
||||
|
||||
T* ptr;
|
||||
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
explicit scoped_ptr( T* p=0 ) throw() : ptr(p) {}
|
||||
~scoped_ptr() { delete ptr; }
|
||||
|
||||
void reset( T* p=0 ) { if ( ptr != p ) { delete ptr; ptr = p; } }
|
||||
T& operator*() const throw() { return *ptr; }
|
||||
T* operator->() const throw() { return ptr; }
|
||||
T* get() const throw() { return ptr; }
|
||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
||||
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
||||
operator T*() const throw() { return ptr; }
|
||||
#endif
|
||||
}; // scoped_ptr
|
||||
|
||||
// scoped_array ------------------------------------------------------------//
|
||||
|
||||
// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
|
||||
// is guaranteed, either on destruction of the scoped_array or via an explicit
|
||||
// reset(). See shared_array or std::vector if your needs are more complex.
|
||||
|
||||
template<typename T> class scoped_array : noncopyable {
|
||||
|
||||
T* ptr;
|
||||
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
explicit scoped_array( T* p=0 ) throw() : ptr(p) {}
|
||||
~scoped_array() { delete [] ptr; }
|
||||
|
||||
void reset( T* p=0 ) { if ( ptr != p ) {delete [] ptr; ptr=p;} }
|
||||
|
||||
T* get() const throw() { return ptr; }
|
||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
||||
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
||||
operator T*() const throw() { return ptr; }
|
||||
#else
|
||||
T& operator[](std::size_t i) const throw() { return ptr[i]; }
|
||||
#endif
|
||||
}; // scoped_array
|
||||
|
||||
// shared_ptr --------------------------------------------------------------//
|
||||
|
||||
// An enhanced relative of scoped_ptr with reference counted copy semantics.
|
||||
// The object pointed to is deleted when the last shared_ptr pointing to it
|
||||
// is destroyed or reset.
|
||||
|
||||
template<typename T> class shared_ptr {
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
explicit shared_ptr(T* p =0) : px(p) {
|
||||
try { pn = new long(1); } // fix: prevent leak if new throws
|
||||
catch (...) { delete p; throw; }
|
||||
}
|
||||
|
||||
shared_ptr(const shared_ptr& r) throw() : px(r.px) { ++*(pn = r.pn); }
|
||||
|
||||
~shared_ptr() { dispose(); }
|
||||
|
||||
shared_ptr& operator=(const shared_ptr& r) {
|
||||
share(r.px,r.pn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_MEMBER_TEMPLATES )
|
||||
template<typename Y>
|
||||
shared_ptr(const shared_ptr<Y>& r) throw() : px(r.px) {
|
||||
++*(pn = r.pn);
|
||||
}
|
||||
|
||||
template<typename Y>
|
||||
shared_ptr(std::auto_ptr<Y>& r) {
|
||||
pn = new long(1); // may throw
|
||||
px = r.release(); // fix: moved here to stop leak if new throws
|
||||
}
|
||||
|
||||
template<typename Y>
|
||||
shared_ptr& operator=(const shared_ptr<Y>& r) {
|
||||
share(r.px,r.pn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Y>
|
||||
shared_ptr& operator=(std::auto_ptr<Y>& r) {
|
||||
// code choice driven by guarantee of "no effect if new throws"
|
||||
if (*pn == 1) { delete px; }
|
||||
else { // allocate new reference counter
|
||||
long * tmp = new long(1); // may throw
|
||||
--*pn; // only decrement once danger of new throwing is past
|
||||
pn = tmp;
|
||||
} // allocate new reference counter
|
||||
px = r.release(); // fix: moved here so doesn't leak if new throws
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
shared_ptr(std::auto_ptr<T>& r) {
|
||||
pn = new long(1); // may throw
|
||||
px = r.release(); // fix: moved here to stop leak if new throws
|
||||
}
|
||||
|
||||
shared_ptr& operator=(std::auto_ptr<T>& r) {
|
||||
// code choice driven by guarantee of "no effect if new throws"
|
||||
if (*pn == 1) { delete px; }
|
||||
else { // allocate new reference counter
|
||||
long * tmp = new long(1); // may throw
|
||||
--*pn; // only decrement once danger of new throwing is past
|
||||
pn = tmp;
|
||||
} // allocate new reference counter
|
||||
px = r.release(); // fix: moved here so doesn't leak if new throws
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
void reset(T* p=0) {
|
||||
if ( px == p ) return; // fix: self-assignment safe
|
||||
if (--*pn == 0) { delete px; }
|
||||
else { // allocate new reference counter
|
||||
try { pn = new long; } // fix: prevent leak if new throws
|
||||
catch (...) {
|
||||
++*pn; // undo effect of --*pn above to meet effects guarantee
|
||||
delete p;
|
||||
throw;
|
||||
} // catch
|
||||
} // allocate new reference counter
|
||||
*pn = 1;
|
||||
px = p;
|
||||
} // reset
|
||||
|
||||
T& operator*() const throw() { return *px; }
|
||||
T* operator->() const throw() { return px; }
|
||||
T* get() const throw() { return px; }
|
||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
||||
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
||||
operator T*() const throw() { return px; }
|
||||
#endif
|
||||
|
||||
long use_count() const throw(){ return *pn; }
|
||||
bool unique() const throw() { return *pn == 1; }
|
||||
|
||||
void swap(shared_ptr<T>& other) throw()
|
||||
{ std::swap(px,other.px); std::swap(pn,other.pn); }
|
||||
|
||||
// Tasteless as this may seem, making all members public allows member templates
|
||||
// to work in the absence of member template friends. (Matthew Langston)
|
||||
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
|
||||
#if defined(BOOST_NO_MEMBER_TEMPLATES) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
|
||||
private:
|
||||
#endif
|
||||
|
||||
T* px; // contained pointer
|
||||
long* pn; // ptr to reference counter
|
||||
|
||||
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
|
||||
#if !defined( BOOST_NO_MEMBER_TEMPLATES ) && !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
|
||||
template<typename Y> friend class shared_ptr;
|
||||
#endif
|
||||
|
||||
void dispose() { if (--*pn == 0) { delete px; delete pn; } }
|
||||
|
||||
void share(T* rpx, long* rpn) {
|
||||
if (pn != rpn) {
|
||||
dispose();
|
||||
px = rpx;
|
||||
++*(pn = rpn);
|
||||
}
|
||||
} // share
|
||||
}; // shared_ptr
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b)
|
||||
{ return a.get() == b.get(); }
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b)
|
||||
{ return a.get() != b.get(); }
|
||||
|
||||
// shared_array ------------------------------------------------------------//
|
||||
|
||||
// shared_array extends shared_ptr to arrays.
|
||||
// The array pointed to is deleted when the last shared_array pointing to it
|
||||
// is destroyed or reset.
|
||||
|
||||
template<typename T> class shared_array {
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
explicit shared_array(T* p =0) : px(p) {
|
||||
try { pn = new long(1); } // fix: prevent leak if new throws
|
||||
catch (...) { delete [] p; throw; }
|
||||
}
|
||||
|
||||
shared_array(const shared_array& r) throw() : px(r.px) { ++*(pn = r.pn); }
|
||||
|
||||
~shared_array() { dispose(); }
|
||||
|
||||
shared_array& operator=(const shared_array& r) {
|
||||
if (pn != r.pn) {
|
||||
dispose();
|
||||
px = r.px;
|
||||
++*(pn = r.pn);
|
||||
}
|
||||
return *this;
|
||||
} // operator=
|
||||
|
||||
void reset(T* p=0) {
|
||||
if ( px == p ) return; // fix: self-assignment safe
|
||||
if (--*pn == 0) { delete [] px; }
|
||||
else { // allocate new reference counter
|
||||
try { pn = new long; } // fix: prevent leak if new throws
|
||||
catch (...) {
|
||||
++*pn; // undo effect of --*pn above to meet effects guarantee
|
||||
delete [] p;
|
||||
throw;
|
||||
} // catch
|
||||
} // allocate new reference counter
|
||||
*pn = 1;
|
||||
px = p;
|
||||
} // reset
|
||||
|
||||
T* get() const throw() { return px; }
|
||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
||||
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
||||
operator T*() const throw() { return px; }
|
||||
#else
|
||||
T& operator[](std::size_t i) const throw() { return px[i]; }
|
||||
#endif
|
||||
|
||||
long use_count() const throw() { return *pn; }
|
||||
bool unique() const throw() { return *pn == 1; }
|
||||
|
||||
void swap(shared_array<T>& other) throw()
|
||||
{ std::swap(px,other.px); std::swap(pn,other.pn); }
|
||||
|
||||
private:
|
||||
|
||||
T* px; // contained pointer
|
||||
long* pn; // ptr to reference counter
|
||||
|
||||
void dispose() { if (--*pn == 0) { delete [] px; delete pn; } }
|
||||
|
||||
}; // shared_array
|
||||
|
||||
template<typename T>
|
||||
inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
|
||||
{ return a.get() == b.get(); }
|
||||
|
||||
template<typename T>
|
||||
inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
|
||||
{ return a.get() != b.get(); }
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// specializations for things in namespace std -----------------------------//
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
namespace std {
|
||||
|
||||
// Specialize std::swap to use the fast, non-throwing swap that's provided
|
||||
// as a member function instead of using the default algorithm which creates
|
||||
// a temporary and uses assignment.
|
||||
|
||||
template<typename T>
|
||||
inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b)
|
||||
{ a.swap(b); }
|
||||
|
||||
template<typename T>
|
||||
inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b)
|
||||
{ a.swap(b); }
|
||||
|
||||
// Specialize std::less so we can use shared pointers and arrays as keys in
|
||||
// associative collections.
|
||||
|
||||
// It's still a controversial question whether this is better than supplying
|
||||
// a full range of comparison operators (<, >, <=, >=).
|
||||
|
||||
template<typename T>
|
||||
struct less< boost::shared_ptr<T> >
|
||||
: binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool>
|
||||
{
|
||||
bool operator()(const boost::shared_ptr<T>& a,
|
||||
const boost::shared_ptr<T>& b) const
|
||||
{ return less<T*>()(a.get(),b.get()); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct less< boost::shared_array<T> >
|
||||
: binary_function<boost::shared_array<T>, boost::shared_array<T>, bool>
|
||||
{
|
||||
bool operator()(const boost::shared_array<T>& a,
|
||||
const boost::shared_array<T>& b) const
|
||||
{ return less<T*>()(a.get(),b.get()); }
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
#endif // BOOST_SMART_PTR_HPP
|
||||
|
263
smart_ptr_test.cpp
Normal file
263
smart_ptr_test.cpp
Normal file
@ -0,0 +1,263 @@
|
||||
// smart pointer test program ----------------------------------------------//
|
||||
|
||||
// (C) Copyright Beman Dawes 1998, 1999. Permission to copy, use, modify, sell
|
||||
// and distribute this software is granted provided this copyright notice
|
||||
// appears in all copies. This software is provided "as is" without express or
|
||||
// implied warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// Revision History
|
||||
// 29 Nov 99 added std::swap and associative container tests (Darin Adler)
|
||||
// 25 Sep 99 added swap tests
|
||||
// 20 Jul 99 header name changed to .hpp
|
||||
// 20 Apr 99 additional error tests added.
|
||||
|
||||
#include <boost/smart_ptr.hpp>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
#ifdef NDEBUG
|
||||
#error This test program makes no sense if NDEBUG is defined
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using boost::scoped_ptr;
|
||||
using boost::scoped_array;
|
||||
using boost::shared_ptr;
|
||||
using boost::shared_array;
|
||||
|
||||
template<typename T>
|
||||
void ck( const T* v1, T v2 ) { assert( *v1 == v2 ); }
|
||||
|
||||
namespace {
|
||||
int UDT_use_count; // independent of pointer maintained counts
|
||||
}
|
||||
|
||||
// user defined type -------------------------------------------------------//
|
||||
|
||||
class UDT {
|
||||
long value_;
|
||||
public:
|
||||
explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; }
|
||||
~UDT() {
|
||||
--UDT_use_count;
|
||||
cout << "UDT with value " << value_ << " being destroyed" << endl;
|
||||
}
|
||||
long value() const { return value_; }
|
||||
void value( long v ) { value_ = v;; }
|
||||
}; // UDT
|
||||
|
||||
// main --------------------------------------------------------------------//
|
||||
|
||||
// This isn't a very systematic test; it just hits some of the basics.
|
||||
|
||||
int main() {
|
||||
|
||||
assert( UDT_use_count == 0 ); // reality check
|
||||
|
||||
// test scoped_ptr with a built-in type
|
||||
long * lp = new long;
|
||||
scoped_ptr<long> sp ( lp );
|
||||
assert( sp.get() == lp );
|
||||
assert( lp == sp.get() );
|
||||
assert( &*sp == lp );
|
||||
|
||||
*sp = 1234568901L;
|
||||
assert( *sp == 1234568901L );
|
||||
assert( *lp == 1234568901L );
|
||||
ck( static_cast<long*>(sp.get()), 1234568901L );
|
||||
ck( lp, *sp );
|
||||
|
||||
sp.reset();
|
||||
assert( sp.get() == 0 );
|
||||
|
||||
// test scoped_ptr with a user defined type
|
||||
scoped_ptr<UDT> udt_sp ( new UDT( 999888777 ) );
|
||||
assert( udt_sp->value() == 999888777 );
|
||||
udt_sp.reset();
|
||||
udt_sp.reset( new UDT( 111222333 ) );
|
||||
assert( udt_sp->value() == 111222333 );
|
||||
udt_sp.reset( new UDT( 333222111 ) );
|
||||
assert( udt_sp->value() == 333222111 );
|
||||
|
||||
// test scoped_array with a build-in type
|
||||
char * sap = new char [ 100 ];
|
||||
scoped_array<char> sa ( sap );
|
||||
assert( sa.get() == sap );
|
||||
assert( sap == sa.get() );
|
||||
|
||||
strcpy( sa.get(), "Hot Dog with mustard and relish" );
|
||||
assert( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 );
|
||||
assert( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 );
|
||||
|
||||
assert( sa[0] == 'H' );
|
||||
assert( sa[30] == 'h' );
|
||||
|
||||
sa[0] = 'N';
|
||||
sa[4] = 'd';
|
||||
assert( strcmp( sap, "Not dog with mustard and relish" ) == 0 );
|
||||
|
||||
sa.reset();
|
||||
assert( sa.get() == 0 );
|
||||
|
||||
// test shared_ptr with a built-in type
|
||||
int * ip = new int;
|
||||
shared_ptr<int> cp ( ip );
|
||||
assert( ip == cp.get() );
|
||||
assert( cp.use_count() == 1 );
|
||||
|
||||
*cp = 54321;
|
||||
assert( *cp == 54321 );
|
||||
assert( *ip == 54321 );
|
||||
ck( static_cast<int*>(cp.get()), 54321 );
|
||||
ck( static_cast<int*>(ip), *cp );
|
||||
|
||||
shared_ptr<int> cp2 ( cp );
|
||||
assert( ip == cp2.get() );
|
||||
assert( cp.use_count() == 2 );
|
||||
assert( cp2.use_count() == 2 );
|
||||
|
||||
assert( *cp == 54321 );
|
||||
assert( *cp2 == 54321 );
|
||||
ck( static_cast<int*>(cp2.get()), 54321 );
|
||||
ck( static_cast<int*>(ip), *cp2 );
|
||||
|
||||
shared_ptr<int> cp3 ( cp );
|
||||
assert( cp.use_count() == 3 );
|
||||
assert( cp2.use_count() == 3 );
|
||||
assert( cp3.use_count() == 3 );
|
||||
cp.reset();
|
||||
assert( cp2.use_count() == 2 );
|
||||
assert( cp3.use_count() == 2 );
|
||||
assert( cp.use_count() == 1 );
|
||||
cp.reset( new int );
|
||||
*cp = 98765;
|
||||
assert( *cp == 98765 );
|
||||
*cp3 = 87654;
|
||||
assert( *cp3 == 87654 );
|
||||
assert( *cp2 == 87654 );
|
||||
cp.swap( cp3 );
|
||||
assert( *cp == 87654 );
|
||||
assert( *cp2 == 87654 );
|
||||
assert( *cp3 == 98765 );
|
||||
cp.swap( cp3 );
|
||||
assert( *cp == 98765 );
|
||||
assert( *cp2 == 87654 );
|
||||
assert( *cp3 == 87654 );
|
||||
cp2 = cp2;
|
||||
assert( cp2.use_count() == 2 );
|
||||
assert( *cp2 == 87654 );
|
||||
cp = cp2;
|
||||
assert( cp2.use_count() == 3 );
|
||||
assert( *cp2 == 87654 );
|
||||
assert( cp.use_count() == 3 );
|
||||
assert( *cp == 87654 );
|
||||
|
||||
shared_ptr<int> cp4;
|
||||
swap( cp2, cp4 );
|
||||
assert( cp4.use_count() == 3 );
|
||||
assert( *cp4 == 87654 );
|
||||
assert( cp2.get() == 0 );
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
set< shared_ptr<int> > scp;
|
||||
scp.insert(cp4);
|
||||
assert( scp.find(cp4) != scp.end() );
|
||||
assert( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) );
|
||||
#endif
|
||||
|
||||
// test shared_array with a built-in type
|
||||
char * cap = new char [ 100 ];
|
||||
shared_array<char> ca ( cap );
|
||||
assert( ca.get() == cap );
|
||||
assert( cap == ca.get() );
|
||||
assert( &ca[0] == cap );
|
||||
|
||||
strcpy( ca.get(), "Hot Dog with mustard and relish" );
|
||||
assert( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 );
|
||||
assert( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 );
|
||||
|
||||
assert( ca[0] == 'H' );
|
||||
assert( ca[30] == 'h' );
|
||||
|
||||
shared_array<char> ca2 ( ca );
|
||||
shared_array<char> ca3 ( ca2 );
|
||||
|
||||
ca[0] = 'N';
|
||||
ca[4] = 'd';
|
||||
assert( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
assert( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
assert( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
assert( ca.use_count() == 3 );
|
||||
assert( ca2.use_count() == 3 );
|
||||
assert( ca3.use_count() == 3 );
|
||||
ca2.reset();
|
||||
assert( ca.use_count() == 2 );
|
||||
assert( ca3.use_count() == 2 );
|
||||
assert( ca2.use_count() == 1 );
|
||||
|
||||
ca.reset();
|
||||
assert( ca.get() == 0 );
|
||||
|
||||
shared_array<char> ca4;
|
||||
swap( ca3, ca4 );
|
||||
assert( ca4.use_count() == 1 );
|
||||
assert( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
assert( ca3.get() == 0 );
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
set< shared_array<char> > sca;
|
||||
sca.insert(ca4);
|
||||
assert( sca.find(ca4) != sca.end() );
|
||||
assert( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) );
|
||||
#endif
|
||||
|
||||
// test shared_array with user defined type
|
||||
shared_array<UDT> udta ( new UDT[3] );
|
||||
|
||||
udta[0].value( 111 );
|
||||
udta[1].value( 222 );
|
||||
udta[2].value( 333 );
|
||||
shared_array<UDT> udta2 ( udta );
|
||||
|
||||
assert( udta[0].value() == 111 );
|
||||
assert( udta[1].value() == 222 );
|
||||
assert( udta[2].value() == 333 );
|
||||
assert( udta2[0].value() == 111 );
|
||||
assert( udta2[1].value() == 222 );
|
||||
assert( udta2[2].value() == 333 );
|
||||
udta2.reset();
|
||||
assert( udta2.get() == 0 );
|
||||
assert( udta.use_count() == 1 );
|
||||
assert( udta2.use_count() == 1 );
|
||||
|
||||
assert( UDT_use_count == 4 ); // reality check
|
||||
|
||||
// test shared_ptr with a user defined type
|
||||
UDT * up = new UDT;
|
||||
shared_ptr<UDT> sup ( up );
|
||||
assert( up == sup.get() );
|
||||
assert( sup.use_count() == 1 );
|
||||
|
||||
sup->value( 54321 ) ;
|
||||
assert( sup->value() == 54321 );
|
||||
assert( up->value() == 54321 );
|
||||
|
||||
shared_ptr<UDT> sup2;
|
||||
sup2 = sup;
|
||||
assert( sup2->value() == 54321 );
|
||||
assert( sup.use_count() == 2 );
|
||||
assert( sup2.use_count() == 2 );
|
||||
sup2 = sup2;
|
||||
assert( sup2->value() == 54321 );
|
||||
assert( sup.use_count() == 2 );
|
||||
assert( sup2.use_count() == 2 );
|
||||
|
||||
cout << "OK" << endl;
|
||||
|
||||
new char[12345]; // deliberate memory leak to verify leaks detected
|
||||
|
||||
return 0;
|
||||
} // main
|
||||
|
Reference in New Issue
Block a user