Documentation and example program improvements

[SVN r10220]
This commit is contained in:
Beman Dawes
2001-05-24 18:42:25 +00:00
parent 94287044ba
commit c17921c417
6 changed files with 214 additions and 186 deletions

View File

@@ -34,7 +34,7 @@ for that usage.</p>
pointed to.&nbsp;&nbsp; <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common pointed to.&nbsp;&nbsp; <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common
requirements</a>.</p> requirements</a>.</p>
<h2>Class scoped_array Synopsis</h2> <h2>Class scoped_array Synopsis</h2>
<pre>#include &lt;boost/smart_ptr.hpp&gt; <pre>#include &lt;<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>&gt;
namespace boost { namespace boost {
template&lt;typename T&gt; class scoped_array : <a href="../utility/utility.htm#noncopyable">noncopyable</a> { template&lt;typename T&gt; class scoped_array : <a href="../utility/utility.htm#noncopyable">noncopyable</a> {
@@ -59,27 +59,21 @@ template&lt;typename T&gt; class scoped_array : <a href="../utility/utility.htm#
<pre>explicit scoped_array( T* p=0 ); // never throws</pre> <pre>explicit scoped_array( T* p=0 ); // never throws</pre>
<p>Constructs a <tt>scoped_array</tt>, storing a copy of <tt>p</tt>, which must <p>Constructs a <tt>scoped_array</tt>, storing a copy of <tt>p</tt>, which must
have been allocated via a C++ <tt>new</tt>[] expression or be 0.</p> have been allocated via a C++ <tt>new</tt>[] expression or be 0.</p>
<p><b>T</b> is not required be a complete type at point of instantiation.&nbsp; <p><b>T</b> is not required be a complete type.&nbsp;
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p> See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
<h3><a name="scoped_array_~scoped_array">scoped_array destructor</a></h3> <h3><a name="scoped_array_~scoped_array">scoped_array destructor</a></h3>
<pre>~scoped_array();</pre> <pre>~scoped_array();</pre>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>Deletes the array pointed to by the stored pointer.&nbsp; Note that in C++ <tt>delete</tt>[] <p>Deletes the array pointed to by the stored pointer.&nbsp; Note that in C++ <tt>delete</tt>[]
on a pointer with a value of 0 is harmless.</p> on a pointer with a value of 0 is harmless.</p>
<p>Does not throw exceptions.</p> <p>Does not throw exceptions.</p>
<h3>scoped_array <a name="scoped_array_reset">reset</a></h3> <h3>scoped_array <a name="scoped_array_reset">reset</a></h3>
<pre>void reset( T* p=0 )();</pre> <pre>void reset( T* p=0 )();</pre>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>If p is not equal to the stored pointer, deletes the array pointed to by the <p>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 stored pointer and then stores a copy of p, which must have been allocated via a
C++ <tt>new[]</tt> expression or be 0.</p> C++ <tt>new[]</tt> expression or be 0.</p>
<p>Does not throw exceptions.</p> <p>Does not throw exceptions.</p>
<h3>scoped_array <a name="scoped_array_operator[]">operator[]</a></h3> <h3>scoped_array <a name="scoped_array_operator[]">operator[]</a></h3>
<p><tt>T&amp; operator[](std::size_t i) const; // never throws</tt></p> <p><tt>T&amp; operator[](std::size_t i) const; // never throws</tt></p>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>Returns a reference to element <tt>i</tt> of the array pointed to by the <p>Returns a reference to element <tt>i</tt> of the array pointed to by the
stored pointer.</p> stored pointer.</p>
<p>Behavior is undefined (and almost certainly undesirable) if <tt>get()==0</tt>, <p>Behavior is undefined (and almost certainly undesirable) if <tt>get()==0</tt>,
@@ -87,13 +81,16 @@ or if <tt>i</tt> is less than 0 or is greater or equal to the number of elements
in the array.</p> in the array.</p>
<h3>scoped_array <a name="scoped_array_get">get</a></h3> <h3>scoped_array <a name="scoped_array_get">get</a></h3>
<pre>T* get() const; // never throws</pre> <pre>T* get() const; // never throws</pre>
<p><b>T</b> is not required be a complete type at point of instantiation.&nbsp; <p><b>T</b> is not required be a complete type.&nbsp;
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p> See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
<p>Returns the stored pointer.</p> <p>Returns the stored pointer.</p>
<h2>Class <a name="shared_array_example">scoped_array example</a></h2> <h2>Class <a name="shared_array_example">scoped_array example</a></h2>
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p> <p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
<hr> <hr>
<p>Revised&nbsp; December 8, 1999</p> <p>Revised&nbsp; <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan
-->24 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13964"
-->
</p>
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, <p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
modify, sell and distribute this document is granted provided this copyright modify, sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &quot;as is&quot; notice appears in all copies. This document is provided &quot;as is&quot;

View File

@@ -19,13 +19,16 @@ See <a href="#scoped_ptr_example">example</a>.</p>
needs.&nbsp; It supplies a basic &quot;resource acquisition is needs.&nbsp; It supplies a basic &quot;resource acquisition is
initialization&quot; facility, without shared-ownership or transfer-of-ownership initialization&quot; facility, without shared-ownership or transfer-of-ownership
semantics.&nbsp; Both its name and enforcement of semantics (by being <a href="../utility/utility.htm#class noncopyable">noncopyable</a>) semantics.&nbsp; Both its name and enforcement of semantics (by being <a href="../utility/utility.htm#class noncopyable">noncopyable</a>)
signal its intent to retain ownership solely within the current scope.&nbsp; By signal its intent to retain ownership solely within the current scope.&nbsp;
being <a href="../utility/utility.htm#class noncopyable">noncopyable</a>, it is Because it is <a href="../utility/utility.htm#class noncopyable">noncopyable</a>, it is
safer than <b>shared_ptr</b> or std::auto_ptr for pointers which should not be safer than <b>shared_ptr</b> or <b> std::auto_ptr</b> for pointers which should not be
copied.</p> copied.</p>
<p>Because <strong>scoped_ptr</strong> is so simple, in its usual implementation <p>Because <strong>scoped_ptr</strong> 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 every operation is as fast as for a built-in pointer and it has no more space overhead
that a built-in pointer.</p> that a built-in pointer.&nbsp; (Because of the &quot;complete type&quot;
requirement for delete and reset members, they may have one additional function
call overhead in certain idioms.&nbsp; See <a href="#Handle/Body">Handle/Body
Idiom</a>.)&nbsp;&nbsp;&nbsp;</p>
<p>Class<strong> scoped_ptr</strong> cannot be used in C++ Standard Library containers.&nbsp; See <a href="shared_ptr.htm"><strong>shared_ptr</strong></a> <p>Class<strong> scoped_ptr</strong> cannot be used in C++ Standard Library containers.&nbsp; See <a href="shared_ptr.htm"><strong>shared_ptr</strong></a>
or std::auto_ptr if <strong>scoped_ptr</strong> does not meet your needs.</p> or std::auto_ptr if <strong>scoped_ptr</strong> does not meet your needs.</p>
<p>Class<strong> scoped_ptr</strong> cannot correctly hold a pointer to a <p>Class<strong> scoped_ptr</strong> cannot correctly hold a pointer to a
@@ -35,7 +38,7 @@ for that usage.</p>
pointed to.&nbsp;&nbsp; <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common pointed to.&nbsp;&nbsp; <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common
requirements</a>.</p> requirements</a>.</p>
<h2>Class scoped_ptr Synopsis</h2> <h2>Class scoped_ptr Synopsis</h2>
<pre>#include &lt;boost/smart_ptr.hpp&gt; <pre>#include &lt;<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>&gt;
namespace boost { namespace boost {
template&lt;typename T&gt; class scoped_ptr : <a href="../utility/utility.htm#class noncopyable">noncopyable</a> { template&lt;typename T&gt; class scoped_ptr : <a href="../utility/utility.htm#class noncopyable">noncopyable</a> {
@@ -59,38 +62,28 @@ template&lt;typename T&gt; class scoped_ptr : <a href="../utility/utility.htm#cl
<p>Provides the type of the stored pointer.</p> <p>Provides the type of the stored pointer.</p>
<h3><a name="scoped_ptr_ctor">scoped_ptr constructors</a></h3> <h3><a name="scoped_ptr_ctor">scoped_ptr constructors</a></h3>
<pre>explicit scoped_ptr( T* p=0 ); // never throws</pre> <pre>explicit scoped_ptr( T* p=0 ); // never throws</pre>
<p><b>T</b> is not required be a complete type at point of instantiation.&nbsp; <p><b>T</b> is not required be a complete type.&nbsp;
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p> See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
<p>Constructs a <tt>scoped_ptr</tt>, storing a copy of <tt>p</tt>, which must <p>Constructs a <tt>scoped_ptr</tt>, storing a copy of <tt>p</tt>, which must
have been allocated via a C++ <tt>new</tt> expression or be 0.</p> have been allocated via a C++ <tt>new</tt> expression or be 0.</p>
<h3><a name="scoped_ptr_~scoped_ptr">scoped_ptr destructor</a></h3> <h3><a name="scoped_ptr_~scoped_ptr">scoped_ptr destructor</a></h3>
<pre>~scoped_ptr();</pre> <pre>~scoped_ptr();</pre>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>Deletes the object pointed to by the stored pointer.&nbsp; Note that in C++, <tt>delete</tt> <p>Deletes the object pointed to by the stored pointer.&nbsp; Note that in C++, <tt>delete</tt>
on a pointer with a value of 0 is harmless.</p> on a pointer with a value of 0 is harmless.</p>
<p>Does not throw exceptions.</p> <p>Does not throw exceptions.</p>
<h3>scoped_ptr <a name="scoped_ptr_reset">reset</a></h3> <h3>scoped_ptr <a name="scoped_ptr_reset">reset</a></h3>
<pre>void reset( T* p=0 );</pre> <pre>void reset( T* p=0 );</pre>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>If p is not equal to the stored pointer, deletes the object pointed to by the <p>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 stored pointer and then stores a copy of p, which must have been allocated via a
C++ <tt>new</tt> expression or be 0.</p> C++ <tt>new</tt> expression or be 0.</p>
<p>Does not throw exceptions.</p> <p>Does not throw exceptions.</p>
<h3>scoped_ptr <a name="scoped_ptr_operator*">operator*</a></h3> <h3>scoped_ptr <a name="scoped_ptr_operator*">operator*</a></h3>
<pre>T&amp; operator*() const; // never throws</pre> <pre>T&amp; operator*() const; // never throws</pre>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>Returns a reference to the object pointed to by the stored pointer.</p> <p>Returns a reference to the object pointed to by the stored pointer.</p>
<h3>scoped_ptr <a name="scoped_ptr_operator-&gt;">operator-&gt;</a> and <a name="scoped_ptr_get">get</a></h3> <h3>scoped_ptr <a name="scoped_ptr_operator-&gt;">operator-&gt;</a> and <a name="scoped_ptr_get">get</a></h3>
<pre>T* operator-&gt;() const; // never throws <pre>T* operator-&gt;() const; // never throws
T* get() const; // never throws</pre> T* get() const; // never throws</pre>
<p><b>T</b> is required be a complete type at point of instantiation of <p><b>T</b> is not required by get() be a complete type.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
operator-&gt;().&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p><b>T</b> is not required be a complete type at point of instantiation of
get().&nbsp; See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
<p>Both return the stored pointer.</p> <p>Both return the stored pointer.</p>
<h2>Class <a name="scoped_ptr_example">scoped_ptr example</a>s</h2> <h2>Class <a name="scoped_ptr_example">scoped_ptr example</a>s</h2>
<pre>#include &lt;iostream&gt; <pre>#include &lt;iostream&gt;
@@ -118,17 +111,37 @@ output:</p>
2 2
Buckle my shoe</pre> Buckle my shoe</pre>
</blockquote> </blockquote>
<h2>Handle/Body Idiom</h2> <h2>Rationale</h2>
<p>One common usage of <b>scoped_ptr</b> is to implement a handle/body idiom which avoids exposing the body (implementation) in the header <p>The primary reason to use <b> scoped_ptr</b> rather than <b> auto_ptr</b> 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.</p>
<p>A secondary reason to use <b> scoped_ptr</b> is to prevent a later maintenance programmer from adding a function that actually transfers
ownership by returning the <b> auto_ptr</b> (because the maintenance programmer saw
<b>auto_ptr</b>, and assumed ownership could safely be transferred.)&nbsp;</p>
<p>Think of <b>bool</b> vs <b>int</b>. We all know that under the covers <b> bool</b> is usually
just an <b>int</b>. Indeed, some argued against including <b> bool</b> in the
C++ standard because of that. But by coding <b> bool</b> rather than <b> int</b>, you tell your readers
what your intent is. Same with <b> scoped_ptr</b> - you are signaling intent.</p>
<p>It has been suggested that <b>boost::scoped_ptr&lt;T&gt;</b> is equivalent to
<b>std::auto_ptr&lt;T> const</b>.&nbsp; Ed Brey pointed out, however, that
reset() will not work on a <b>std::auto_ptr&lt;T> const.</b></p>
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
<p>One common usage of <b>scoped_ptr</b> is to implement a handle/body (also
called pimpl) idiom which avoids exposing the body (implementation) in the header
file.</p> file.</p>
<p>The <a href="scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a> <p>The <a href="scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a>
sample program includes a header file, <a href="scoped_ptr_example.hpp">scoped_ptr_example.hpp</a>, sample program includes a header file, <a href="scoped_ptr_example.hpp">scoped_ptr_example.hpp</a>,
which uses a <b>scoped_ptr&lt;&gt;</b> to an incomplete type to hide the which uses a <b>scoped_ptr&lt;&gt;</b> to an incomplete type to hide the
implementation.&nbsp;&nbsp; The implementation.&nbsp;&nbsp; The
instantiation of member functions which require a complete type occurs in the <a href="scoped_ptr_example.cpp">scoped_ptr_example.cpp</a> instantiation of member functions which require a complete type occurs in the <a href="scoped_ptr_example.cpp">scoped_ptr_example.cpp</a>
implementation file.&nbsp;</p> implementation file.</p>
<h2>FAQ</h2>
<p><b>Q</b>. Why doesn't <b>scoped_ptr</b> have a release() member?<br>
<b>A</b>. Because the whole point of <b>scoped_ptr</b> is to signal intent not
to transfer ownership.&nbsp; Use <b>std::auto_ptr</b> if ownership transfer is
required.</p>
<hr> <hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->22 May 2001<!--webbot bot="Timestamp" endspan i-checksum="15106" --></p> <p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->24 May 2001<!--webbot bot="Timestamp" endspan i-checksum="15110" --></p>
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, <p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
modify, sell and distribute this document is granted provided this copyright modify, sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &quot;as is&quot; notice appears in all copies. This document is provided &quot;as is&quot;

View File

@@ -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 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 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.</p> leave array A dangling with a use_count() of 1.</p>
<p>A heavier duty alternative to a <strong>shared_array</strong> is a <strong>shared_ptr</strong> <p>A C++ Standard Library <strong>vector</strong> is <strong> </strong>a <strong>
to a C++ Standard Library <strong>vector</strong>.</p> </strong>heavier duty alternative to a <strong>shared_array</strong>.</p>
<p>The class is a template parameterized on <tt>T</tt>, the type of the object <p>The class is a template parameterized on <tt>T</tt>, the type of the object
pointed to.&nbsp;&nbsp; <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common pointed to.&nbsp;&nbsp; <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
requirements</a>.</p> requirements</a>.</p>
<h2>Class shared_array Synopsis</h2> <h2>Class shared_array Synopsis</h2>
<pre>#include &lt;boost/smart_ptr.hpp&gt; <pre>#include &lt;<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>&gt;
namespace boost { namespace boost {
template&lt;typename T&gt; class shared_array { template&lt;typename T&gt; class shared_array {
@@ -108,23 +108,17 @@ name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.</p>
<p>Provides the type of the stored pointer.</p> <p>Provides the type of the stored pointer.</p>
<h3><a name="shared_array_ctor">shared_array constructors</a></h3> <h3><a name="shared_array_ctor">shared_array constructors</a></h3>
<pre>explicit shared_array( T* p=0 );</pre> <pre>explicit shared_array( T* p=0 );</pre>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>Constructs a <strong>shared_array</strong>, storing a copy of <tt>p</tt>, <p>Constructs a <strong>shared_array</strong>, storing a copy of <tt>p</tt>,
which must have been allocated via a C++ <tt>new</tt>[] expression or be 0. which must have been allocated via a C++ <tt>new</tt>[] expression or be 0.
Afterwards, use_count() is 1 (even if p==0; see <a href="#shared_array_~shared_array">~shared_array</a>).</p> Afterwards, use_count() is 1 (even if p==0; see <a href="#shared_array_~shared_array">~shared_array</a>).</p>
<p>The only exception which may be thrown is <tt>std::bad_alloc</tt>.&nbsp; If <p>The only exception which may be thrown is <tt>std::bad_alloc</tt>.&nbsp; If
an exception is thrown,&nbsp; <tt>delete[] p</tt> is called.</p> an exception is thrown,&nbsp; <tt>delete[] p</tt> is called.</p>
<pre>shared_array( const shared_array&amp; r); // never throws</pre> <pre>shared_array( const shared_array&amp; r); // never throws</pre>
<p><b>T</b> is not required be a complete type at point of instantiation.&nbsp;
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
<p>Constructs a <strong>shared_array</strong>, as if by storing a copy of the <p>Constructs a <strong>shared_array</strong>, as if by storing a copy of the
pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong> pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
for all copies is 1 more than the initial <strong>r.use_count()</strong>.</p> for all copies is 1 more than the initial <strong>r.use_count()</strong>.</p>
<h3><a name="shared_array_~shared_array">shared_array destructor</a></h3> <h3><a name="shared_array_~shared_array">shared_array destructor</a></h3>
<pre>~shared_array();</pre> <pre>~shared_array();</pre>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>If <strong>use_count()</strong> == 1, deletes the array pointed to by the <p>If <strong>use_count()</strong> == 1, deletes the array pointed to by the
stored pointer.&nbsp;Otherwise, <strong>use_count()</strong> for any remaining stored pointer.&nbsp;Otherwise, <strong>use_count()</strong> for any remaining
copies is decremented by 1. Note that in C++ <tt>delete</tt>[] on a pointer with copies is decremented by 1. Note that in C++ <tt>delete</tt>[] on a pointer with
@@ -132,8 +126,6 @@ a value of 0 is harmless.</p>
<p>Does not throw exceptions.</p> <p>Does not throw exceptions.</p>
<h3>shared_array <a name="shared_array_operator=">operator=</a></h3> <h3>shared_array <a name="shared_array_operator=">operator=</a></h3>
<pre>shared_array&amp; operator=( const shared_array&amp; r); // never throws</pre> <pre>shared_array&amp; operator=( const shared_array&amp; r); // never throws</pre>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>First, if <strong>use_count()</strong> == 1, deletes the array pointed to by <p>First, if <strong>use_count()</strong> == 1, deletes the array pointed to by
the stored pointer.&nbsp;Otherwise, <strong>use_count()</strong> for any the stored pointer.&nbsp;Otherwise, <strong>use_count()</strong> for any
remaining copies is decremented by 1. Note that in C++ <tt>delete</tt>[] on a remaining copies is decremented by 1. Note that in C++ <tt>delete</tt>[] on a
@@ -143,8 +135,6 @@ of the pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</st
for all copies is 1 more than the initial <strong>r.use_count()</strong>.&nbsp;</p> for all copies is 1 more than the initial <strong>r.use_count()</strong>.&nbsp;</p>
<h3>shared_array <a name="shared_array_reset">reset</a></h3> <h3>shared_array <a name="shared_array_reset">reset</a></h3>
<pre>void reset( T* p=0 );</pre> <pre>void reset( T* p=0 );</pre>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>First, if <strong>use_count()</strong> == 1, deletes the array pointed to by <p>First, if <strong>use_count()</strong> == 1, deletes the array pointed to by
the stored pointer.&nbsp;Otherwise, <strong>use_count()</strong> for any the stored pointer.&nbsp;Otherwise, <strong>use_count()</strong> for any
remaining copies is decremented by 1. Note that in C++&nbsp; <tt>delete</tt>[] remaining copies is decremented by 1. Note that in C++&nbsp; <tt>delete</tt>[]
@@ -157,8 +147,6 @@ see <a href="#shared_array_~shared_array">~shared_array</a>).</p>
an exception is thrown,&nbsp; <tt>delete[] p</tt> is called.</p> an exception is thrown,&nbsp; <tt>delete[] p</tt> is called.</p>
<h3>shared_array <a name="shared_array_operator[]">operator[]</a></h3> <h3>shared_array <a name="shared_array_operator[]">operator[]</a></h3>
<p><tt>T&amp; operator[](std::size_t i) const; // never throws</tt></p> <p><tt>T&amp; operator[](std::size_t i) const; // never throws</tt></p>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>Returns a reference to element <tt>i</tt> of the array pointed to by the <p>Returns a reference to element <tt>i</tt> of the array pointed to by the
stored pointer.</p> stored pointer.</p>
<p>Behavior is undefined (and almost certainly undesirable) if <tt>get()==0</tt>, <p>Behavior is undefined (and almost certainly undesirable) if <tt>get()==0</tt>,
@@ -166,29 +154,30 @@ or if <tt>i</tt> is less than 0 or is greater or equal to the number of elements
in the array.</p> in the array.</p>
<h3>shared_array <a name="shared_array_get">get</a></h3> <h3>shared_array <a name="shared_array_get">get</a></h3>
<pre>T* get() const; // never throws</pre> <pre>T* get() const; // never throws</pre>
<p><b>T</b> is not required be a complete type at point of instantiation.&nbsp; <p><b>T</b> is not required be a complete type.&nbsp;
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p> See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
<p>Returns the stored pointer.</p> <p>Returns the stored pointer.</p>
<h3>shared_array<a name="shared_array_use_count"> use_count</a></h3> <h3>shared_array<a name="shared_array_use_count"> use_count</a></h3>
<p><tt>long use_count() const; // never throws</tt></p> <p><tt>long use_count() const; // never throws</tt></p>
<p><b>T</b> is not required be a complete type at point of instantiation.&nbsp; <p><b>T</b> is not required be a complete type.&nbsp;
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p> See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
<p>Returns the number of <strong>shared_arrays</strong> sharing ownership of the <p>Returns the number of <strong>shared_arrays</strong> sharing ownership of the
stored pointer.</p> stored pointer.</p>
<h3>shared_array <a name="shared_array_unique">unique</a></h3> <h3>shared_array <a name="shared_array_unique">unique</a></h3>
<p><tt>bool unique() const; // never throws</tt></p> <p><tt>bool unique() const; // never throws</tt></p>
<p><b>T</b> is not required be a complete type at point of instantiation.&nbsp; <p><b>T</b> is not required be a complete type.&nbsp;
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p> See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
<p>Returns <strong>use_count()</strong> == 1.</p> <p>Returns <strong>use_count()</strong> == 1.</p>
<h3><a name="shared_array_swap">shared_array swap</a></h3> <h3><a name="shared_array_swap">shared_array swap</a></h3>
<p><code>void swap( shared_array&lt;T&gt;&amp; other ) throw()</code></p> <p><code>void swap( shared_array&lt;T&gt;&amp; other ) throw()</code></p>
<p><b>T</b> is not required be a complete type at point of instantiation.&nbsp; <p><b>T</b> is not required be a complete type.&nbsp;
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p> See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
<p>Swaps the two smart pointers, as if by std::swap.</p> <p>Swaps the two smart pointers, as if by std::swap.</p>
<h2>Class <a name="shared_array_example">shared_array example</a></h2> <h2>Class <a name="shared_array_example">shared_array example</a></h2>
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p> <p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
<hr> <hr>
<p>Revised December 8, 1999</p> <p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->24 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13964" -->
</p>
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, <p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
modify, sell and distribute this document is granted provided this copyright modify, sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &quot;as is&quot; notice appears in all copies. This document is provided &quot;as is&quot;

View File

@@ -34,7 +34,7 @@ object A dangling with a use_count() of 1.</p>
pointed to.&nbsp;&nbsp; <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common pointed to.&nbsp;&nbsp; <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
requirements</a>.</p> requirements</a>.</p>
<h2>Class shared_ptr Synopsis</h2> <h2>Class shared_ptr Synopsis</h2>
<pre>#include &lt;boost/smart_ptr.hpp&gt; <pre>#include &lt;<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>&gt;
namespace boost { namespace boost {
template&lt;typename T&gt; class shared_ptr { template&lt;typename T&gt; class shared_ptr {
@@ -118,8 +118,6 @@ the macro name BOOST_NO_MEMBER_TEMPLATES is defined.</p>
<p>Provides the type of the stored pointer.</p> <p>Provides the type of the stored pointer.</p>
<h3><a name="shared_ptr_ctor">shared_ptr constructors</a></h3> <h3><a name="shared_ptr_ctor">shared_ptr constructors</a></h3>
<pre>explicit shared_ptr( T* p=0 );</pre> <pre>explicit shared_ptr( T* p=0 );</pre>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>Constructs a <strong>shared_ptr</strong>, storing a copy of <tt>p</tt>, which <p>Constructs a <strong>shared_ptr</strong>, storing a copy of <tt>p</tt>, which
must have been allocated via a C++ <tt>new</tt> expression or be 0. Afterwards, <strong>use_count()</strong> must have been allocated via a C++ <tt>new</tt> expression or be 0. Afterwards, <strong>use_count()</strong>
is 1 (even if p==0; see <a href="#shared_ptr_~shared_ptr">~shared_ptr</a>).</p> is 1 (even if p==0; see <a href="#shared_ptr_~shared_ptr">~shared_ptr</a>).</p>
@@ -130,8 +128,6 @@ template&lt;typename Y&gt;
shared_ptr(const shared_ptr&lt;Y&gt;&amp; r); // never throws shared_ptr(const shared_ptr&lt;Y&gt;&amp; r); // never throws
template&lt;typename Y&gt; template&lt;typename Y&gt;
shared_ptr(std::auto_ptr&lt;Y&gt;&amp; r);</pre> shared_ptr(std::auto_ptr&lt;Y&gt;&amp; r);</pre>
<p><b>T</b> is not required be a complete type at point of instantiation.&nbsp;
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
<p>Constructs a <strong>shared_ptr</strong>, as if by storing a copy of the <p>Constructs a <strong>shared_ptr</strong>, as if by storing a copy of the
pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong> pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
for all copies is 1 more than the initial <strong>r.use_count()</strong>, or 1 for all copies is 1 more than the initial <strong>r.use_count()</strong>, or 1
@@ -142,8 +138,6 @@ is <tt>std::bad_alloc</tt>.&nbsp;&nbsp; If an exception is thrown, that
constructor has no effect.</p> constructor has no effect.</p>
<h3><a name="shared_ptr_~shared_ptr">shared_ptr destructor</a></h3> <h3><a name="shared_ptr_~shared_ptr">shared_ptr destructor</a></h3>
<pre>~shared_ptr();</pre> <pre>~shared_ptr();</pre>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>If <strong>use_count()</strong> == 1, deletes the object pointed to by the <p>If <strong>use_count()</strong> == 1, deletes the object pointed to by the
stored pointer.&nbsp;Otherwise, <strong>use_count()</strong> for any remaining stored pointer.&nbsp;Otherwise, <strong>use_count()</strong> for any remaining
copies is decremented by 1. Note that in C++&nbsp; <tt>delete</tt> on a pointer copies is decremented by 1. Note that in C++&nbsp; <tt>delete</tt> on a pointer
@@ -155,8 +149,6 @@ template&lt;typename Y&gt;
shared_ptr&amp; operator=(const shared_ptr&lt;Y&gt;&amp; r); shared_ptr&amp; operator=(const shared_ptr&lt;Y&gt;&amp; r);
template&lt;typename Y&gt; template&lt;typename Y&gt;
shared_ptr&amp; operator=(std::auto_ptr&lt;Y&gt;&amp; r);</pre> shared_ptr&amp; operator=(std::auto_ptr&lt;Y&gt;&amp; r);</pre>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>First, if <strong>use_count()</strong> == 1, deletes the object pointed to by <p>First, if <strong>use_count()</strong> == 1, deletes the object pointed to by
the stored pointer.&nbsp;Otherwise, <strong>use_count()</strong> for any the stored pointer.&nbsp;Otherwise, <strong>use_count()</strong> for any
remaining copies is decremented by 1. Note that in C++&nbsp; <tt>delete</tt> on remaining copies is decremented by 1. Note that in C++&nbsp; <tt>delete</tt> on
@@ -172,8 +164,6 @@ is <tt>std::bad_alloc</tt>.&nbsp;&nbsp; If an exception is thrown, the function
has no effect.</p> has no effect.</p>
<h3>shared_ptr <a name="shared_ptr_reset">reset</a></h3> <h3>shared_ptr <a name="shared_ptr_reset">reset</a></h3>
<pre>void reset( T* p=0 );</pre> <pre>void reset( T* p=0 );</pre>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>First, if <strong>use_count()</strong> == 1, deletes the object pointed to by <p>First, if <strong>use_count()</strong> == 1, deletes the object pointed to by
the stored pointer.&nbsp;Otherwise, <strong>use_count()</strong> for any the stored pointer.&nbsp;Otherwise, <strong>use_count()</strong> for any
remaining copies is decremented by 1.&nbsp;</p> remaining copies is decremented by 1.&nbsp;</p>
@@ -186,32 +176,26 @@ on a pointer with a value of 0 is harmless.</p>
an exception is thrown,&nbsp; <tt>delete p</tt> is called.</p> an exception is thrown,&nbsp; <tt>delete p</tt> is called.</p>
<h3>shared_ptr <a name="shared_ptr_operator*">operator*</a></h3> <h3>shared_ptr <a name="shared_ptr_operator*">operator*</a></h3>
<pre>T&amp; operator*() const; // never throws</pre> <pre>T&amp; operator*() const; // never throws</pre>
<p><b>T</b> is required be a complete type at point of instantiation.&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p>Returns a reference to the object pointed to by the stored pointer.</p> <p>Returns a reference to the object pointed to by the stored pointer.</p>
<h3>shared_ptr <a name="shared_ptr_operator-&gt;">operator-&gt;</a> and <a name="shared_ptr_get">get</a></h3> <h3>shared_ptr <a name="shared_ptr_operator-&gt;">operator-&gt;</a> and <a name="shared_ptr_get">get</a></h3>
<pre>T* operator-&gt;() const; // never throws <pre>T* operator-&gt;() const; // never throws
T* get() const; // never throws</pre> T* get() const; // never throws</pre>
<p><b>T</b> is required be a complete type at point of instantiation of <p><b>T</b> is not required by get() to be a complete type .&nbsp; See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
operator-&gt;().&nbsp; See <a href="smart_ptr.htm#Common requirements">Common
Requirements</a>.</p>
<p><b>T</b> is not required be a complete type at point of instantiation of
get().&nbsp; See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
<p>Both return the stored pointer.</p> <p>Both return the stored pointer.</p>
<h3>shared_ptr<a name="shared_ptr_use_count"> use_count</a></h3> <h3>shared_ptr<a name="shared_ptr_use_count"> use_count</a></h3>
<p><tt>long use_count() const; // never throws</tt></p> <p><tt>long use_count() const; // never throws</tt></p>
<p><b>T</b> is not required be a complete type at point of instantiation.&nbsp; <p><b>T</b> is not required be a complete type.&nbsp;
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p> See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
<p>Returns the number of <strong>shared_ptrs</strong> sharing ownership of the <p>Returns the number of <strong>shared_ptrs</strong> sharing ownership of the
stored pointer.</p> stored pointer.</p>
<h3>shared_ptr <a name="shared_ptr_unique">unique</a></h3> <h3>shared_ptr <a name="shared_ptr_unique">unique</a></h3>
<p><tt>bool unique() const; // never throws</tt></p> <p><tt>bool unique() const; // never throws</tt></p>
<p><b>T</b> is not required be a complete type at point of instantiation.&nbsp; <p><b>T</b> is not required be a complete type.&nbsp;
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p> See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
<p>Returns <strong>use_count()</strong> == 1.</p> <p>Returns <strong>use_count()</strong> == 1.</p>
<h3><a name="shared_ptr_swap">shared_ptr swap</a></h3> <h3><a name="shared_ptr_swap">shared_ptr swap</a></h3>
<p><code>void swap( shared_ptr&lt;T&gt;&amp; other ) throw()</code></p> <p><code>void swap( shared_ptr&lt;T&gt;&amp; other ) throw()</code></p>
<p><b>T</b> is not required be a complete type at point of instantiation.&nbsp; <p><b>T</b> is not required be a complete type.&nbsp;
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p> See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
<p>Swaps the two smart pointers, as if by std::swap.</p> <p>Swaps the two smart pointers, as if by std::swap.</p>
<h2>Class <a name="shared_ptr_example">shared_ptr example</a></h2> <h2>Class <a name="shared_ptr_example">shared_ptr example</a></h2>
@@ -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 More complicated yet, the container operations may throw exceptions under a
variety of circumstances.&nbsp; Without using a smart pointer, memory and variety of circumstances.&nbsp; Without using a smart pointer, memory and
exception management would be a nightmare.</p> exception management would be a nightmare.</p>
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
<p>One common usage of <b>shared_ptr</b> is to implement a handle/body (also
called pimpl) idiom which avoids exposing the body (implementation) in the header
file.</p>
<p>The <a href="shared_ptr_example2_test.cpp">shared_ptr_example2_test.cpp</a>
sample program includes a header file, <a href="shared_ptr_example2.hpp">shared_ptr_example2.hpp</a>,
which uses a <b>shared_ptr&lt;&gt;</b> to an incomplete type to hide the
implementation.&nbsp;&nbsp; The
instantiation of member functions which require a complete type occurs in the <a href="shared_ptr_example2.cpp">shared_ptr_example2.cpp</a>
implementation file.</p>
<h2>FAQ</h2>
<p><b>Q</b>. Why doesn't <b>shared_ptr</b> have template parameters supplying
traits or policies to allow extensive user customization?<br>
<b>A</b>. Parameterization discourages users.&nbsp; <b>Shared_ptr</b> 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.&nbsp; Until then, <b>shared_ptr</b> is the
smart pointer of choice for a wide range of applications.</p>
<p><b>Q</b>. Why don't <b>shared_ptr</b> (and the other Boost smart pointers)
supply an automatic conversion to <b>T*</b>?<br>
<b>A</b>. Automatic conversion is believed to be too error prone.</p>
<hr> <hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->22 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13960" --> <p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->24 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13964" -->
</p> </p>
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, <p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
modify, sell and distribute this document is granted provided this copyright modify, sell and distribute this document is granted provided this copyright

View File

@@ -56,22 +56,20 @@ interest to those curious about performance issues.</p>
<p>These smart pointer classes have a template parameter, <tt><b>T</b></tt>, which <p>These smart pointer classes have a template parameter, <tt><b>T</b></tt>, which
specifies the type of the object pointed to by the smart pointer.&nbsp; The specifies the type of the object pointed to by the smart pointer.&nbsp; The
behavior of all four classes is undefined if the destructor or operator delete behavior of all four classes is undefined if the destructor or operator delete
for objects of type <tt><b>T</b></tt> throws exceptions.</p> for objects of type <tt><b>T</b></tt> throw exceptions.</p>
<p><code><b>T</b></code> may be an incomplete type at the point of smart pointer <p><code><b>T</b></code> may be an incomplete type at the point of smart pointer
declaration.&nbsp; Unless otherwise specified, it is required that <code><b>T</b></code> declaration.&nbsp; Unless otherwise specified, it is required that <code><b>T</b></code>
be a complete type at point of instantiation of all member functions.</p> 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 <a href="../utility/utility.htm#checked_delete">checked_delete()</a>.</p>
<h3>Rationale</h3> <h3>Rationale</h3>
<p>The requirements on <tt><b>T</b></tt> are carefully crafted to ensure safety <p>The requirements on <tt><b>T</b></tt> are carefully crafted to maximize safety
yet allow handle-body (aka pimpl) and similar idioms.&nbsp; In these idioms a yet allow handle-body (also called pimpl) and similar idioms.&nbsp; In these idioms a
smart pointer may appear in translation units where <tt><b>T</b></tt> is an smart pointer may appear in translation units where <tt><b>T</b></tt> is an
incomplete type.&nbsp; This separates interface from implementation and hides incomplete type.&nbsp; This separates interface from implementation and hides
implementation from translation units which merely use the interface.</p> implementation from translation units which merely use the interface.&nbsp;
<h3>Example</h3> Examples described in the documentation for specific smart pointers illustrate
<p>The <a href="scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a> use of smart pointers in these idioms.</p>
sample program includes a header file, <a href="scoped_ptr_example.hpp">scoped_ptr_example.hpp</a>,
which uses a <b>scoped_ptr&lt;&gt;</b> to an incomplete type.&nbsp;&nbsp; The
instantiation of member functions which require a complete type occurs in the <a href="scoped_ptr_example.cpp">scoped_ptr_example.cpp</a>
implementation file.&nbsp;</p>
<h2>Exception safety</h2> <h2>Exception safety</h2>
<p>Several functions in these smart pointer classes are specified as having <p>Several functions in these smart pointer classes are specified as having
&quot;no effect&quot; or &quot;no effect except such-and-such&quot; if an &quot;no effect&quot; or &quot;no effect except such-and-such&quot; if an
@@ -144,7 +142,7 @@ implementation.</p>
<p>See the Revision History section of the header for further contributors.</p> <p>See the Revision History section of the header for further contributors.</p>
<hr> <hr>
<p>Revised&nbsp; <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan <p>Revised&nbsp; <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan
-->22 May 2001<!--webbot bot="Timestamp" endspan i-checksum="15106" -->24 May 2001<!--webbot bot="Timestamp" endspan i-checksum="15110"
--></p> --></p>
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, <p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
modify, sell and distribute this document is granted provided this copyright modify, sell and distribute this document is granted provided this copyright

View File

@@ -6,20 +6,26 @@
// implied warranty, and with no claim as to its suitability for any purpose. // implied warranty, and with no claim as to its suitability for any purpose.
// Revision History // 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) // 29 Nov 99 added std::swap and associative container tests (Darin Adler)
// 25 Sep 99 added swap tests // 25 Sep 99 added swap tests
// 20 Jul 99 header name changed to .hpp // 20 Jul 99 header name changed to .hpp
// 20 Apr 99 additional error tests added. // 20 Apr 99 additional error tests added.
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <boost/smart_ptr.hpp> #include <boost/smart_ptr.hpp>
#include <cassert>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <set> #include <set>
#ifdef NDEBUG class Incomplete;
#error This test program makes no sense if NDEBUG is defined
#endif Incomplete * get_ptr( boost::shared_ptr<Incomplete>& incomplete )
{
return incomplete.get();
}
using namespace std; using namespace std;
using boost::scoped_ptr; using boost::scoped_ptr;
@@ -28,7 +34,7 @@ using boost::shared_ptr;
using boost::shared_array; using boost::shared_array;
template<typename T> template<typename T>
void ck( const T* v1, T v2 ) { assert( *v1 == v2 ); } void ck( const T* v1, T v2 ) { BOOST_TEST( *v1 == v2 ); }
namespace { namespace {
int UDT_use_count; // independent of pointer maintained counts int UDT_use_count; // independent of pointer maintained counts
@@ -48,169 +54,189 @@ class UDT {
void value( long v ) { value_ = v;; } void value( long v ) { value_ = v;; }
}; // UDT }; // 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>& incomplete )
{
return incomplete.get();
}
Incomplete * check_incomplete( shared_ptr<Incomplete>& incomplete,
shared_ptr<Incomplete>& i2 )
{
incomplete.swap(i2);
cout << incomplete.use_count() << " " << incomplete.unique() << endl;
return incomplete.get();
}
// main --------------------------------------------------------------------// // main --------------------------------------------------------------------//
// This isn't a very systematic test; it just hits some of the basics. // 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 // test scoped_ptr with a built-in type
long * lp = new long; long * lp = new long;
scoped_ptr<long> sp ( lp ); scoped_ptr<long> sp ( lp );
assert( sp.get() == lp ); BOOST_TEST( sp.get() == lp );
assert( lp == sp.get() ); BOOST_TEST( lp == sp.get() );
assert( &*sp == lp ); BOOST_TEST( &*sp == lp );
*sp = 1234568901L; *sp = 1234568901L;
assert( *sp == 1234568901L ); BOOST_TEST( *sp == 1234568901L );
assert( *lp == 1234568901L ); BOOST_TEST( *lp == 1234568901L );
ck( static_cast<long*>(sp.get()), 1234568901L ); ck( static_cast<long*>(sp.get()), 1234568901L );
ck( lp, *sp ); ck( lp, *sp );
sp.reset(); sp.reset();
assert( sp.get() == 0 ); BOOST_TEST( sp.get() == 0 );
// test scoped_ptr with a user defined type // test scoped_ptr with a user defined type
scoped_ptr<UDT> udt_sp ( new UDT( 999888777 ) ); scoped_ptr<UDT> udt_sp ( new UDT( 999888777 ) );
assert( udt_sp->value() == 999888777 ); BOOST_TEST( udt_sp->value() == 999888777 );
udt_sp.reset(); udt_sp.reset();
udt_sp.reset( new UDT( 111222333 ) ); udt_sp.reset( new UDT( 111222333 ) );
assert( udt_sp->value() == 111222333 ); BOOST_TEST( udt_sp->value() == 111222333 );
udt_sp.reset( new UDT( 333222111 ) ); 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 // test scoped_array with a build-in type
char * sap = new char [ 100 ]; char * sap = new char [ 100 ];
scoped_array<char> sa ( sap ); scoped_array<char> sa ( sap );
assert( sa.get() == sap ); BOOST_TEST( sa.get() == sap );
assert( sap == sa.get() ); BOOST_TEST( sap == sa.get() );
strcpy( sa.get(), "Hot Dog with mustard and relish" ); strcpy( sa.get(), "Hot Dog with mustard and relish" );
assert( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 ); BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 );
assert( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 ); BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 );
assert( sa[0] == 'H' ); BOOST_TEST( sa[0] == 'H' );
assert( sa[30] == 'h' ); BOOST_TEST( sa[30] == 'h' );
sa[0] = 'N'; sa[0] = 'N';
sa[4] = 'd'; 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(); sa.reset();
assert( sa.get() == 0 ); BOOST_TEST( sa.get() == 0 );
// test shared_ptr with a built-in type // test shared_ptr with a built-in type
int * ip = new int; int * ip = new int;
shared_ptr<int> cp ( ip ); shared_ptr<int> cp ( ip );
assert( ip == cp.get() ); BOOST_TEST( ip == cp.get() );
assert( cp.use_count() == 1 ); BOOST_TEST( cp.use_count() == 1 );
*cp = 54321; *cp = 54321;
assert( *cp == 54321 ); BOOST_TEST( *cp == 54321 );
assert( *ip == 54321 ); BOOST_TEST( *ip == 54321 );
ck( static_cast<int*>(cp.get()), 54321 ); ck( static_cast<int*>(cp.get()), 54321 );
ck( static_cast<int*>(ip), *cp ); ck( static_cast<int*>(ip), *cp );
shared_ptr<int> cp2 ( cp ); shared_ptr<int> cp2 ( cp );
assert( ip == cp2.get() ); BOOST_TEST( ip == cp2.get() );
assert( cp.use_count() == 2 ); BOOST_TEST( cp.use_count() == 2 );
assert( cp2.use_count() == 2 ); BOOST_TEST( cp2.use_count() == 2 );
assert( *cp == 54321 ); BOOST_TEST( *cp == 54321 );
assert( *cp2 == 54321 ); BOOST_TEST( *cp2 == 54321 );
ck( static_cast<int*>(cp2.get()), 54321 ); ck( static_cast<int*>(cp2.get()), 54321 );
ck( static_cast<int*>(ip), *cp2 ); ck( static_cast<int*>(ip), *cp2 );
shared_ptr<int> cp3 ( cp ); shared_ptr<int> cp3 ( cp );
assert( cp.use_count() == 3 ); BOOST_TEST( cp.use_count() == 3 );
assert( cp2.use_count() == 3 ); BOOST_TEST( cp2.use_count() == 3 );
assert( cp3.use_count() == 3 ); BOOST_TEST( cp3.use_count() == 3 );
cp.reset(); cp.reset();
assert( cp2.use_count() == 2 ); BOOST_TEST( cp2.use_count() == 2 );
assert( cp3.use_count() == 2 ); BOOST_TEST( cp3.use_count() == 2 );
assert( cp.use_count() == 1 ); BOOST_TEST( cp.use_count() == 1 );
cp.reset( new int ); cp.reset( new int );
*cp = 98765; *cp = 98765;
assert( *cp == 98765 ); BOOST_TEST( *cp == 98765 );
*cp3 = 87654; *cp3 = 87654;
assert( *cp3 == 87654 ); BOOST_TEST( *cp3 == 87654 );
assert( *cp2 == 87654 ); BOOST_TEST( *cp2 == 87654 );
cp.swap( cp3 ); cp.swap( cp3 );
assert( *cp == 87654 ); BOOST_TEST( *cp == 87654 );
assert( *cp2 == 87654 ); BOOST_TEST( *cp2 == 87654 );
assert( *cp3 == 98765 ); BOOST_TEST( *cp3 == 98765 );
cp.swap( cp3 ); cp.swap( cp3 );
assert( *cp == 98765 ); BOOST_TEST( *cp == 98765 );
assert( *cp2 == 87654 ); BOOST_TEST( *cp2 == 87654 );
assert( *cp3 == 87654 ); BOOST_TEST( *cp3 == 87654 );
cp2 = cp2; cp2 = cp2;
assert( cp2.use_count() == 2 ); BOOST_TEST( cp2.use_count() == 2 );
assert( *cp2 == 87654 ); BOOST_TEST( *cp2 == 87654 );
cp = cp2; cp = cp2;
assert( cp2.use_count() == 3 ); BOOST_TEST( cp2.use_count() == 3 );
assert( *cp2 == 87654 ); BOOST_TEST( *cp2 == 87654 );
assert( cp.use_count() == 3 ); BOOST_TEST( cp.use_count() == 3 );
assert( *cp == 87654 ); BOOST_TEST( *cp == 87654 );
shared_ptr<int> cp4; shared_ptr<int> cp4;
swap( cp2, cp4 ); swap( cp2, cp4 );
assert( cp4.use_count() == 3 ); BOOST_TEST( cp4.use_count() == 3 );
assert( *cp4 == 87654 ); BOOST_TEST( *cp4 == 87654 );
assert( cp2.get() == 0 ); BOOST_TEST( cp2.get() == 0 );
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
set< shared_ptr<int> > scp; set< shared_ptr<int> > scp;
scp.insert(cp4); scp.insert(cp4);
assert( scp.find(cp4) != scp.end() ); BOOST_TEST( scp.find(cp4) != scp.end() );
assert( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) ); BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) );
#endif #endif
// test shared_array with a built-in type // test shared_array with a built-in type
char * cap = new char [ 100 ]; char * cap = new char [ 100 ];
shared_array<char> ca ( cap ); shared_array<char> ca ( cap );
assert( ca.get() == cap ); BOOST_TEST( ca.get() == cap );
assert( cap == ca.get() ); BOOST_TEST( cap == ca.get() );
assert( &ca[0] == cap ); BOOST_TEST( &ca[0] == cap );
strcpy( ca.get(), "Hot Dog with mustard and relish" ); strcpy( ca.get(), "Hot Dog with mustard and relish" );
assert( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 ); BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 );
assert( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 ); BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 );
assert( ca[0] == 'H' ); BOOST_TEST( ca[0] == 'H' );
assert( ca[30] == 'h' ); BOOST_TEST( ca[30] == 'h' );
shared_array<char> ca2 ( ca ); shared_array<char> ca2 ( ca );
shared_array<char> ca3 ( ca2 ); shared_array<char> ca3 ( ca2 );
ca[0] = 'N'; ca[0] = 'N';
ca[4] = 'd'; ca[4] = 'd';
assert( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 ); BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 );
assert( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 ); BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 );
assert( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 ); BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 );
assert( ca.use_count() == 3 ); BOOST_TEST( ca.use_count() == 3 );
assert( ca2.use_count() == 3 ); BOOST_TEST( ca2.use_count() == 3 );
assert( ca3.use_count() == 3 ); BOOST_TEST( ca3.use_count() == 3 );
ca2.reset(); ca2.reset();
assert( ca.use_count() == 2 ); BOOST_TEST( ca.use_count() == 2 );
assert( ca3.use_count() == 2 ); BOOST_TEST( ca3.use_count() == 2 );
assert( ca2.use_count() == 1 ); BOOST_TEST( ca2.use_count() == 1 );
ca.reset(); ca.reset();
assert( ca.get() == 0 ); BOOST_TEST( ca.get() == 0 );
shared_array<char> ca4; shared_array<char> ca4;
swap( ca3, ca4 ); swap( ca3, ca4 );
assert( ca4.use_count() == 1 ); BOOST_TEST( ca4.use_count() == 1 );
assert( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 );
assert( ca3.get() == 0 ); BOOST_TEST( ca3.get() == 0 );
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
set< shared_array<char> > sca; set< shared_array<char> > sca;
sca.insert(ca4); sca.insert(ca4);
assert( sca.find(ca4) != sca.end() ); BOOST_TEST( sca.find(ca4) != sca.end() );
assert( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) ); BOOST_TEST( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) );
#endif #endif
// test shared_array with user defined type // test shared_array with user defined type
@@ -221,38 +247,38 @@ int main() {
udta[2].value( 333 ); udta[2].value( 333 );
shared_array<UDT> udta2 ( udta ); shared_array<UDT> udta2 ( udta );
assert( udta[0].value() == 111 ); BOOST_TEST( udta[0].value() == 111 );
assert( udta[1].value() == 222 ); BOOST_TEST( udta[1].value() == 222 );
assert( udta[2].value() == 333 ); BOOST_TEST( udta[2].value() == 333 );
assert( udta2[0].value() == 111 ); BOOST_TEST( udta2[0].value() == 111 );
assert( udta2[1].value() == 222 ); BOOST_TEST( udta2[1].value() == 222 );
assert( udta2[2].value() == 333 ); BOOST_TEST( udta2[2].value() == 333 );
udta2.reset(); udta2.reset();
assert( udta2.get() == 0 ); BOOST_TEST( udta2.get() == 0 );
assert( udta.use_count() == 1 ); BOOST_TEST( udta.use_count() == 1 );
assert( udta2.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 // test shared_ptr with a user defined type
UDT * up = new UDT; UDT * up = new UDT;
shared_ptr<UDT> sup ( up ); shared_ptr<UDT> sup ( up );
assert( up == sup.get() ); BOOST_TEST( up == sup.get() );
assert( sup.use_count() == 1 ); BOOST_TEST( sup.use_count() == 1 );
sup->value( 54321 ) ; sup->value( 54321 ) ;
assert( sup->value() == 54321 ); BOOST_TEST( sup->value() == 54321 );
assert( up->value() == 54321 ); BOOST_TEST( up->value() == 54321 );
shared_ptr<UDT> sup2; shared_ptr<UDT> sup2;
sup2 = sup; sup2 = sup;
assert( sup2->value() == 54321 ); BOOST_TEST( sup2->value() == 54321 );
assert( sup.use_count() == 2 ); BOOST_TEST( sup.use_count() == 2 );
assert( sup2.use_count() == 2 ); BOOST_TEST( sup2.use_count() == 2 );
sup2 = sup2; sup2 = sup2;
assert( sup2->value() == 54321 ); BOOST_TEST( sup2->value() == 54321 );
assert( sup.use_count() == 2 ); BOOST_TEST( sup.use_count() == 2 );
assert( sup2.use_count() == 2 ); BOOST_TEST( sup2.use_count() == 2 );
cout << "OK" << endl; cout << "OK" << endl;