| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | 
					
						
							| 
									
										
										
										
											2000-07-27 14:27:00 +00:00
										 |  |  | <html> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 	<head> | 
					
						
							|  |  |  | 		<title>shared_ptr</title> | 
					
						
							|  |  |  | 		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | 
					
						
							|  |  |  | 	</head> | 
					
						
							|  |  |  | 	<body text="#000000" bgColor="#ffffff"> | 
					
						
							|  |  |  | 		<h1><IMG height="86" alt="c++boost.gif (8819 bytes)" src="../../c++boost.gif" width="277" align="middle">shared_ptr  | 
					
						
							|  |  |  | 			class template</h1> | 
					
						
							|  |  |  | 		<p><A href="#Introduction">Introduction</A><br> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 			<a href="#BestPractices">Best Practices</a><br> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 			<A href="#Synopsis">Synopsis</A><br> | 
					
						
							|  |  |  | 			<A href="#Members">Members</A><br> | 
					
						
							|  |  |  | 			<A href="#functions">Free Functions</A><br> | 
					
						
							|  |  |  | 			<A href="#example">Example</A><br> | 
					
						
							|  |  |  | 			<A href="#Handle/Body">Handle/Body Idiom</A><br> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 			<a href="#ThreadSafety">Thread Safety</a><br> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 			<A href="#FAQ">Frequently Asked Questions</A><br> | 
					
						
							|  |  |  | 			<A href="smarttests.htm">Smart Pointer Timings</A></p> | 
					
						
							|  |  |  | 		<h2><a name="Introduction">Introduction</a></h2> | 
					
						
							|  |  |  | 		<p>The <b>shared_ptr</b> class template stores a pointer to a dynamically allocated  | 
					
						
							| 
									
										
										
										
											2002-09-16 15:26:52 +00:00
										 |  |  | 			object, typically with a C++ <EM>new-expression</EM> . The object pointed to is  | 
					
						
							|  |  |  | 			guaranteed to be deleted when the last <b>shared_ptr</b> pointing to it is  | 
					
						
							|  |  |  | 			destroyed or reset. See the <A href="#example">example</A>.</p> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<p>Every <b>shared_ptr</b> meets the <b>CopyConstructible</b> and <b>Assignable</b>  | 
					
						
							|  |  |  | 			requirements of the C++ Standard Library, and so can be used in standard  | 
					
						
							|  |  |  | 			library containers. Comparison operators are supplied so that <b>shared_ptr</b>  | 
					
						
							|  |  |  | 			works with the standard library's associative containers.</p> | 
					
						
							|  |  |  | 		<p>Normally, a <b>shared_ptr</b> cannot correctly hold a pointer to a dynamically  | 
					
						
							|  |  |  | 			allocated array. See <A href="shared_array.htm"><b>shared_array</b></A> for  | 
					
						
							|  |  |  | 			that usage.</p> | 
					
						
							| 
									
										
										
										
											2002-09-16 15:26:52 +00:00
										 |  |  | 		<p>Because the implementation uses reference counting, cycles of <b>shared_ptr</b> instances  | 
					
						
							|  |  |  | 			will not be reclaimed. For example, if <b>main()</b> holds a <b>shared_ptr</b> to | 
					
						
							|  |  |  | 			<b>A</b>, which directly or indirectly holds a <b>shared_ptr</b> back to <b>A</b>, | 
					
						
							|  |  |  | 			<b>A</b>'s use count will be 2. Destruction of the original <b>shared_ptr</b> will  | 
					
						
							|  |  |  | 			leave <b>A</b> dangling with a use count of 1. Use <A href="weak_ptr.htm">weak_ptr</A> | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 			to "break cycles."</p> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<p>The class template is parameterized on <b>T</b>, the type of the object pointed  | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 			to. <STRONG>shared_ptr</STRONG> and most of its member functions place no  | 
					
						
							|  |  |  | 			requirements on <STRONG>T</STRONG>; it is allowed to be an incomplete type, or <STRONG> | 
					
						
							|  |  |  | 				void</STRONG>. Member functions that do place additional requirements (<A href="#constructors">constructors</A>, | 
					
						
							|  |  |  | 			<A href="#reset">reset</A>) are explicitly documented below.</p> | 
					
						
							|  |  |  | 		<P><STRONG>shared_ptr<T></STRONG> can be implicitly converted to <STRONG>shared_ptr<U></STRONG> | 
					
						
							|  |  |  | 			whenever <STRONG>T*</STRONG> can be implicitly converted to <STRONG>U*</STRONG>.  | 
					
						
							|  |  |  | 			In particular, <STRONG>shared_ptr<T></STRONG> is implicitly convertible  | 
					
						
							|  |  |  | 			to <STRONG>shared_ptr<T const></STRONG>, to <STRONG>shared_ptr<U></STRONG> | 
					
						
							|  |  |  | 			where <STRONG>U</STRONG> is an accessible base of <STRONG>T</STRONG>, and to <STRONG> | 
					
						
							|  |  |  | 				shared_ptr<void></STRONG>.</P> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<h2><a name="BestPractices">Best Practices</a></h2> | 
					
						
							|  |  |  | 		<P>A simple guideline that nearly eliminates the possibility of memory leaks  | 
					
						
							|  |  |  | 			is: always use a named smart pointer variable to hold the result of <STRONG>new. </STRONG> | 
					
						
							|  |  |  | 			Every occurence of the <STRONG>new</STRONG> keyword in the code should have the  | 
					
						
							|  |  |  | 			form:</P> | 
					
						
							|  |  |  | 		<PRE>shared_ptr<T> p(new Y);</PRE> | 
					
						
							|  |  |  | 		<P>It is, of course, acceptable to use another smart pointer in place of <STRONG>shared_ptr</STRONG> | 
					
						
							|  |  |  | 			above; having <STRONG>T</STRONG> and <STRONG>Y</STRONG> be the same type, or  | 
					
						
							|  |  |  | 			passing arguments to <STRONG>Y</STRONG>'s constructor is also OK.</P> | 
					
						
							|  |  |  | 		<P>If you observe this guideline, it naturally follows that you will have no  | 
					
						
							|  |  |  | 			explicit <STRONG>delete</STRONG>s; <STRONG>try/catch</STRONG> constructs will  | 
					
						
							|  |  |  | 			be rare.</P> | 
					
						
							|  |  |  | 		<P>Avoid using unnamed <STRONG>shared_ptr</STRONG> temporaries to save typing; to  | 
					
						
							|  |  |  | 			see why this is dangerous, consider this example:</P> | 
					
						
							|  |  |  | 		<PRE> | 
					
						
							|  |  |  | void f(shared_ptr<int>, int); | 
					
						
							|  |  |  | int g(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ok() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     shared_ptr<int> p(new int(2)); | 
					
						
							|  |  |  |     f(p, g()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void bad() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     f(shared_ptr<int>(new int(2)), g()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | </PRE> | 
					
						
							|  |  |  | 		<P>The function <STRONG>ok</STRONG> follows the guideline to the letter, whereas <STRONG> | 
					
						
							|  |  |  | 				bad</STRONG> constructs the temporary <STRONG>shared_ptr</STRONG> in place,  | 
					
						
							|  |  |  | 			admitting the possibility of a memory leak. Since function arguments are  | 
					
						
							|  |  |  | 			evaluated in unspecified order, it is possible for <STRONG>new int(2)</STRONG> to  | 
					
						
							|  |  |  | 			be evaluated first, <STRONG>g()</STRONG> second, and we may never get to the <STRONG> | 
					
						
							|  |  |  | 				shared_ptr </STRONG>constructor if <STRONG>g</STRONG> throws an exception.  | 
					
						
							|  |  |  | 			See <A href="http://www.gotw.ca/gotw/056.htm">Herb Sutter's treatment</A> of  | 
					
						
							|  |  |  | 			the issue for more information.</P> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<h2><a name="Synopsis">Synopsis</a></h2> | 
					
						
							|  |  |  | 		<pre>namespace boost { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-15 13:31:58 +00:00
										 |  |  |   class use_count_is_zero: public std::exception; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |   template<typename T> class <A href="weak_ptr.htm" >weak_ptr</A>; | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   template<typename T> class shared_ptr { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public: | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |       typedef T <A href="#element_type" >element_type</A>; | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-19 16:23:07 +00:00
										 |  |  |       <A href="#constructors" >shared_ptr</A>(); | 
					
						
							|  |  |  |       template<typename Y> explicit <A href="#constructors" >shared_ptr</A>(Y * p); | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  |       template<typename Y, typename D> <A href="#constructors" >shared_ptr</A>(Y * p, D d); | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |       <A href="#destructor" >~shared_ptr</A>(); // never throws | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |       <A href="#constructors" >shared_ptr</A>(shared_ptr const & r); // never throws | 
					
						
							|  |  |  |       template<typename Y> <A href="#constructors" >shared_ptr</A>(shared_ptr<Y> const & r); // never throws | 
					
						
							| 
									
										
										
										
											2002-02-15 13:31:58 +00:00
										 |  |  |       explicit <A href="#constructors" >shared_ptr</A>(<A href="weak_ptr.htm" >weak_ptr</A> const & r); | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |       template<typename Y> <A href="#constructors" >shared_ptr</A>(std::auto_ptr<Y> & r); | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |       shared_ptr & <A href="#assignment" >operator=</A>(shared_ptr const & r); // never throws   | 
					
						
							|  |  |  |       template<typename Y> shared_ptr & <A href="#assignment" >operator=</A>(shared_ptr<Y> const & r); // never throws | 
					
						
							|  |  |  |       template<typename Y> shared_ptr & <A href="#assignment" >operator=</A>(std::auto_ptr<Y> & r); | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-15 13:31:58 +00:00
										 |  |  |       void <A href="#reset" >reset</A> (); | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  |       template<typename Y> void <A href="#reset" >reset</A> (Y * p); | 
					
						
							|  |  |  |       template<typename Y> template<typename D> void <A href="#reset" >reset</A>(Y * p, D d); | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |       T & <A href="#indirection" >operator*</A>() const; // never throws | 
					
						
							|  |  |  |       T * <A href="#indirection" >operator-></A>() const; // never throws | 
					
						
							|  |  |  |       T * <A href="#get" >get</A>() const; // never throws | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |       bool <A href="#unique" >unique</A>() const; // never throws | 
					
						
							|  |  |  |       long <A href="#use_count" >use_count</A>() const; // never throws | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-24 10:20:30 +00:00
										 |  |  |       operator <a href="#conversions"><i>unspecified-bool-type</i></a> () const; // never throws | 
					
						
							| 
									
										
										
										
											2002-02-15 14:46:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |       void <A href="#swap" >swap</A>(shared_ptr<T> & b); // never throws | 
					
						
							| 
									
										
										
										
											2000-07-27 14:27:00 +00:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  |   template<typename T, typename U> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |     bool <A href="#comparison" >operator==</A>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  |   template<typename T, typename U> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |     bool <A href="#comparison" >operator!=</A>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws | 
					
						
							| 
									
										
										
										
											2002-02-08 20:45:04 +00:00
										 |  |  |   template<typename T> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |     bool <A href="#comparison" >operator<</A>(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |   template<typename T> void <A href="#free-swap" >swap</A>(shared_ptr<T> & a, shared_ptr<T> & b); // never throws | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-27 16:02:26 +00:00
										 |  |  |   template<typename T> T * <A href="#get_pointer" >get_pointer</A>(shared_ptr<T> const & p); // never throws | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  |   template<typename T, typename U> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |     shared_ptr<T> <A href="#shared_static_cast" >shared_static_cast</A>(shared_ptr<U> const & r); // never throws | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  |   template<typename T, typename U> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |     shared_ptr<T> <A href="#shared_dynamic_cast" >shared_dynamic_cast</A>(shared_ptr<U> const & r); | 
					
						
							| 
									
										
										
										
											2002-02-06 19:42:04 +00:00
										 |  |  |   template<typename T, typename U> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |     shared_ptr<T> <A href="#shared_polymorphic_cast" >shared_polymorphic_cast</A>(shared_ptr<U> const & r); | 
					
						
							| 
									
										
										
										
											2002-02-06 19:42:04 +00:00
										 |  |  |   template<typename T, typename U> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  |     shared_ptr<T> <A href="#shared_polymorphic_downcast" >shared_polymorphic_downcast</A>(shared_ptr<U> const & r); // never throws | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | }</pre> | 
					
						
							| 
									
										
										
										
											2002-07-24 10:20:30 +00:00
										 |  |  | 		<P><EM>[It might be convenient to relax the requirements on <STRONG>shared_ptr</STRONG>'s  | 
					
						
							| 
									
										
										
										
											2002-09-16 15:26:52 +00:00
										 |  |  | 				signature, allowing an additional, defaulted, template parameter; the parameter  | 
					
						
							|  |  |  | 				can encode the threading model, for example. This would help in detecting  | 
					
						
							|  |  |  | 				possible ODR violations. On the other hand, using <STRONG>shared_ptr</STRONG> as  | 
					
						
							|  |  |  | 				an argument to a template template parameter requires an exact signature  | 
					
						
							|  |  |  | 				match.]</EM></P> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<h2><a name="Members">Members</a></h2> | 
					
						
							|  |  |  | 		<h3><a name="element_type">element_type</a></h3> | 
					
						
							|  |  |  | 		<pre>typedef T element_type;</pre> | 
					
						
							|  |  |  | 		<blockquote> | 
					
						
							|  |  |  | 			<p>Provides the type of the template parameter T.</p> | 
					
						
							|  |  |  | 		</blockquote> | 
					
						
							|  |  |  | 		<h3><a name="constructors">constructors</a></h3> | 
					
						
							| 
									
										
										
										
											2002-02-15 13:31:58 +00:00
										 |  |  | 		<pre>shared_ptr();</pre> | 
					
						
							|  |  |  | 		<blockquote> | 
					
						
							|  |  |  | 			<p><b>Effects:</b> Constructs a <b>shared_ptr</b>.</p> | 
					
						
							|  |  |  | 			<p><b>Postconditions:</b> <A href="#use_count">use count</A> is 1; the stored  | 
					
						
							|  |  |  | 				pointer is 0.</p> | 
					
						
							|  |  |  | 			<p><b>Throws:</b> <b>std::bad_alloc</b>.</p> | 
					
						
							|  |  |  | 			<p><b>Exception safety:</b> If an exception is thrown, the constructor has no  | 
					
						
							|  |  |  | 				effect.</p> | 
					
						
							|  |  |  | 		</blockquote> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<P><EM>[The poscondition of use_count() == 1 is too strong. Having the nothrow  | 
					
						
							|  |  |  | 				guarantee is important, since <STRONG>reset()</STRONG> is specified in terms of  | 
					
						
							|  |  |  | 				the default constructor, but the current specification requires that a count be  | 
					
						
							|  |  |  | 				allocated. Therefore, this postcondition will be dropped in a future release.  | 
					
						
							|  |  |  | 				The use count of a default-constructed <STRONG>shared_ptr</STRONG>, including  | 
					
						
							|  |  |  | 				all copies created from it, will probably be left unspecified.</EM></P> | 
					
						
							|  |  |  | 		<P><EM>There are two possible nothrow implementations, one stores 0 as a pointer to the  | 
					
						
							|  |  |  | 				reference count, the other uses a single statically allocated count for all  | 
					
						
							|  |  |  | 				default-constructed <STRONG>shared_ptr</STRONG>s. The second option is  | 
					
						
							|  |  |  | 				difficult to achieve in the current header-only reference implementation due to  | 
					
						
							|  |  |  | 				thread safety issues and initialization order, but it should not be precluded  | 
					
						
							|  |  |  | 				by the specification.</EM></P> | 
					
						
							|  |  |  | 		<P><EM>A future release may enable <STRONG>shared_ptr</STRONG> construction from a  | 
					
						
							|  |  |  | 				literal zero, for consistency with built-in pointers. It is not clear yet  | 
					
						
							|  |  |  | 				whether this constructor should be left implicit, enabling <STRONG>0</STRONG> to  | 
					
						
							|  |  |  | 				be used as a shorthand for <STRONG>shared_ptr<T>().</STRONG>]</EM></P> | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 		<pre>template<typename Y> explicit shared_ptr(Y * p);</pre> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<blockquote> | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 			<p><b>Requirements:</b> <b>p</b> must be convertible to <b>T *</b>. <STRONG>Y</STRONG> | 
					
						
							|  |  |  | 				must be a complete type. The expression <code>delete p</code> must be  | 
					
						
							|  |  |  | 				well-formed, must not invoke undefined behavior, and must not throw exceptions. | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 			</p> | 
					
						
							|  |  |  | 			<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b>.</p> | 
					
						
							|  |  |  | 			<p><b>Postconditions:</b> <A href="#use_count">use count</A> is 1.</p> | 
					
						
							|  |  |  | 			<p><b>Throws:</b> <b>std::bad_alloc</b>.</p> | 
					
						
							|  |  |  | 			<p><b>Exception safety:</b> If an exception is thrown, <code>delete p</code> is  | 
					
						
							|  |  |  | 				called.</p> | 
					
						
							|  |  |  | 			<P><STRONG>Notes:</STRONG> <B>p</B> must be a pointer to an object that was  | 
					
						
							|  |  |  | 				allocated via a C++ <B>new</B> expression or be 0. The postcondition that <A href="#use_count"> | 
					
						
							|  |  |  | 					use count</A> is 1 holds even if <b>p</b> is 0; invoking <STRONG>delete</STRONG> | 
					
						
							|  |  |  | 				on a pointer that has a value of 0 is harmless.</P> | 
					
						
							|  |  |  | 		</blockquote> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<P><EM>[This constructor has been changed to a template in order to remember the actual  | 
					
						
							|  |  |  | 				pointer type passed. The destructor will call <STRONG>delete</STRONG> with the  | 
					
						
							|  |  |  | 				same pointer, complete with its original type, even when <STRONG>T</STRONG> does  | 
					
						
							| 
									
										
										
										
											2002-07-23 19:12:40 +00:00
										 |  |  | 				not have a virtual destructor, or is <STRONG>void</STRONG>.</EM></P> | 
					
						
							|  |  |  | 		<P><EM>In the current implementation, if <STRONG>p</STRONG> is convertible to <STRONG>counted_base  | 
					
						
							|  |  |  | 					*</STRONG>, <STRONG>shared_ptr</STRONG> will use the embedded reference  | 
					
						
							|  |  |  | 				count supplied by <STRONG>counted_base</STRONG>. This is an (experimental)  | 
					
						
							|  |  |  | 				attempt to provide a way for <STRONG>shared_ptr</STRONG> to be constructed from  | 
					
						
							|  |  |  | 				a raw pointer such as <STRONG>this</STRONG>. A free function <STRONG>shared_from_this(q)</STRONG> | 
					
						
							|  |  |  | 				performs the conversion when <STRONG>q</STRONG> is convertible to <STRONG>counted_base  | 
					
						
							|  |  |  | 					const *</STRONG>.</EM></P> | 
					
						
							|  |  |  | 		<P><EM>The optional intrusive counting employed by the current implementation allows <STRONG> | 
					
						
							|  |  |  | 					shared_ptr</STRONG> to interoperate with <STRONG>intrusive_ptr</STRONG>, an  | 
					
						
							|  |  |  | 				experimental generic intrusive-counted smart pointer.</EM></P> | 
					
						
							|  |  |  | 		<P><EM> Another possible implementation is to use a global pointer-to-count map instead  | 
					
						
							|  |  |  | 				of intrusive counting. <STRONG>shared_from_this</STRONG> would no longer be  | 
					
						
							|  |  |  | 				O(1), which is a concern for some users, although I do not expect any  | 
					
						
							|  |  |  | 				performance problems, since the operation is rare. Maintaining a global  | 
					
						
							|  |  |  | 				map is difficult; it needs to be initialized before any <STRONG>shared_ptr</STRONG> | 
					
						
							|  |  |  | 				instances are constructed, and the initialization needs to be thread safe.  | 
					
						
							|  |  |  | 				In addition, under the Windows dynamic library model, it is possible for  | 
					
						
							|  |  |  | 				several maps to exist.</EM></P> | 
					
						
							|  |  |  | 		<P><EM> It is not yet clear which implementation should be used, or whether the  | 
					
						
							|  |  |  | 				specification should allow both; nevertheless, the ability to make a <STRONG>shared_ptr</STRONG> | 
					
						
							|  |  |  | 				from <STRONG>this</STRONG> is considered essential by experienced smart  | 
					
						
							|  |  |  | 				pointer users.</EM><EM>]</EM></P> | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 		<pre>template<typename Y, typename D> shared_ptr(Y * p, D d);</pre> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<blockquote> | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 			<p><b>Requirements:</b> <B>p</B> must be convertible to <B>T *</B>. The copy  | 
					
						
							| 
									
										
										
										
											2002-09-16 15:26:52 +00:00
										 |  |  | 				constructor and destructor of <b>D</b> must not throw. The expression <code>d2(p)</code>,  | 
					
						
							|  |  |  | 				where <STRONG>d2</STRONG> is a copy of <STRONG>d</STRONG>, must be well-formed,  | 
					
						
							|  |  |  | 				must not invoke undefined behavior, and must not throw exceptions. | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 			</p> | 
					
						
							|  |  |  | 			<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b> and <b>d</b>.</p> | 
					
						
							|  |  |  | 			<p><b>Postconditions:</b> <A href="#use_count">use count</A> is 1.</p> | 
					
						
							|  |  |  | 			<p><b>Throws:</b> <b>std::bad_alloc</b>.</p> | 
					
						
							|  |  |  | 			<p><b>Exception safety:</b> If an exception is thrown, <code>d(p)</code> is called.</p> | 
					
						
							|  |  |  | 			<p><b>Notes:</b> When the the time comes to delete the object pointed to by <b>p</b>, | 
					
						
							| 
									
										
										
										
											2002-09-16 15:26:52 +00:00
										 |  |  | 				<code>d2(p)</code> is invoked, where <STRONG>d2</STRONG> is the stored copy of <STRONG> | 
					
						
							|  |  |  | 					d</STRONG>.</p> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		</blockquote> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<P><EM>[Custom deallocators allow a factory function returning a <STRONG>shared_ptr</STRONG> | 
					
						
							|  |  |  | 				to insulate the user from its memory allocation strategy. Since the deallocator  | 
					
						
							|  |  |  | 				is not part of the type, changing the allocation strategy does not break source  | 
					
						
							|  |  |  | 				or binary compatibility, and does not require a client recompilation. For  | 
					
						
							|  |  |  | 				example, a "no-op" deallocator is useful when returning a <STRONG>shared_ptr</STRONG> | 
					
						
							|  |  |  | 				to a statically allocated object.</EM></P> | 
					
						
							|  |  |  | 		<P><EM>The support for custom deallocators does not impose significant overhead. Other <STRONG> | 
					
						
							| 
									
										
										
										
											2002-08-17 13:05:25 +00:00
										 |  |  | 					shared_ptr</STRONG> features still require a deallocator to be kept.</EM></P> | 
					
						
							| 
									
										
										
										
											2002-08-19 16:23:07 +00:00
										 |  |  | 		<P><EM>The requirement that the copy constructor of <b>D</b> does not throw is too  | 
					
						
							|  |  |  | 				strong. It will be removed when some core language issues are resolved  | 
					
						
							|  |  |  | 				(cv-qualified function types, partial ordering clarifications.)]</EM></P> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<pre>shared_ptr(shared_ptr const & r); // never throws | 
					
						
							|  |  |  | template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws</pre> | 
					
						
							|  |  |  | 		<blockquote> | 
					
						
							|  |  |  | 			<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, as if by storing a copy of the  | 
					
						
							|  |  |  | 				pointer stored in <STRONG>r</STRONG>.</p> | 
					
						
							|  |  |  | 			<p><b>Postconditions:</b> <A href="#use_count">use count</A> for all copies is  | 
					
						
							|  |  |  | 				increased by one.</p> | 
					
						
							|  |  |  | 			<p><b>Throws:</b> nothing.</p> | 
					
						
							|  |  |  | 		</blockquote> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<P><EM>[The postcondition will be relaxed when a default-constructed <STRONG>shared_ptr</STRONG> | 
					
						
							|  |  |  | 				is being copied.]</EM></P> | 
					
						
							| 
									
										
										
										
											2002-02-15 13:31:58 +00:00
										 |  |  | 		<pre>explicit shared_ptr(<A href="weak_ptr.htm" >weak_ptr</A> const & r);</pre> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<blockquote> | 
					
						
							|  |  |  | 			<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, as if by storing a copy of the  | 
					
						
							|  |  |  | 				pointer stored in <STRONG>r</STRONG>.</p> | 
					
						
							|  |  |  | 			<p><b>Postconditions:</b> <A href="#use_count">use count</A> for all copies is  | 
					
						
							|  |  |  | 				increased by one.</p> | 
					
						
							|  |  |  | 			<p><b>Throws:</b> <b>use_count_is_zero</b> when <code>r.use_count() == 0</code>.</p> | 
					
						
							|  |  |  | 			<p><b>Exception safety:</b> If an exception is thrown, the constructor has no  | 
					
						
							|  |  |  | 				effect.</p> | 
					
						
							|  |  |  | 		</blockquote> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<P><EM>[This constructor is an optional part of the specification; it depends on the  | 
					
						
							|  |  |  | 				existence of <STRONG>weak_ptr</STRONG>. It is true that <STRONG>weak_ptr</STRONG> | 
					
						
							|  |  |  | 				support imposes overhead on every <STRONG>shared_ptr</STRONG> user, regardless  | 
					
						
							|  |  |  | 				of whether weak pointers are used.</EM></P> | 
					
						
							|  |  |  | 		<P><EM>On the other hand, cyclic references are a serious problem with all reference  | 
					
						
							|  |  |  | 				counted designs. Not providing a solution within the library is unacceptable;  | 
					
						
							|  |  |  | 				if users are forced to reinvent the weak pointer wheel, there is substantial  | 
					
						
							|  |  |  | 				probability that they will get it wrong, as designing a safe <STRONG>weak_ptr</STRONG> | 
					
						
							|  |  |  | 				interface is non-trivial.</EM></P> | 
					
						
							|  |  |  | 		<P><EM>My opinion is that the added functionality is worth the cost. <STRONG>weak_ptr</STRONG> | 
					
						
							|  |  |  | 				is provided in the reference implementation as a proof of concept.]</EM></P> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<pre>template<typename Y> shared_ptr(std::auto_ptr<Y> & r);</pre> | 
					
						
							|  |  |  | 		<BLOCKQUOTE> | 
					
						
							|  |  |  | 			<P><B>Effects:</B> Constructs a <B>shared_ptr</B>, as if by storing a copy of <STRONG>r.release()</STRONG>.</P> | 
					
						
							| 
									
										
										
										
											2002-08-19 16:23:07 +00:00
										 |  |  | 			<P><B>Postconditions:</B> <A href="#use_count">use count</A> is 1.</P> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 			<P><B>Throws:</B> <B>std::bad_alloc</B>.</P> | 
					
						
							|  |  |  | 			<P><B>Exception safety:</B> If an exception is thrown, the constructor has no  | 
					
						
							|  |  |  | 				effect.</P> | 
					
						
							|  |  |  | 		</BLOCKQUOTE> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<P><EM>[This constructor takes a the source <STRONG>auto_ptr</STRONG> by reference and  | 
					
						
							|  |  |  | 				not by value, and cannot accept <STRONG>auto_ptr</STRONG> temporaries. This is  | 
					
						
							|  |  |  | 				by design, as the constructor offers the strong guarantee.]</EM></P> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<h3><a name="destructor">destructor</a></h3> | 
					
						
							|  |  |  | 		<pre>~shared_ptr(); // never throws</pre> | 
					
						
							|  |  |  | 		<BLOCKQUOTE> | 
					
						
							|  |  |  | 			<P><B>Effects:</B> If <STRONG>*this</STRONG> is the sole owner (<code>use_count() == 1</code>),  | 
					
						
							|  |  |  | 				destroys the object pointed to by the stored pointer.</P> | 
					
						
							|  |  |  | 			<P><B>Postconditions:</B> <A href="#use_count">use count</A> for all remaining  | 
					
						
							|  |  |  | 				copies is decreased by one.</P> | 
					
						
							|  |  |  | 			<P><B>Throws:</B> nothing.</P> | 
					
						
							|  |  |  | 		</BLOCKQUOTE> | 
					
						
							|  |  |  | 		<H3><a name="assignment">assignment</a></H3> | 
					
						
							|  |  |  | 		<pre>shared_ptr & operator=(shared_ptr const & r); // never throws | 
					
						
							|  |  |  | template<typename Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws | 
					
						
							|  |  |  | template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r);</pre> | 
					
						
							|  |  |  | 		<BLOCKQUOTE> | 
					
						
							|  |  |  | 			<P><B>Effects:</B> Equivalent to <code>shared_ptr(r).swap(*this)</code>.</P> | 
					
						
							| 
									
										
										
										
											2002-02-15 13:31:58 +00:00
										 |  |  | 			<P><B>Notes:</B> The implementation is free to meet the effects (and the implied  | 
					
						
							|  |  |  | 				guarantees) via different means, without creating a temporary. In particular,  | 
					
						
							|  |  |  | 				in the example:</P> | 
					
						
							|  |  |  | 			<pre> | 
					
						
							|  |  |  | shared_ptr<int> p(new int); | 
					
						
							|  |  |  | shared_ptr<void> q(p); | 
					
						
							|  |  |  | p = p; | 
					
						
							|  |  |  | q = p; | 
					
						
							|  |  |  | </pre> | 
					
						
							|  |  |  | 			<p>both assignments may be no-ops.</p> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		</BLOCKQUOTE> | 
					
						
							|  |  |  | 		<h3><a name="reset">reset</a></h3> | 
					
						
							| 
									
										
										
										
											2002-02-15 13:31:58 +00:00
										 |  |  | 		<pre>void reset();</pre> | 
					
						
							|  |  |  | 		<BLOCKQUOTE> | 
					
						
							|  |  |  | 			<P><B>Effects:</B> Equivalent to <code>shared_ptr().swap(*this)</code>.</P> | 
					
						
							|  |  |  | 		</BLOCKQUOTE> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<P><EM>[<STRONG>reset()</STRONG> will offer the nothrow guarantee in a future  | 
					
						
							|  |  |  | 				implementation.]</EM></P> | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 		<pre>template<typename Y> void reset(Y * p);</pre> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<BLOCKQUOTE> | 
					
						
							|  |  |  | 			<P><B>Effects:</B> Equivalent to <code>shared_ptr(p).swap(*this)</code>.</P> | 
					
						
							|  |  |  | 		</BLOCKQUOTE> | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 		<pre>template<typename Y, typename D> void reset(Y * p, D d);</pre> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<BLOCKQUOTE> | 
					
						
							|  |  |  | 			<P><B>Effects:</B> Equivalent to <code>shared_ptr(p, d).swap(*this)</code>.</P> | 
					
						
							|  |  |  | 		</BLOCKQUOTE> | 
					
						
							|  |  |  | 		<h3><a name="indirection">indirection</a></h3> | 
					
						
							|  |  |  | 		<pre>T & operator*() const; // never throws</pre> | 
					
						
							|  |  |  | 		<blockquote> | 
					
						
							|  |  |  | 			<p><b>Requirements:</b> The stored pointer must not be 0.</p> | 
					
						
							|  |  |  | 			<p><b>Returns:</b> a reference to the object pointed to by the stored pointer.</p> | 
					
						
							|  |  |  | 			<p><b>Throws:</b> nothing.</p> | 
					
						
							|  |  |  | 		</blockquote> | 
					
						
							|  |  |  | 		<pre>T * operator->() const; // never throws</pre> | 
					
						
							|  |  |  | 		<blockquote> | 
					
						
							|  |  |  | 			<p><b>Requirements:</b> The stored pointer must not be 0.</p> | 
					
						
							|  |  |  | 			<p><b>Returns:</b> the stored pointer.</p> | 
					
						
							|  |  |  | 			<p><b>Throws:</b> nothing.</p> | 
					
						
							|  |  |  | 		</blockquote> | 
					
						
							|  |  |  | 		<h3><a name="get">get</a></h3> | 
					
						
							|  |  |  | 		<pre>T * get() const; // never throws</pre> | 
					
						
							|  |  |  | 		<blockquote> | 
					
						
							|  |  |  | 			<p><b>Returns:</b> the stored pointer.</p> | 
					
						
							|  |  |  | 			<p><b>Throws:</b> nothing.</p> | 
					
						
							|  |  |  | 		</blockquote> | 
					
						
							|  |  |  | 		<h3><a name="unique">unique</a></h3> | 
					
						
							|  |  |  | 		<pre>bool unique() const; // never throws</pre> | 
					
						
							|  |  |  | 		<blockquote> | 
					
						
							|  |  |  | 			<p><b>Returns:</b> <code>use_count() == 1</code>.</p> | 
					
						
							|  |  |  | 			<p><b>Throws:</b> nothing.</p> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 			<P><B>Notes:</B> <code>unique()</code> may be faster than <code>use_count()</code>.  | 
					
						
							|  |  |  | 				If you are using <code>unique()</code> to implement copy on write, do not rely  | 
					
						
							|  |  |  | 				on a specific value when the stored pointer is zero.</P> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		</blockquote> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<P><EM>[In a future release, <STRONG>unique()</STRONG> will return an unspecified value  | 
					
						
							|  |  |  | 				for a default-constructed <STRONG>shared_ptr.</STRONG>]</EM></P> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<h3><a name="use_count">use_count</a></h3> | 
					
						
							|  |  |  | 		<pre>long use_count() const; // never throws</pre> | 
					
						
							|  |  |  | 		<blockquote> | 
					
						
							|  |  |  | 			<p><b>Returns:</b> the number of <b>shared_ptr</b> objects sharing ownership of the  | 
					
						
							|  |  |  | 				stored pointer.</p> | 
					
						
							|  |  |  | 			<p><b>Throws:</b> nothing.</p> | 
					
						
							|  |  |  | 			<P><B>Notes:</B> <code>use_count()</code> is not necessarily efficient. Use only  | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 				for debugging and testing purposes, not for production code.</P> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		</blockquote> | 
					
						
							| 
									
										
										
										
											2002-02-15 14:46:53 +00:00
										 |  |  | 		<h3><a name="conversions">conversions</a></h3> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre> | 
					
						
							| 
									
										
										
										
											2002-02-15 14:46:53 +00:00
										 |  |  | 		<blockquote> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 			<p><b>Returns:</b> an unspecified value that, when used in boolean contexts,  | 
					
						
							|  |  |  | 				is equivalent to <code>get() != 0</code>.</p> | 
					
						
							| 
									
										
										
										
											2002-02-15 14:46:53 +00:00
										 |  |  | 			<p><b>Throws:</b> nothing.</p> | 
					
						
							|  |  |  | 			<P><B>Notes:</B> This conversion operator allows <b>shared_ptr</b> objects to be  | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 				used in boolean contexts, like <code>if (p && p->valid()) {}</code>.  | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 				The actual target type is typically a pointer to a member function, avoiding  | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 				many of the implicit conversion pitfalls.</P> | 
					
						
							| 
									
										
										
										
											2002-02-15 14:46:53 +00:00
										 |  |  | 		</blockquote> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<P><EM>[The conversion to bool is not merely syntactic sugar. It allows <STRONG>shared_ptr</STRONG>s  | 
					
						
							|  |  |  | 				to be declared in conditions when using <STRONG>shared_dynamic_cast </STRONG>or <STRONG> | 
					
						
							|  |  |  | 					make_shared</STRONG>.]</EM></P> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<h3><a name="swap">swap</a></h3> | 
					
						
							|  |  |  | 		<pre>void swap(shared_ptr & b); // never throws</pre> | 
					
						
							|  |  |  | 		<blockquote> | 
					
						
							|  |  |  | 			<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p> | 
					
						
							|  |  |  | 			<p><b>Throws:</b> nothing.</p> | 
					
						
							|  |  |  | 		</blockquote> | 
					
						
							|  |  |  | 		<h2><a name="functions">Free Functions</a></h2> | 
					
						
							|  |  |  | 		<h3><a name="comparison">comparison</a></h3> | 
					
						
							|  |  |  | 		<pre>template<typename T, typename U> | 
					
						
							|  |  |  |   bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre> | 
					
						
							|  |  |  | 		<blockquote> | 
					
						
							|  |  |  | 			<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p> | 
					
						
							|  |  |  | 			<p><b>Throws:</b> nothing.</p> | 
					
						
							|  |  |  | 		</blockquote> | 
					
						
							|  |  |  | 		<pre>template<typename T, typename U> | 
					
						
							|  |  |  |   bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre> | 
					
						
							|  |  |  | 		<blockquote> | 
					
						
							|  |  |  | 			<p><b>Returns:</b> <code>a.get() != b.get()</code>.</p> | 
					
						
							|  |  |  | 			<p><b>Throws:</b> nothing.</p> | 
					
						
							|  |  |  | 		</blockquote> | 
					
						
							|  |  |  | 		<pre>template<typename T> | 
					
						
							| 
									
										
										
										
											2002-02-09 01:18:00 +00:00
										 |  |  |   bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws</pre> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<blockquote> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 			<p><b>Returns:</b> an unspecified value such that <b>operator<</b> is a  | 
					
						
							|  |  |  | 				strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 				of the C++ standard.</p> | 
					
						
							|  |  |  | 			<p><b>Throws:</b> nothing.</p> | 
					
						
							|  |  |  | 			<P><B>Notes:</B> Allows <STRONG>shared_ptr</STRONG> objects to be used as keys in  | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 				associative containers.</P> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		</blockquote> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<P><EM>[<STRONG>Operator<</STRONG> has been preferred over a <STRONG>std::less </STRONG> | 
					
						
							|  |  |  | 				specialization for consistency and legality reasons, as <STRONG>std::less</STRONG> | 
					
						
							|  |  |  | 				is required to return the results of <STRONG>operator<</STRONG>, and many  | 
					
						
							|  |  |  | 				standard algorithms use <STRONG>operator<</STRONG> instead of <STRONG>std::less</STRONG> | 
					
						
							| 
									
										
										
										
											2002-07-24 10:20:30 +00:00
										 |  |  | 				for comparisons when a predicate is not supplied. Composite objects, like <STRONG>std::pair</STRONG>,  | 
					
						
							|  |  |  | 				also implement their <STRONG>operator<</STRONG> in terms of their contained  | 
					
						
							|  |  |  | 				subobjects' <STRONG>operator<</STRONG>.</EM></P> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<P><EM>The rest of the comparison operators are omitted by design.]</EM></P> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<h3><a name="free-swap">swap</a></h3> | 
					
						
							|  |  |  | 		<pre>template<typename T> | 
					
						
							| 
									
										
										
										
											2002-07-27 16:02:26 +00:00
										 |  |  |   void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws</pre> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<BLOCKQUOTE> | 
					
						
							|  |  |  | 			<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P> | 
					
						
							|  |  |  | 			<P><B>Throws:</B> nothing.</P> | 
					
						
							|  |  |  | 			<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to  | 
					
						
							|  |  |  | 				generic programming.</P> | 
					
						
							|  |  |  | 		</BLOCKQUOTE> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<P><EM>[<STRONG>swap</STRONG> is defined in the same namespace as <STRONG>shared_ptr</STRONG> | 
					
						
							|  |  |  | 				as this is currently the only legal way to supply a <STRONG>swap</STRONG> function  | 
					
						
							|  |  |  | 				that has a chance to be used by the standard library.]</EM></P> | 
					
						
							| 
									
										
										
										
											2002-07-27 16:02:26 +00:00
										 |  |  | 		<h3><a name="get_pointer">get_pointer</a></h3> | 
					
						
							|  |  |  | 		<pre>template<typename T> | 
					
						
							|  |  |  |   T * get_pointer(shared_ptr<T> const & p); // never throws</pre> | 
					
						
							|  |  |  | 		<BLOCKQUOTE> | 
					
						
							|  |  |  | 			<P><B>Returns:</B> <code>p.get()</code>.</P> | 
					
						
							|  |  |  | 			<P><B>Throws:</B> nothing.</P> | 
					
						
							|  |  |  | 			<P><B>Notes:</B> Provided as an aid to generic programming. Used by <A href="../bind/mem_fn.html"> | 
					
						
							|  |  |  | 					mem_fn</A>.</P> | 
					
						
							|  |  |  | 		</BLOCKQUOTE> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<h3><a name="shared_static_cast">shared_static_cast</a></h3> | 
					
						
							|  |  |  | 		<pre>template<typename T, typename U> | 
					
						
							|  |  |  |   shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws</pre> | 
					
						
							|  |  |  | 		<BLOCKQUOTE> | 
					
						
							|  |  |  | 			<P><STRONG>Requires:</STRONG> The expression <code>static_cast<T*>(r.get())</code> | 
					
						
							|  |  |  | 				must be well-formed.</P> | 
					
						
							|  |  |  | 			<P><B>Returns:</B> A <STRONG>shared_ptr<T></STRONG> object that stores a copy  | 
					
						
							|  |  |  | 				of <code>static_cast<T*>(r.get())</code> and shares ownership with <b>r</b>.</P> | 
					
						
							|  |  |  | 			<P><B>Throws:</B> nothing.</P> | 
					
						
							|  |  |  | 			<P><B>Notes:</B> the seemingly equivalent expression</P> | 
					
						
							|  |  |  | 			<p><code>shared_ptr<T>(static_cast<T*>(r.get()))</code></p> | 
					
						
							|  |  |  | 			<p>will eventually result in undefined behavior, attempting to delete the same  | 
					
						
							|  |  |  | 				object twice.</p> | 
					
						
							|  |  |  | 		</BLOCKQUOTE> | 
					
						
							|  |  |  | 		<h3><a name="shared_dynamic_cast">shared_dynamic_cast</a></h3> | 
					
						
							|  |  |  | 		<pre>template<typename T, typename U> | 
					
						
							|  |  |  |   shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r);</pre> | 
					
						
							|  |  |  | 		<BLOCKQUOTE> | 
					
						
							|  |  |  | 			<P><STRONG>Requires:</STRONG> The expression <CODE>dynamic_cast<T*>(r.get())</CODE> | 
					
						
							|  |  |  | 				must be well-formed and its behavior defined.</P> | 
					
						
							|  |  |  | 			<P><B>Returns:</B></P> | 
					
						
							|  |  |  | 			<UL> | 
					
						
							|  |  |  | 				<LI> | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 					When <CODE>dynamic_cast<T*>(r.get())</CODE> returns a nonzero value, a <STRONG> | 
					
						
							|  |  |  | 						shared_ptr<T></STRONG> object that stores a copy of it and shares  | 
					
						
							|  |  |  | 					ownership with <STRONG>r</STRONG>; | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 				<LI> | 
					
						
							|  |  |  | 					Otherwise, a default-constructed <STRONG>shared_ptr<T></STRONG> object.</LI></UL> | 
					
						
							|  |  |  | 			<P><B>Throws:</B> <STRONG>std::bad_alloc</STRONG>.</P> | 
					
						
							| 
									
										
										
										
											2002-05-04 14:27:21 +00:00
										 |  |  | 			<P><B>Exception safety:</B> If an exception is thrown, the function has no effect.</P> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 			<P><B>Notes:</B> the seemingly equivalent expression</P> | 
					
						
							|  |  |  | 			<P><CODE>shared_ptr<T>(dynamic_cast<T*>(r.get()))</CODE></P> | 
					
						
							|  |  |  | 			<P>will eventually result in undefined behavior, attempting to delete the same  | 
					
						
							|  |  |  | 				object twice.</P> | 
					
						
							|  |  |  | 		</BLOCKQUOTE> | 
					
						
							|  |  |  | 		<h3><a name="shared_polymorphic_cast">shared_polymorphic_cast</a></h3> | 
					
						
							|  |  |  | 		<pre>template<typename T, typename U> | 
					
						
							|  |  |  |   shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r);</pre> | 
					
						
							|  |  |  | 		<BLOCKQUOTE> | 
					
						
							|  |  |  | 			<p><STRONG>Requires:</STRONG> The expression <CODE><A href="../conversion/cast.htm#Polymorphic_cast"> | 
					
						
							| 
									
										
										
										
											2002-02-15 13:31:58 +00:00
										 |  |  | 						polymorphic_cast</A><T*>(r.get())</CODE> must be well-formed and  | 
					
						
							|  |  |  | 				its behavior defined.</p> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 			<P><B>Returns:</B> A <STRONG>shared_ptr<T></STRONG> object that stores a copy  | 
					
						
							|  |  |  | 				of <CODE><A href="../conversion/cast.htm#Polymorphic_cast">polymorphic_cast</A><T*>(r.get())</CODE> | 
					
						
							|  |  |  | 				and shares ownership with <B>r</B>.</P> | 
					
						
							| 
									
										
										
										
											2002-02-15 14:46:53 +00:00
										 |  |  | 			<P><B>Throws:</B> <STRONG>std::bad_cast</STRONG> when the pointer cannot be  | 
					
						
							|  |  |  | 				converted.</P> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 			<P><B>Exception safety:</B> If an exception is thrown, the function has no effect.</P> | 
					
						
							|  |  |  | 		</BLOCKQUOTE> | 
					
						
							|  |  |  | 		<h3><a name="shared_polymorphic_downcast">shared_polymorphic_downcast</a></h3> | 
					
						
							|  |  |  | 		<pre>template<typename T, typename U> | 
					
						
							|  |  |  |   shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws</pre> | 
					
						
							|  |  |  | 		<BLOCKQUOTE> | 
					
						
							|  |  |  | 			<p><STRONG>Requires:</STRONG> The expression <CODE><A href="../conversion/cast.htm#Polymorphic_cast"> | 
					
						
							| 
									
										
										
										
											2002-02-15 13:31:58 +00:00
										 |  |  | 						polymorphic_downcast</A><T*>(r.get())</CODE> must be well-formed  | 
					
						
							|  |  |  | 				and its behavior defined.</p> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 			<P><B>Returns:</B> A <STRONG>shared_ptr<T></STRONG> object that stores a copy  | 
					
						
							|  |  |  | 				of <CODE><A href="../conversion/cast.htm#Polymorphic_cast">polymorphic_downcast</A><T*>(r.get())</CODE> | 
					
						
							|  |  |  | 				and shares ownership with <B>r</B>.</P> | 
					
						
							|  |  |  | 			<P><B>Throws:</B> nothing.</P> | 
					
						
							|  |  |  | 		</BLOCKQUOTE> | 
					
						
							|  |  |  | 		<h2><a name="example">Example</a></h2> | 
					
						
							|  |  |  | 		<p>See <A href="shared_ptr_example.cpp">shared_ptr_example.cpp</A> for a complete  | 
					
						
							|  |  |  | 			example program. The program builds a <b>std::vector</b> and <b>std::set</b> of <b>shared_ptr</b> | 
					
						
							|  |  |  | 			objects.</p> | 
					
						
							|  |  |  | 		<p>Note that after the containers have been populated, some of the <b>shared_ptr</b> | 
					
						
							|  |  |  | 			objects will have a use count of 1 rather than a use count of 2, since the set  | 
					
						
							|  |  |  | 			is a <b>std::set</b> rather than a <b>std::multiset</b>, and thus does not  | 
					
						
							|  |  |  | 			contain duplicate entries. Furthermore, the use count may be even higher at  | 
					
						
							|  |  |  | 			various times while <b>push_back</b> and <b>insert</b> container operations are  | 
					
						
							|  |  |  | 			performed. More complicated yet, the container operations may throw exceptions  | 
					
						
							|  |  |  | 			under a variety of circumstances. Getting the memory management and exception  | 
					
						
							|  |  |  | 			handling in this example right without a smart pointer 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<></b> to an incomplete type to hide the  | 
					
						
							|  |  |  | 			implementation. 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. Note that there is no need for an explicit destructor.  | 
					
						
							|  |  |  | 			Unlike ~scoped_ptr, ~shared_ptr does not require that <b>T</b> be a complete  | 
					
						
							|  |  |  | 			type.</p> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<h2><a name="ThreadSafety">Thread Safety</a></h2> | 
					
						
							|  |  |  | 		<p><STRONG>shared_ptr</STRONG> objects offer the same level of thread safety as  | 
					
						
							|  |  |  | 			built-in types. A <STRONG>shared_ptr</STRONG> instance can be "read"  | 
					
						
							|  |  |  | 			(accessed using only const operations) simultaneously by multiple threads.  | 
					
						
							|  |  |  | 			Different <STRONG>shared_ptr</STRONG> instances can be "written to" (accessed  | 
					
						
							|  |  |  | 			using mutable operations such as <STRONG>operator= </STRONG>or <STRONG>reset</STRONG>)  | 
					
						
							|  |  |  | 			simultaneosly by multiple threads (even when these instances are copies, and  | 
					
						
							|  |  |  | 			share the same reference count underneath.)</p> | 
					
						
							|  |  |  | 		<P>Any other simultaneous accesses result in undefined behavior.</P> | 
					
						
							|  |  |  | 		<P>Examples:</P> | 
					
						
							|  |  |  | 		<pre> | 
					
						
							|  |  |  | shared_ptr<int> p(new int(42)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //--- Example 1 --- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // thread A | 
					
						
							|  |  |  | shared_ptr<int> p2(p); // reads p | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // thread B | 
					
						
							|  |  |  | shared_ptr<int> p3(p); // OK, multiple reads are safe | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //--- Example 2 --- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // thread A | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | p.reset(new int(1912)); // writes p | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // thread B | 
					
						
							|  |  |  | p2.reset(); // OK, writes p2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //--- Example 3 --- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // thread A | 
					
						
							|  |  |  | p = p3; // reads p3, writes p | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // thread B | 
					
						
							|  |  |  | p3.reset(); // writes p3; undefined, simultaneous read/write | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //--- Example 4 --- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // thread A | 
					
						
							|  |  |  | p3 = p2; // reads p2, writes p3 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // thread B | 
					
						
							|  |  |  | // p2 goes out of scope: undefined, the destructor is considered a "write access" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //--- Example 5 --- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // thread A | 
					
						
							|  |  |  | p3.reset(new int(1)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // thread B | 
					
						
							|  |  |  | p3.reset(new int(2)); // undefined, multiple writes | 
					
						
							|  |  |  | </pre> | 
					
						
							|  |  |  | 		<p><STRONG>shared_ptr</STRONG> uses <A href="../config/config.htm">Boost.Config</A>  | 
					
						
							|  |  |  | 			to detect whether the implementation supports threads. If your program is  | 
					
						
							|  |  |  | 			single-threaded, but your platform is autodetected by <STRONG>Boost.Config</STRONG> | 
					
						
							|  |  |  | 			as supporting multiple threads, <STRONG>#define BOOST_DISABLE_THREADS</STRONG> to  | 
					
						
							|  |  |  | 			eliminate the thread safety overhead.</p> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<h2><a name="FAQ">Frequently Asked Questions</a></h2> | 
					
						
							|  |  |  | 		<P><B>Q.</B> There are several variations of shared pointers, with different  | 
					
						
							|  |  |  | 			tradeoffs; why does the smart pointer library supply only a single  | 
					
						
							|  |  |  | 			implementation? It would be useful to be able to experiment with each type so  | 
					
						
							|  |  |  | 			as to find the most suitable for the job at hand?<BR> | 
					
						
							|  |  |  | 			<b>A.</b> An important goal of <STRONG>shared_ptr</STRONG> is to provide a  | 
					
						
							|  |  |  | 			standard shared-ownership pointer. Having a single pointer type is important  | 
					
						
							|  |  |  | 			for stable library interfaces, since different shared pointers typically cannot  | 
					
						
							|  |  |  | 			interoperate, i.e. a reference counted pointer (used by library A) cannot share  | 
					
						
							|  |  |  | 			ownership with a linked pointer (used by library B.)</P> | 
					
						
							|  |  |  | 		<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. The <B>shared_ptr</B> template is  | 
					
						
							|  |  |  | 			carefully crafted to meet common needs without extensive parameterization. Some  | 
					
						
							|  |  |  | 			day a highly configurable smart pointer may be invented that is also very easy  | 
					
						
							|  |  |  | 			to use and very hard to misuse. Until then, <B>shared_ptr</B> is the smart  | 
					
						
							|  |  |  | 			pointer of choice for a wide range of applications. (Those interested in policy  | 
					
						
							|  |  |  | 			based smart pointers should read <A href="http://cseng.aw.com/book/0,,0201704315,00.html"> | 
					
						
							|  |  |  | 				Modern C++ Design</A> by Andrei Alexandrescu.)</P> | 
					
						
							| 
									
										
										
										
											2002-07-23 15:19:22 +00:00
										 |  |  | 		<P><B>Q.</B> I am not convinced. Default parameters can be used where appropriate  | 
					
						
							|  |  |  | 			to hide the complexity. Again, why not policies?<BR> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 			<B>A.</B> Template parameters affect the type. See the answer to the first  | 
					
						
							|  |  |  | 			question above.</P> | 
					
						
							|  |  |  | 		<p><b>Q.</b> Why doesn't <b>shared_ptr</b> use a linked list implementation?<br> | 
					
						
							|  |  |  | 			<b>A.</b> A linked list implementation does not offer enough advantages to  | 
					
						
							|  |  |  | 			offset the added cost of an extra pointer. See <A href="smarttests.htm">timings</A> | 
					
						
							|  |  |  | 			page. In addition, it is expensive to make a linked list implementation thread  | 
					
						
							|  |  |  | 			safe.</p> | 
					
						
							|  |  |  | 		<p><b>Q.</b> Why doesn't <b>shared_ptr</b> (or any of 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> | 
					
						
							|  |  |  | 		<p><b>Q.</b> Why does <b>shared_ptr</b> supply use_count()?<br> | 
					
						
							|  |  |  | 			<b>A.</b> As an aid to writing test cases and debugging displays. One of the  | 
					
						
							|  |  |  | 			progenitors had use_count(), and it was useful in tracking down bugs in a  | 
					
						
							|  |  |  | 			complex project that turned out to have cyclic-dependencies.</p> | 
					
						
							|  |  |  | 		<p><b>Q.</b> Why doesn't <b>shared_ptr</b> specify complexity requirements?<br> | 
					
						
							|  |  |  | 			<b>A.</b> Because complexity requirements limit implementors and complicate the  | 
					
						
							|  |  |  | 			specification without apparent benefit to <b>shared_ptr</b> users. For example,  | 
					
						
							|  |  |  | 			error-checking implementations might become non-conforming if they had to meet  | 
					
						
							|  |  |  | 			stringent complexity requirements.</p> | 
					
						
							|  |  |  | 		<p><b>Q.</b> Why doesn't <b>shared_ptr</b> provide a release() function?<br> | 
					
						
							|  |  |  | 			<b>A.</b> <b>shared_ptr</b> cannot give away ownership unless it's unique()  | 
					
						
							|  |  |  | 			because the other copy will still destroy the object.</p> | 
					
						
							|  |  |  | 		<p>Consider:</p> | 
					
						
							|  |  |  | 		<blockquote><pre>shared_ptr<int> a(new int); | 
					
						
							| 
									
										
										
										
											2002-01-11 20:20:07 +00:00
										 |  |  | shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int * p = a.release(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | // Who owns p now? b will still call delete on it in its destructor.</pre> | 
					
						
							|  |  |  | 		</blockquote> | 
					
						
							|  |  |  | 		<p><b>Q.</b> Why doesn't <b>shared_ptr</b> provide (your pet feature here)?<br> | 
					
						
							|  |  |  | 			<b>A.</b> Because (your pet feature here) would mandate a reference counted  | 
					
						
							|  |  |  | 			implementation or a linked list implementation, or some other specific  | 
					
						
							|  |  |  | 			implementation. This is not the intent.</p> | 
					
						
							|  |  |  | 		<hr> | 
					
						
							| 
									
										
										
										
											2002-09-16 15:26:52 +00:00
										 |  |  | 		<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->  | 
					
						
							| 
									
										
										
										
											2002-07-23 19:12:40 +00:00
										 |  |  | 			23 July 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p> | 
					
						
							| 
									
										
										
										
											2002-02-14 17:12:07 +00:00
										 |  |  | 		<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.  | 
					
						
							|  |  |  | 			Copyright 2002 Peter Dimov. 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" without express or implied  | 
					
						
							|  |  |  | 			warranty, and with no claim as to its suitability for any purpose.</p> | 
					
						
							|  |  |  | 	</body> | 
					
						
							| 
									
										
										
										
											2002-02-02 18:36:12 +00:00
										 |  |  | </html> |