From 70255d46bb9058a8f976a2d1f06a97b144204b3d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 4 May 2002 14:27:21 +0000 Subject: [PATCH] Documented templated pointer constructors, revised the intro a bit. [SVN r13665] --- shared_ptr.htm | 95 ++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 53 deletions(-) diff --git a/shared_ptr.htm b/shared_ptr.htm index 49649e2..fc9df88 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -31,12 +31,19 @@ work correctly with cyclic data structures. For example, if main() holds a shared_ptr to A, which directly or indirectly holds a shared_ptr back to A, A's use count will be 2. Destruction of the original shared_ptr - will leave A dangling with a use count of 1.

+ will leave A dangling with a use count of 1. Use weak_ptr + to "break cycles."

The class template is parameterized on T, the type of the object pointed - to. T must meet the smart pointer - common requirements. T may be void, but in that case, - either an explicit delete function must be passed in, or the pointed-to object - must have a trivial destructor.

+ to. shared_ptr and most of its member functions place no + requirements on T; it is allowed to be an incomplete type, or + void. Member functions that do place additional requirements (constructors, + reset) are explicitly documented below.

+

shared_ptr<T> can be implicitly converted to shared_ptr<U> + whenever T* can be implicitly converted to U*. + In particular, shared_ptr<T> is implicitly convertible + to shared_ptr<T const>, to shared_ptr<U> + where U is an accessible base of T, and to + shared_ptr<void>.

Synopsis

