From c17921c417413ac11041b04f7ed23a5d435ce09a Mon Sep 17 00:00:00 2001
From: Beman Dawes
#include <boost/smart_ptr.hpp> +#include <boost/smart_ptr.hpp> namespace boost { template<typename T> class scoped_array : noncopyable { @@ -59,27 +59,21 @@ template<typename T> class scoped_array : Common Requirements.scoped_array destructor
~scoped_array();-T is required be a complete type at point of instantiation. See Common -Requirements.
Deletes the array pointed to by the stored pointer. Note that in C++ delete[] on a pointer with a value of 0 is harmless.
Does not throw exceptions.
scoped_array reset
void reset( T* p=0 )();-T is required be a complete type at point of instantiation. See Common -Requirements.
If p is not equal to the stored pointer, deletes the array pointed to by the stored pointer and then stores a copy of p, which must have been allocated via a C++ new[] expression or be 0.
Does not throw exceptions.
scoped_array operator[]
T& operator[](std::size_t i) const; // never throws
-T is required be a complete type at point of instantiation. See Common -Requirements.
Returns a reference to element i of the array pointed to by the stored pointer.
Behavior is undefined (and almost certainly undesirable) if get()==0, @@ -87,13 +81,16 @@ or if i is less than 0 or is greater or equal to the number of elements in the array.
scoped_array get
T* get() const; // never throws-T is not required be a complete type at point of instantiation. +
T is not required be a complete type. See Common Requirements.
Returns the stored pointer.
Class scoped_array example
[To be supplied. In the meantime, see smart_ptr_test.cpp.]
-Revised December 8, 1999
+Revised 24 May, 2001 +
© Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 4945084..652d1bb 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -19,13 +19,16 @@ See example.
needs. It supplies a basic "resource acquisition is initialization" facility, without shared-ownership or transfer-of-ownership semantics. Both its name and enforcement of semantics (by being noncopyable) -signal its intent to retain ownership solely within the current scope. By -being noncopyable, it is -safer than shared_ptr or std::auto_ptr for pointers which should not be +signal its intent to retain ownership solely within the current scope. +Because it is noncopyable, it is +safer than shared_ptr or std::auto_ptr for pointers which should not be copied.Because scoped_ptr is so simple, in its usual implementation every operation is as fast as for a built-in pointer and it has no more space overhead -that a built-in pointer.
+that a built-in pointer. (Because of the "complete type" +requirement for delete and reset members, they may have one additional function +call overhead in certain idioms. See Handle/Body +Idiom.)Class scoped_ptr cannot be used in C++ Standard Library containers. See shared_ptr or std::auto_ptr if scoped_ptr does not meet your needs.
Class scoped_ptr cannot correctly hold a pointer to a @@ -35,7 +38,7 @@ for that usage.
pointed to. T must meet the smart pointer common requirements.Class scoped_ptr Synopsis
-#include <boost/smart_ptr.hpp> +#include <boost/smart_ptr.hpp> namespace boost { template<typename T> class scoped_ptr : noncopyable { @@ -59,38 +62,28 @@ template<typename T> class scoped_ptr : scoped_ptr constructorsexplicit scoped_ptr( T* p=0 ); // never throws-T is not required be a complete type at point of instantiation. +
T is not required be a complete type. See Common Requirements.
Constructs a scoped_ptr, storing a copy of p, which must have been allocated via a C++ new expression or be 0.
scoped_ptr destructor
~scoped_ptr();-T is required be a complete type at point of instantiation. See Common -Requirements.
Deletes the object pointed to by the stored pointer. Note that in C++, delete on a pointer with a value of 0 is harmless.
Does not throw exceptions.
scoped_ptr reset
void reset( T* p=0 );-T is required be a complete type at point of instantiation. See Common -Requirements.
If p is not equal to the stored pointer, deletes the object pointed to by the stored pointer and then stores a copy of p, which must have been allocated via a C++ new expression or be 0.
Does not throw exceptions.
scoped_ptr operator*
T& operator*() const; // never throws-T is required be a complete type at point of instantiation. See Common -Requirements.
Returns a reference to the object pointed to by the stored pointer.
scoped_ptr operator-> and get
T* operator->() const; // never throws T* get() const; // never throws-T is required be a complete type at point of instantiation of -operator->(). See Common -Requirements.
-T is not required be a complete type at point of instantiation of -get(). See Common Requirements.
+T is not required by get() be a complete type. See Common Requirements.
Both return the stored pointer.
Class scoped_ptr examples
#include <iostream> @@ -118,17 +111,37 @@ output: 2 Buckle my shoe-Handle/Body Idiom
-One common usage of scoped_ptr is to implement a handle/body idiom which avoids exposing the body (implementation) in the header +
Rationale
+The primary reason to use scoped_ptr rather than auto_ptr is to let readers +of your code know that you intend "resource acquisition is initialization" to be applied only for the current scope, and have no intent to transfer +ownership.
+A secondary reason to use scoped_ptr is to prevent a later maintenance programmer from adding a function that actually transfers +ownership by returning the auto_ptr (because the maintenance programmer saw +auto_ptr, and assumed ownership could safely be transferred.)
+Think of bool vs int. We all know that under the covers bool is usually +just an int. Indeed, some argued against including bool in the +C++ standard because of that. But by coding bool rather than int, you tell your readers +what your intent is. Same with scoped_ptr - you are signaling intent.
+It has been suggested that boost::scoped_ptr<T> is equivalent to +std::auto_ptr<T> const. Ed Brey pointed out, however, that +reset() will not work on a std::auto_ptr<T> const.
+Handle/Body Idiom
+One common usage of scoped_ptr is to implement a handle/body (also +called pimpl) idiom which avoids exposing the body (implementation) in the header file.
The scoped_ptr_example_test.cpp sample program includes a header file, scoped_ptr_example.hpp, which uses a scoped_ptr<> to an incomplete type to hide the implementation. The instantiation of member functions which require a complete type occurs in the scoped_ptr_example.cpp -implementation file.
+implementation file. +FAQ
+Q. Why doesn't scoped_ptr have a release() member?
+A. Because the whole point of scoped_ptr is to signal intent not +to transfer ownership. Use std::auto_ptr if ownership transfer is +required.
-Revised 22 May 2001
+Revised 24 May 2001
© Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" diff --git a/shared_array.htm b/shared_array.htm index 24842d1..6de8704 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -30,13 +30,13 @@ structures. For example, if main() holds a shared_array pointing to array A, which directly or indirectly holds a shared_array pointing back to array A, then array A's use_count() will be 2, and destruction of the main() shared_array will leave array A dangling with a use_count() of 1.
-A heavier duty alternative to a shared_array is a shared_ptr -to a C++ Standard Library vector.
+A C++ Standard Library vector is a +heavier duty alternative to a shared_array.
The class is a template parameterized on T, the type of the object pointed to. T must meet the smart pointer Common requirements.
Class shared_array Synopsis
-#include <boost/smart_ptr.hpp> +#include <boost/smart_ptr.hpp> namespace boost { template<typename T> class shared_array { @@ -108,23 +108,17 @@ name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.Provides the type of the stored pointer.
shared_array constructors
explicit shared_array( T* p=0 );-T is required be a complete type at point of instantiation. See Common -Requirements.
Constructs a shared_array, storing a copy of p, which must have been allocated via a C++ new[] expression or be 0. Afterwards, use_count() is 1 (even if p==0; see ~shared_array).
The only exception which may be thrown is std::bad_alloc. If an exception is thrown, delete[] p is called.
shared_array( const shared_array& r); // never throws-T is not required be a complete type at point of instantiation. -See Common Requirements.
Constructs a shared_array, as if by storing a copy of the pointer stored in r. Afterwards, use_count() for all copies is 1 more than the initial r.use_count().
shared_array destructor
~shared_array();-T is required be a complete type at point of instantiation. See Common -Requirements.
If use_count() == 1, deletes the array pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++ delete[] on a pointer with @@ -132,8 +126,6 @@ a value of 0 is harmless.
Does not throw exceptions.
shared_array operator=
shared_array& operator=( const shared_array& r); // never throws-T is required be a complete type at point of instantiation. See Common -Requirements.
First, if use_count() == 1, deletes the array pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++ delete[] on a @@ -143,8 +135,6 @@ of the pointer stored in r. Afterwards, use_count()r.use_count().
shared_array reset
void reset( T* p=0 );-T is required be a complete type at point of instantiation. See Common -Requirements.
First, if use_count() == 1, deletes the array pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++ delete[] @@ -157,8 +147,6 @@ see ~shared_array).
an exception is thrown, delete[] p is called.shared_array operator[]
T& operator[](std::size_t i) const; // never throws
-T is required be a complete type at point of instantiation. See Common -Requirements.
Returns a reference to element i of the array pointed to by the stored pointer.
Behavior is undefined (and almost certainly undesirable) if get()==0, @@ -166,29 +154,30 @@ or if i is less than 0 or is greater or equal to the number of elements in the array.
shared_array get
T* get() const; // never throws-T is not required be a complete type at point of instantiation. +
T is not required be a complete type. See Common Requirements.
Returns the stored pointer.
shared_array use_count
long use_count() const; // never throws
-T is not required be a complete type at point of instantiation. +
T is not required be a complete type. See Common Requirements.
Returns the number of shared_arrays sharing ownership of the stored pointer.
shared_array unique
bool unique() const; // never throws
-T is not required be a complete type at point of instantiation. +
T is not required be a complete type. See Common Requirements.
Returns use_count() == 1.
shared_array swap
-
void swap( shared_array<T>& other ) throw()
T is not required be a complete type at point of instantiation. +
T is not required be a complete type. See Common Requirements.
Swaps the two smart pointers, as if by std::swap.
Class shared_array example
[To be supplied. In the meantime, see smart_ptr_test.cpp.]
-Revised December 8, 1999
+Revised 24 May, 2001 +
© Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" diff --git a/shared_ptr.htm b/shared_ptr.htm index 78ed702..cdf2b93 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -34,7 +34,7 @@ object A dangling with a use_count() of 1.
pointed to. T must meet the smart pointer Common requirements.Class shared_ptr Synopsis
-#include <boost/smart_ptr.hpp> +-#include <boost/smart_ptr.hpp> namespace boost { template<typename T> class shared_ptr { @@ -118,8 +118,6 @@ the macro name BOOST_NO_MEMBER_TEMPLATES is defined.-Provides the type of the stored pointer.
shared_ptr constructors
explicit shared_ptr( T* p=0 );-T is required be a complete type at point of instantiation. See Common -Requirements.
Constructs a shared_ptr, storing a copy of p, which must have been allocated via a C++ new expression or be 0. Afterwards, use_count() is 1 (even if p==0; see ~shared_ptr).
@@ -130,8 +128,6 @@ template<typename Y> shared_ptr(const shared_ptr<Y>& r); // never throws template<typename Y> shared_ptr(std::auto_ptr<Y>& r);T is not required be a complete type at point of instantiation. -See Common Requirements.
Constructs a shared_ptr, as if by storing a copy of the pointer stored in r. Afterwards, use_count() for all copies is 1 more than the initial r.use_count(), or 1 @@ -142,8 +138,6 @@ is std::bad_alloc. If an exception is thrown, that constructor has no effect.
shared_ptr destructor
~shared_ptr();-T is required be a complete type at point of instantiation. See Common -Requirements.
If use_count() == 1, deletes the object pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++ delete on a pointer @@ -155,8 +149,6 @@ template<typename Y> shared_ptr& operator=(const shared_ptr<Y>& r); template<typename Y> shared_ptr& operator=(std::auto_ptr<Y>& r);
T is required be a complete type at point of instantiation. See Common -Requirements.
First, if use_count() == 1, deletes the object pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++ delete on @@ -172,8 +164,6 @@ is std::bad_alloc. If an exception is thrown, the function has no effect.
shared_ptr reset
void reset( T* p=0 );-T is required be a complete type at point of instantiation. See Common -Requirements.
First, if use_count() == 1, deletes the object pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1.
@@ -186,32 +176,26 @@ on a pointer with a value of 0 is harmless. an exception is thrown, delete p is called.shared_ptr operator*
T& operator*() const; // never throws-T is required be a complete type at point of instantiation. See Common -Requirements.
Returns a reference to the object pointed to by the stored pointer.
shared_ptr operator-> and get
T* operator->() const; // never throws T* get() const; // never throws-T is required be a complete type at point of instantiation of -operator->(). See Common -Requirements.
-T is not required be a complete type at point of instantiation of -get(). See Common Requirements.
+T is not required by get() to be a complete type . See Common Requirements.
Both return the stored pointer.
shared_ptr use_count
long use_count() const; // never throws
-T is not required be a complete type at point of instantiation. +
T is not required be a complete type. See Common Requirements.
Returns the number of shared_ptrs sharing ownership of the stored pointer.
shared_ptr unique
bool unique() const; // never throws
-T is not required be a complete type at point of instantiation. +
T is not required be a complete type. See Common Requirements.
Returns use_count() == 1.
shared_ptr swap
-
void swap( shared_ptr<T>& other ) throw()
T is not required be a complete type at point of instantiation. +
T is not required be a complete type. See Common Requirements.
Swaps the two smart pointers, as if by std::swap.
Class shared_ptr example
@@ -224,8 +208,29 @@ at various times while push_back() and insert() container operations are perform More complicated yet, the container operations may throw exceptions under a variety of circumstances. Without using a smart pointer, memory and exception management would be a nightmare. +Handle/Body Idiom
+One common usage of shared_ptr is to implement a handle/body (also +called pimpl) idiom which avoids exposing the body (implementation) in the header +file.
+The shared_ptr_example2_test.cpp +sample program includes a header file, shared_ptr_example2.hpp, +which uses a shared_ptr<> to an incomplete type to hide the +implementation. The +instantiation of member functions which require a complete type occurs in the shared_ptr_example2.cpp +implementation file.
+FAQ
+Q. Why doesn't shared_ptr have template parameters supplying +traits or policies to allow extensive user customization?
+
+A. Parameterization discourages users. Shared_ptr is +carefully crafted to meet common needs without extensive parameterization. +Someday a highly configurable smart pointer may be invented that is also very +easy to use and very hard to misuse. Until then, shared_ptr is the +smart pointer of choice for a wide range of applications.Q. Why don't shared_ptr (and the other Boost smart pointers) +supply an automatic conversion to T*?
+A. Automatic conversion is believed to be too error prone.
-Revised 22 May, 2001 +
Revised 24 May, 2001
© Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright diff --git a/smart_ptr.htm b/smart_ptr.htm index b7bcf04..07538e4 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -56,22 +56,20 @@ interest to those curious about performance issues.
These smart pointer classes have a template parameter, T, which specifies the type of the object pointed to by the smart pointer. The behavior of all four classes is undefined if the destructor or operator delete -for objects of type T throws exceptions.
+for objects of type T throw exceptions.+be a complete type at points of smart pointer instantiation. Implementations are +required to diagnose (treat as an error) all violations of this requirement, +including deletion of an incomplete type. See checked_delete().
T
may be an incomplete type at the point of smart pointer declaration. Unless otherwise specified, it is required thatT
-be a complete type at point of instantiation of all member functions.Rationale
-The requirements on T are carefully crafted to ensure safety -yet allow handle-body (aka pimpl) and similar idioms. In these idioms a +
The requirements on T are carefully crafted to maximize safety +yet allow handle-body (also called pimpl) and similar idioms. In these idioms a smart pointer may appear in translation units where T is an incomplete type. This separates interface from implementation and hides -implementation from translation units which merely use the interface.
-Example
-The scoped_ptr_example_test.cpp -sample program includes a header file, scoped_ptr_example.hpp, -which uses a scoped_ptr<> to an incomplete type. The -instantiation of member functions which require a complete type occurs in the scoped_ptr_example.cpp -implementation file.
+implementation from translation units which merely use the interface. +Examples described in the documentation for specific smart pointers illustrate +use of smart pointers in these idioms.Exception safety
Several functions in these smart pointer classes are specified as having "no effect" or "no effect except such-and-such" if an @@ -144,7 +142,7 @@ implementation.
See the Revision History section of the header for further contributors.
Revised 22 May 200124 May 2001
© Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright diff --git a/smart_ptr_test.cpp b/smart_ptr_test.cpp index cd4d61b..62c97ca 100644 --- a/smart_ptr_test.cpp +++ b/smart_ptr_test.cpp @@ -6,20 +6,26 @@ // implied warranty, and with no claim as to its suitability for any purpose. // Revision History +// 24 May 01 use Boost test library for error detection, reporting, add tests +// for operations on incomplete types (Beman Dawes) // 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. +#define BOOST_INCLUDE_MAIN +#include
#include -#include #include #include #include -#ifdef NDEBUG -#error This test program makes no sense if NDEBUG is defined -#endif +class Incomplete; + +Incomplete * get_ptr( boost::shared_ptr & incomplete ) +{ + return incomplete.get(); +} using namespace std; using boost::scoped_ptr; @@ -28,7 +34,7 @@ using boost::shared_ptr; using boost::shared_array; template -void ck( const T* v1, T v2 ) { assert( *v1 == v2 ); } +void ck( const T* v1, T v2 ) { BOOST_TEST( *v1 == v2 ); } namespace { int UDT_use_count; // independent of pointer maintained counts @@ -48,169 +54,189 @@ class UDT { void value( long v ) { value_ = v;; } }; // UDT +// tests on incomplete types -----------------------------------------------// + +// Certain smart pointer operations are specified to work on incomplete types, +// and some uses depend upon this feature. These tests verify compilation +// only - the functions aren't actually invoked. + +class Incomplete; + +Incomplete * check_incomplete( scoped_ptr & incomplete ) +{ + return incomplete.get(); +} + +Incomplete * check_incomplete( shared_ptr & incomplete, + shared_ptr & i2 ) +{ + incomplete.swap(i2); + cout << incomplete.use_count() << " " << incomplete.unique() << endl; + return incomplete.get(); +} // main --------------------------------------------------------------------// // This isn't a very systematic test; it just hits some of the basics. -int main() { +int test_main( int, char ** ) { - assert( UDT_use_count == 0 ); // reality check + BOOST_TEST( UDT_use_count == 0 ); // reality check // test scoped_ptr with a built-in type long * lp = new long; scoped_ptr sp ( lp ); - assert( sp.get() == lp ); - assert( lp == sp.get() ); - assert( &*sp == lp ); + BOOST_TEST( sp.get() == lp ); + BOOST_TEST( lp == sp.get() ); + BOOST_TEST( &*sp == lp ); *sp = 1234568901L; - assert( *sp == 1234568901L ); - assert( *lp == 1234568901L ); + BOOST_TEST( *sp == 1234568901L ); + BOOST_TEST( *lp == 1234568901L ); ck( static_cast (sp.get()), 1234568901L ); ck( lp, *sp ); sp.reset(); - assert( sp.get() == 0 ); + BOOST_TEST( sp.get() == 0 ); // test scoped_ptr with a user defined type scoped_ptr udt_sp ( new UDT( 999888777 ) ); - assert( udt_sp->value() == 999888777 ); + BOOST_TEST( udt_sp->value() == 999888777 ); udt_sp.reset(); udt_sp.reset( new UDT( 111222333 ) ); - assert( udt_sp->value() == 111222333 ); + BOOST_TEST( udt_sp->value() == 111222333 ); udt_sp.reset( new UDT( 333222111 ) ); - assert( udt_sp->value() == 333222111 ); + BOOST_TEST( udt_sp->value() == 333222111 ); // test scoped_array with a build-in type char * sap = new char [ 100 ]; scoped_array sa ( sap ); - assert( sa.get() == sap ); - assert( sap == sa.get() ); + BOOST_TEST( sa.get() == sap ); + BOOST_TEST( 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 ); + BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 ); - assert( sa[0] == 'H' ); - assert( sa[30] == 'h' ); + BOOST_TEST( sa[0] == 'H' ); + BOOST_TEST( sa[30] == 'h' ); sa[0] = 'N'; sa[4] = 'd'; - assert( strcmp( sap, "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( sap, "Not dog with mustard and relish" ) == 0 ); sa.reset(); - assert( sa.get() == 0 ); + BOOST_TEST( sa.get() == 0 ); // test shared_ptr with a built-in type int * ip = new int; shared_ptr cp ( ip ); - assert( ip == cp.get() ); - assert( cp.use_count() == 1 ); + BOOST_TEST( ip == cp.get() ); + BOOST_TEST( cp.use_count() == 1 ); *cp = 54321; - assert( *cp == 54321 ); - assert( *ip == 54321 ); + BOOST_TEST( *cp == 54321 ); + BOOST_TEST( *ip == 54321 ); ck( static_cast (cp.get()), 54321 ); ck( static_cast (ip), *cp ); shared_ptr cp2 ( cp ); - assert( ip == cp2.get() ); - assert( cp.use_count() == 2 ); - assert( cp2.use_count() == 2 ); + BOOST_TEST( ip == cp2.get() ); + BOOST_TEST( cp.use_count() == 2 ); + BOOST_TEST( cp2.use_count() == 2 ); - assert( *cp == 54321 ); - assert( *cp2 == 54321 ); + BOOST_TEST( *cp == 54321 ); + BOOST_TEST( *cp2 == 54321 ); ck( static_cast (cp2.get()), 54321 ); ck( static_cast (ip), *cp2 ); shared_ptr cp3 ( cp ); - assert( cp.use_count() == 3 ); - assert( cp2.use_count() == 3 ); - assert( cp3.use_count() == 3 ); + BOOST_TEST( cp.use_count() == 3 ); + BOOST_TEST( cp2.use_count() == 3 ); + BOOST_TEST( cp3.use_count() == 3 ); cp.reset(); - assert( cp2.use_count() == 2 ); - assert( cp3.use_count() == 2 ); - assert( cp.use_count() == 1 ); + BOOST_TEST( cp2.use_count() == 2 ); + BOOST_TEST( cp3.use_count() == 2 ); + BOOST_TEST( cp.use_count() == 1 ); cp.reset( new int ); *cp = 98765; - assert( *cp == 98765 ); + BOOST_TEST( *cp == 98765 ); *cp3 = 87654; - assert( *cp3 == 87654 ); - assert( *cp2 == 87654 ); + BOOST_TEST( *cp3 == 87654 ); + BOOST_TEST( *cp2 == 87654 ); cp.swap( cp3 ); - assert( *cp == 87654 ); - assert( *cp2 == 87654 ); - assert( *cp3 == 98765 ); + BOOST_TEST( *cp == 87654 ); + BOOST_TEST( *cp2 == 87654 ); + BOOST_TEST( *cp3 == 98765 ); cp.swap( cp3 ); - assert( *cp == 98765 ); - assert( *cp2 == 87654 ); - assert( *cp3 == 87654 ); + BOOST_TEST( *cp == 98765 ); + BOOST_TEST( *cp2 == 87654 ); + BOOST_TEST( *cp3 == 87654 ); cp2 = cp2; - assert( cp2.use_count() == 2 ); - assert( *cp2 == 87654 ); + BOOST_TEST( cp2.use_count() == 2 ); + BOOST_TEST( *cp2 == 87654 ); cp = cp2; - assert( cp2.use_count() == 3 ); - assert( *cp2 == 87654 ); - assert( cp.use_count() == 3 ); - assert( *cp == 87654 ); + BOOST_TEST( cp2.use_count() == 3 ); + BOOST_TEST( *cp2 == 87654 ); + BOOST_TEST( cp.use_count() == 3 ); + BOOST_TEST( *cp == 87654 ); shared_ptr cp4; swap( cp2, cp4 ); - assert( cp4.use_count() == 3 ); - assert( *cp4 == 87654 ); - assert( cp2.get() == 0 ); + BOOST_TEST( cp4.use_count() == 3 ); + BOOST_TEST( *cp4 == 87654 ); + BOOST_TEST( cp2.get() == 0 ); #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION set< shared_ptr > scp; scp.insert(cp4); - assert( scp.find(cp4) != scp.end() ); - assert( scp.find(cp4) == scp.find( shared_ptr (cp4) ) ); + BOOST_TEST( scp.find(cp4) != scp.end() ); + BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr (cp4) ) ); #endif // test shared_array with a built-in type char * cap = new char [ 100 ]; shared_array ca ( cap ); - assert( ca.get() == cap ); - assert( cap == ca.get() ); - assert( &ca[0] == cap ); + BOOST_TEST( ca.get() == cap ); + BOOST_TEST( cap == ca.get() ); + BOOST_TEST( &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 ); + BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 ); - assert( ca[0] == 'H' ); - assert( ca[30] == 'h' ); + BOOST_TEST( ca[0] == 'H' ); + BOOST_TEST( ca[30] == 'h' ); shared_array ca2 ( ca ); shared_array 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 ); + BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( ca.use_count() == 3 ); + BOOST_TEST( ca2.use_count() == 3 ); + BOOST_TEST( ca3.use_count() == 3 ); ca2.reset(); - assert( ca.use_count() == 2 ); - assert( ca3.use_count() == 2 ); - assert( ca2.use_count() == 1 ); + BOOST_TEST( ca.use_count() == 2 ); + BOOST_TEST( ca3.use_count() == 2 ); + BOOST_TEST( ca2.use_count() == 1 ); ca.reset(); - assert( ca.get() == 0 ); + BOOST_TEST( ca.get() == 0 ); shared_array ca4; swap( ca3, ca4 ); - assert( ca4.use_count() == 1 ); - assert( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); - assert( ca3.get() == 0 ); + BOOST_TEST( ca4.use_count() == 1 ); + BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); + BOOST_TEST( ca3.get() == 0 ); #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION set< shared_array > sca; sca.insert(ca4); - assert( sca.find(ca4) != sca.end() ); - assert( sca.find(ca4) == sca.find( shared_array (ca4) ) ); + BOOST_TEST( sca.find(ca4) != sca.end() ); + BOOST_TEST( sca.find(ca4) == sca.find( shared_array (ca4) ) ); #endif // test shared_array with user defined type @@ -221,38 +247,38 @@ int main() { udta[2].value( 333 ); shared_array 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 ); + BOOST_TEST( udta[0].value() == 111 ); + BOOST_TEST( udta[1].value() == 222 ); + BOOST_TEST( udta[2].value() == 333 ); + BOOST_TEST( udta2[0].value() == 111 ); + BOOST_TEST( udta2[1].value() == 222 ); + BOOST_TEST( udta2[2].value() == 333 ); udta2.reset(); - assert( udta2.get() == 0 ); - assert( udta.use_count() == 1 ); - assert( udta2.use_count() == 1 ); + BOOST_TEST( udta2.get() == 0 ); + BOOST_TEST( udta.use_count() == 1 ); + BOOST_TEST( udta2.use_count() == 1 ); - assert( UDT_use_count == 4 ); // reality check + BOOST_TEST( UDT_use_count == 4 ); // reality check // test shared_ptr with a user defined type UDT * up = new UDT; shared_ptr sup ( up ); - assert( up == sup.get() ); - assert( sup.use_count() == 1 ); + BOOST_TEST( up == sup.get() ); + BOOST_TEST( sup.use_count() == 1 ); sup->value( 54321 ) ; - assert( sup->value() == 54321 ); - assert( up->value() == 54321 ); + BOOST_TEST( sup->value() == 54321 ); + BOOST_TEST( up->value() == 54321 ); shared_ptr sup2; sup2 = sup; - assert( sup2->value() == 54321 ); - assert( sup.use_count() == 2 ); - assert( sup2.use_count() == 2 ); + BOOST_TEST( sup2->value() == 54321 ); + BOOST_TEST( sup.use_count() == 2 ); + BOOST_TEST( sup2.use_count() == 2 ); sup2 = sup2; - assert( sup2->value() == 54321 ); - assert( sup.use_count() == 2 ); - assert( sup2.use_count() == 2 ); + BOOST_TEST( sup2->value() == 54321 ); + BOOST_TEST( sup.use_count() == 2 ); + BOOST_TEST( sup2.use_count() == 2 ); cout << "OK" << endl;