namespace boost {
 
@@ -47,11 +54,12 @@
   template<typename T> class shared_ptr {
 
     public:
+
       typedef T element_type;
 
       shared_ptr ();
-      explicit shared_ptr (T * p); // requires complete type
-      template<typename D> shared_ptr(T * p, D d);
+      template<typename Y> explicit shared_ptr (Y * p);
+      template<typename Y, typename D> shared_ptr(Y * p, D d);
       ~shared_ptr(); // never throws
 
       shared_ptr(shared_ptr const & r); // never throws
@@ -64,8 +72,8 @@
       template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
 
       void reset ();
-      void reset (T * p); // requires complete type
-      template<typename D> void reset(T * p, D d);
+      template<typename Y> void reset (Y * p);
+      template<typename Y> template<typename D> void reset(Y * p, D d);
 
       T & operator*() const; // never throws
       T * operator->() const; // never throws
@@ -113,13 +121,12 @@
 			

Throws: std::bad_alloc.

Exception safety: If an exception is thrown, the constructor has no effect.

-

Notes: T need not be a complete type. See the smart pointer - common requirements.

-
explicit shared_ptr(T * p);
+
template<typename Y> explicit shared_ptr(Y * p);
-

Requirements: The expression delete p must be well-formed - and must not invoke undefined behavior. +

Requirements: p must be convertible to T *. Y + must be a complete type. The expression delete p must be + well-formed, must not invoke undefined behavior, and must not throw exceptions.

Effects: Constructs a shared_ptr, storing a copy of p.

Postconditions: use count is 1.

@@ -131,11 +138,12 @@ use count is 1 holds even if p is 0; invoking delete on a pointer that has a value of 0 is harmless.

-
template<typename D> shared_ptr(T * p, D d);
+
template<typename Y, typename D> shared_ptr(Y * p, D d);
-

Requirements: The copy constructor and destructor of D must not - throw. The expression d(p) must be well-formed, must not invoke - undefined behavior, and must not throw exceptions. +

Requirements: p must be convertible to T *. The copy + constructor and destructor of D must not throw. The expression d(p) + must be well-formed, must not invoke undefined behavior, and must not throw + exceptions.

Effects: Constructs a shared_ptr, storing a copy of p and d.

Postconditions: use count is 1.

@@ -180,10 +188,6 @@ template<typename Y> shared_ptr(shared_ptr<Y> const & r); // nev

Postconditions: use count for all remaining copies is decreased by one.

Throws: nothing.

-

Notes: T need not be a complete type. The guarantee that the - destructor does not throw exceptions depends on the requirement that the - deleted object's destructor does not throw exceptions. See the smart pointer - common requirements.

assignment

shared_ptr & operator=(shared_ptr const & r); // never throws
@@ -207,12 +211,11 @@ q = p;
 		

Effects: Equivalent to shared_ptr().swap(*this).

-
void reset(T * p);
+
template<typename Y> void reset(Y * p);

Effects: Equivalent to shared_ptr(p).swap(*this).

-

Notes: Note the implied requirement that T is a complete type.

-
template<typename D> void reset(T * p, D d);
+
template<typename Y, typename D> void reset(Y * p, D d);

Effects: Equivalent to shared_ptr(p, d).swap(*this).

@@ -234,17 +237,13 @@ q = p;

Returns: the stored pointer.

Throws: nothing.

-

Notes: T need not be a complete type. See the smart pointer - common requirements.

unique

bool unique() const; // never throws

Returns: use_count() == 1.

Throws: nothing.

-

Notes: unique() may be faster than use_count(). T - need not be a complete type. See the smart pointer - common requirements.

+

Notes: unique() may be faster than use_count().

use_count

long use_count() const; // never throws
@@ -253,9 +252,7 @@ q = p; stored pointer.

Throws: nothing.

Notes: use_count() is not necessarily efficient. Use only - for debugging and testing purposes, not for production code. T need not - be a complete type. See the smart pointer - common requirements.

+ for debugging and testing purposes, not for production code.

conversions

operator implementation-defined-type () const; // never throws
@@ -264,17 +261,15 @@ q = p; contexts, is equivalent to get() != 0.

Throws: nothing.

Notes: This conversion operator allows shared_ptr objects to be - used in boolean contexts, like if (p && p->valid()) {}. The - actual target type is typically a pointer to a member function, avloiding many - of the implicit conversion pitfalls.

+ used in boolean contexts, like if (p && p->valid()) {}. + The actual target type is typically a pointer to a member function, avloiding + many of the implicit conversion pitfalls.

swap

void swap(shared_ptr & b); // never throws

Effects: Exchanges the contents of the two smart pointers.

Throws: nothing.

-

Notes: T need not be a complete type. See the smart pointer - common requirements.

Free Functions

comparison

@@ -283,27 +278,22 @@ q = p;

Returns: a.get() == b.get().

Throws: nothing.

-

Notes: T need not be a complete type. See the smart pointer - common requirements.

template<typename T, typename U>
   bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws

Returns: a.get() != b.get().

Throws: nothing.

-

Notes: T need not be a complete type. See the smart pointer - common requirements.

template<typename T>
   bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws
-

Returns: an implementation-defined value such that operator< - is a strict weak ordering as described in section 25.3 [lib.alg.sorting] +

Returns: an implementation-defined value such that operator< is + a strict weak ordering as described in section 25.3 [lib.alg.sorting] of the C++ standard.

Throws: nothing.

Notes: Allows shared_ptr objects to be used as keys in - associative containers. T need not be a complete type. See the smart - pointer common requirements.

+ associative containers.

swap

template<typename T>
@@ -337,14 +327,13 @@ q = p;
 			

Returns:

  • - When dynamic_cast<T*>(r.get()) returns a nonzero - value, a shared_ptr<T> object that stores a copy of - it and shares ownership with r; + When dynamic_cast<T*>(r.get()) returns a nonzero value, a + shared_ptr<T> object that stores a copy of it and shares + ownership with r;
  • Otherwise, a default-constructed shared_ptr<T> object.

Throws: std::bad_alloc.

-

Exception safety: If an exception is thrown, the function has no - effect.

+

Exception safety: If an exception is thrown, the function has no effect.

Notes: the seemingly equivalent expression

shared_ptr<T>(dynamic_cast<T*>(r.get()))

will eventually result in undefined behavior, attempting to delete the same @@ -456,8 +445,8 @@ int * p = a.release(); implementation or a linked list implementation, or some other specific implementation. This is not the intent.


-

Revised  - 14 February 2002

+

Revised  + 04 May 2002

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