From 0dfb4dad0fe54957c1000f9131972831ae4da130 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 12 Jun 2017 01:58:08 +0300 Subject: [PATCH 01/26] Start rewriting documentation in asciidoc --- compatibility.htm | 88 --- doc/Jamfile | 26 + doc/asciidoctor.jam | 50 ++ doc/smart_ptr-docinfo-footer.html | 33 + doc/smart_ptr.adoc | 70 ++ doc/smart_ptr/enable_shared_from_this.adoc | 15 + doc/smart_ptr/history.adoc | 89 +++ doc/smart_ptr/introduction.adoc | 49 ++ doc/smart_ptr/intrusive_ptr.adoc | 15 + doc/smart_ptr/intrusive_ref_counter.adoc | 15 + doc/smart_ptr/make_shared.adoc | 15 + doc/smart_ptr/make_unique.adoc | 15 + doc/smart_ptr/pointer_cast.adoc | 15 + doc/smart_ptr/pointer_to_other.adoc | 15 + doc/smart_ptr/scoped_array.adoc | 15 + doc/smart_ptr/scoped_ptr.adoc | 15 + doc/smart_ptr/shared_array.adoc | 15 + doc/smart_ptr/shared_ptr.adoc | 15 + doc/smart_ptr/techniques.adoc | 15 + doc/smart_ptr/weak_ptr.adoc | 15 + enable_shared_from_this.html | 110 --- gccspeed.gif | Bin 6603 -> 0 bytes index.html | 12 +- intrusive_ptr.html | 320 -------- intrusive_ref_counter.html | 94 --- make_shared.html | 119 --- make_shared_array.html | 393 ---------- make_unique.html | 184 ----- msvcspeed.gif | Bin 6169 -> 0 bytes pointer_cast.html | 183 ----- pointer_to_other.html | 108 --- scoped_array.htm | 115 --- scoped_ptr.htm | 180 ----- shared_array.htm | 183 ----- shared_ptr.htm | 858 --------------------- smart_ptr.htm | 224 ------ smarttest.zip | Bin 11513 -> 0 bytes smarttests.htm | 542 ------------- sp_techniques.html | 765 ------------------ weak_ptr.htm | 240 ------ 40 files changed, 518 insertions(+), 4712 deletions(-) delete mode 100644 compatibility.htm create mode 100644 doc/Jamfile create mode 100644 doc/asciidoctor.jam create mode 100644 doc/smart_ptr-docinfo-footer.html create mode 100644 doc/smart_ptr.adoc create mode 100644 doc/smart_ptr/enable_shared_from_this.adoc create mode 100644 doc/smart_ptr/history.adoc create mode 100644 doc/smart_ptr/introduction.adoc create mode 100644 doc/smart_ptr/intrusive_ptr.adoc create mode 100644 doc/smart_ptr/intrusive_ref_counter.adoc create mode 100644 doc/smart_ptr/make_shared.adoc create mode 100644 doc/smart_ptr/make_unique.adoc create mode 100644 doc/smart_ptr/pointer_cast.adoc create mode 100644 doc/smart_ptr/pointer_to_other.adoc create mode 100644 doc/smart_ptr/scoped_array.adoc create mode 100644 doc/smart_ptr/scoped_ptr.adoc create mode 100644 doc/smart_ptr/shared_array.adoc create mode 100644 doc/smart_ptr/shared_ptr.adoc create mode 100644 doc/smart_ptr/techniques.adoc create mode 100644 doc/smart_ptr/weak_ptr.adoc delete mode 100644 enable_shared_from_this.html delete mode 100644 gccspeed.gif delete mode 100644 intrusive_ptr.html delete mode 100644 intrusive_ref_counter.html delete mode 100644 make_shared.html delete mode 100644 make_shared_array.html delete mode 100644 make_unique.html delete mode 100644 msvcspeed.gif delete mode 100644 pointer_cast.html delete mode 100644 pointer_to_other.html delete mode 100644 scoped_array.htm delete mode 100644 scoped_ptr.htm delete mode 100644 shared_array.htm delete mode 100644 shared_ptr.htm delete mode 100644 smart_ptr.htm delete mode 100644 smarttest.zip delete mode 100644 smarttests.htm delete mode 100644 sp_techniques.html delete mode 100644 weak_ptr.htm diff --git a/compatibility.htm b/compatibility.htm deleted file mode 100644 index 6f57e4d..0000000 --- a/compatibility.htm +++ /dev/null @@ -1,88 +0,0 @@ - - - - Smart Pointer Changes - - - -

boost.png (6897 bytes)Smart Pointer Changes

-

The February 2002 change to the Boost smart pointers introduced a number of - changes. Since the previous version of the smart pointers was in use for a long - time, it's useful to have a detailed list of what changed from a library user's - point of view.

-

Note that for compilers that don't support member templates well enough, a - separate implementation is used that lacks many of the new features and is more - like the old version.

-

Features Requiring Code Changes to Take Advantage

- -

Features That Improve Robustness

- -

Implementation Details

- -
-

$Date$

-

Copyright 2002 Darin Adler. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/doc/Jamfile b/doc/Jamfile new file mode 100644 index 0000000..b6d2c35 --- /dev/null +++ b/doc/Jamfile @@ -0,0 +1,26 @@ +# Copyright 2017 Peter Dimov +# +# Distributed under the Boost Software License, Version 1.0. +# +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt + +project doc/smart_ptr ; + +import asciidoctor ; + +html smart_ptr.html : smart_ptr.adoc ; + +install html_ : smart_ptr.html : html ; + +pdf smart_ptr.pdf : smart_ptr.adoc ; +explicit smart_ptr.pdf ; + +install pdf_ : smart_ptr.pdf : pdf ; +explicit pdf_ ; + +############################################################################### +alias boostdoc ; +explicit boostdoc ; +alias boostrelease : html_ ; +explicit boostrelease ; diff --git a/doc/asciidoctor.jam b/doc/asciidoctor.jam new file mode 100644 index 0000000..488670d --- /dev/null +++ b/doc/asciidoctor.jam @@ -0,0 +1,50 @@ +# Copyright 2017 Peter Dimov +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import type ; +import scanner ; +import generators ; +import boostbook ; + +# File type + +type.register ASCIIDOC : asciidoc adoc ; + +# Define dependency scanner + +class asciidoc-scanner : common-scanner +{ + rule pattern ( ) + { + return "include::([^[]+)\\[" ; + } +} + +scanner.register asciidoc-scanner : include ; +type.set-scanner ASCIIDOC : asciidoc-scanner ; + +# Define generators + +generators.register-standard asciidoctor.asciidoc-to-html : ASCIIDOC : HTML ; +generators.register-standard asciidoctor.asciidoc-to-pdf : ASCIIDOC : PDF ; +# generators.register-standard asciidoctor.asciidoc-to-docbook : ASCIIDOC : DOCBOOK ; + +# Define actions + +actions asciidoc-to-html +{ + asciidoctor -b html -o $(1) $(2) +} + +actions asciidoc-to-pdf +{ + asciidoctor -r asciidoctor-pdf -b pdf -o $(1) $(2) +} + +actions asciidoc-to-docbook +{ + asciidoctor -b docbook -o $(1) $(2) +} diff --git a/doc/smart_ptr-docinfo-footer.html b/doc/smart_ptr-docinfo-footer.html new file mode 100644 index 0000000..8cf495c --- /dev/null +++ b/doc/smart_ptr-docinfo-footer.html @@ -0,0 +1,33 @@ + + + diff --git a/doc/smart_ptr.adoc b/doc/smart_ptr.adoc new file mode 100644 index 0000000..e85479b --- /dev/null +++ b/doc/smart_ptr.adoc @@ -0,0 +1,70 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +# Boost.SmartPtr: Smart Pointer Library +Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes +:toc: left +:toclevels: 3 +:idprefix: +:listing-caption: Code Example +:table-caption: Illustration +:docinfo: private-footer + +:leveloffset: +1 + +include::smart_ptr/introduction.adoc[] + +include::smart_ptr/scoped_ptr.adoc[] + +include::smart_ptr/scoped_array.adoc[] + +include::smart_ptr/shared_ptr.adoc[] + +include::smart_ptr/weak_ptr.adoc[] + +include::smart_ptr/make_shared.adoc[] + +include::smart_ptr/enable_shared_from_this.adoc[] + +include::smart_ptr/make_unique.adoc[] + +include::smart_ptr/intrusive_ptr.adoc[] + +include::smart_ptr/intrusive_ref_counter.adoc[] + +include::smart_ptr/pointer_cast.adoc[] + +include::smart_ptr/pointer_to_other.adoc[] + +// appendix +include::smart_ptr/techniques.adoc[] + +// appendix +include::smart_ptr/history.adoc[] + +// appendix, deprecated +include::smart_ptr/shared_array.adoc[] + +:leveloffset: -1 + +[appendix] +## Copyright and License + +This documentation is + +* Copyright 1999 Greg Colvin +* Copyright 1999 Beman Dawes +* Copyright 2002 Darin Adler +* Copyright 2003-2017 Peter Dimov +* Copyright 2005, 2006 Ion Gaztañaga +* Copyright 2008 Frank Mori Hess +* Copyright 2012-2017 Glen Fernandes +* Copyright 2013 Andrey Semashev + +and is distributed under the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0]. diff --git a/doc/smart_ptr/enable_shared_from_this.adoc b/doc/smart_ptr/enable_shared_from_this.adoc new file mode 100644 index 0000000..5b385cb --- /dev/null +++ b/doc/smart_ptr/enable_shared_from_this.adoc @@ -0,0 +1,15 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#enable_shared_from_this] +# enable_shared_from_this +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/history.adoc b/doc/smart_ptr/history.adoc new file mode 100644 index 0000000..ffdb9af --- /dev/null +++ b/doc/smart_ptr/history.adoc @@ -0,0 +1,89 @@ +//// +Copyright 1999 Greg Colvin and Beman Dawes +Copyright 2002 Darin Adler +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[appendix,#history] +# History and Acknowledgments +:idprefix: + +## Summer 1994 + +Greg Colvin http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1994/N0555.pdf[proposed] +to the {cpp} Standards Committee classes named `auto_ptr` and `counted_ptr` which were very +similar to what we now call `scoped_ptr` and `shared_ptr`. In one of the very few cases +where the Library Working Group's recommendations were not followed by the full committee, +`counted_ptr` was rejected and surprising transfer-of-ownership semantics were added to `auto_ptr`. + +## October 1998 + +Beman Dawes proposed reviving the original semantics under the names `safe_ptr` and `counted_ptr`, +meeting of Per Andersson, Matt Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, +Dietmar Kühl, Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new class +names were finalized, it was decided that there was no need to exactly follow the `std::auto_ptr` +interface, and various function signatures and semantics were finalized. + +Over the next three months, several implementations were considered for `shared_ptr`, and discussed +on the http://www.boost.org/[boost.org] mailing list. The implementation questions revolved around +the reference count which must be kept, either attached to the pointed to object, or detached elsewhere. +Each of those variants have themselves two major variants: + +* Direct detached: the `shared_ptr` contains a pointer to the object, and a pointer to the count. +* Indirect detached: the `shared_ptr` contains a pointer to a helper object, which in turn contains a pointer to the object and the count. +* Embedded attached: the count is a member of the object pointed to. +* Placement attached: the count is attached via operator new manipulations. + +Each implementation technique has advantages and disadvantages. We went so far as to run various timings +of the direct and indirect approaches, and found that at least on Intel Pentium chips there was very little +measurable difference. Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar Kühl +suggested an elegant partial template specialization technique to allow users to choose which implementation +they preferred, and that was also experimented with. + +But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage users", and in the end we choose +to supply only the direct implementation. + +## May 1999 + +In April and May, 1999, Valentin Bonnard and David Abrahams made a number of suggestions resulting in numerous improvements. + +## September 1999 + +Luis Coelho provided `shared_ptr::swap` and `shared_array::swap`. + +## November 1999 + +Darin Adler provided `operator ==`, `operator !=`, and `std::swap` and `std::less` specializations for shared types. + +## May 2001 + +Vladimir Prus suggested requiring a complete type on destruction. Refinement evolved in discussions including Dave Abrahams, +Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and others. + +## January 2002 + +Peter Dimov reworked all four classes, adding features, fixing bugs, splitting them into four separate headers, and adding +`weak_ptr`. + +## November 2012 + +Glen Fernandes provided implementations of `make_shared` and `allocate_shared` for arrays. They achieve a single allocation +for an array that can be initialized with constructor arguments or initializer lists as well as overloads for default initialization +and no value initialization. + +## February 2014 + +Glen Fernandes updated overloads of `make_shared` and `allocate_shared` to conform to the specification in {cpp} standard paper +http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3870.html[N3870], +and implemented `make_unique` for arrays and objects. Peter Dimov and Glen Fernandes updated the scalar and array implementations, +respectively, to resolve {cpp} standard library defect 2070. + +## February 2017 + +Glen Fernandes rewrote `allocate_shared` and `make_shared` for arrays for a more optimal and more maintainable implementation. + diff --git a/doc/smart_ptr/introduction.adoc b/doc/smart_ptr/introduction.adoc new file mode 100644 index 0000000..dec424e --- /dev/null +++ b/doc/smart_ptr/introduction.adoc @@ -0,0 +1,49 @@ +//// +Copyright 1999 Greg Colvin and Beman Dawes +Copyright 2002 Darin Adler +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#introduction] +# Introduction +:toc: +:toc-title: +:idprefix: + +Smart pointers are objects which store pointers to dynamically allocated (heap) objects. +They behave much like built-in {cpp} pointers except that they automatically delete the object +pointed to at the appropriate time. Smart pointers are particularly useful in the face of +exceptions as they ensure proper destruction of dynamically allocated objects. They can also be +used to keep track of dynamically allocated objects shared by multiple owners. + +Conceptually, smart pointers are seen as owning the object pointed to, and thus responsible for +deletion of the object when it is no longer needed. As such, they are examples of the "resource +acquisition is initialization" idiom described in Bjarne Stroustrup's "The C++ Programming Language", +3rd edition, Section 14.4, Resource Management. + +This library provides five smart pointer class templates: + +* `scoped_ptr`, used to contain ownership of a dynamically allocated object to the current scope; +* `scoped_array`, which provides scoped ownership for a dynamically allocated array; +* `shared_ptr`, a versatile tool for managing shared ownership of an object or array; +* `weak_ptr`, a non-owning observer to a shared_ptr-managed object that can be promoted temporarily to shared_ptr; +* `intrusive_ptr`, a pointer to objects with an embedded reference count. + +`shared_ptr` and `weak_ptr` are part of the {cpp} standard since its 2011 iteration. + +In addition, the library contains the following supporting utility functions and classes: + +* `make_shared`, a factory function for creating objects that returns a `shared_ptr`; +* `make_unique`, a factory function returning `std::unique_ptr`; +* `enable_shared_from_this`, a helper base class that enables the acquisition of a `shared_ptr` pointing to `this`; +* `pointer_to_other`, a helper trait for converting one smart pointer type to another; +* `static_pointer_cast` and companions, generic smart pointer casts; +* `intrusive_ref_counter`, a helper base class containing a reference count. + +As a general rule, the destructor or `operator delete` for an object managed by pointers in the library +are not allowed to throw exceptions. diff --git a/doc/smart_ptr/intrusive_ptr.adoc b/doc/smart_ptr/intrusive_ptr.adoc new file mode 100644 index 0000000..6bf4843 --- /dev/null +++ b/doc/smart_ptr/intrusive_ptr.adoc @@ -0,0 +1,15 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#intrusive_ptr] +# intrusive_ptr +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/intrusive_ref_counter.adoc b/doc/smart_ptr/intrusive_ref_counter.adoc new file mode 100644 index 0000000..4a9885a --- /dev/null +++ b/doc/smart_ptr/intrusive_ref_counter.adoc @@ -0,0 +1,15 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#intrusive_ref_counter] +# intrusive_ref_counter +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc new file mode 100644 index 0000000..2531cfe --- /dev/null +++ b/doc/smart_ptr/make_shared.adoc @@ -0,0 +1,15 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#make_shared] +# make_shared +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/make_unique.adoc b/doc/smart_ptr/make_unique.adoc new file mode 100644 index 0000000..9cfec90 --- /dev/null +++ b/doc/smart_ptr/make_unique.adoc @@ -0,0 +1,15 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#make_unique] +# make_unique +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/pointer_cast.adoc b/doc/smart_ptr/pointer_cast.adoc new file mode 100644 index 0000000..3041eeb --- /dev/null +++ b/doc/smart_ptr/pointer_cast.adoc @@ -0,0 +1,15 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#pointer_cast] +# Generic Pointer Casts +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/pointer_to_other.adoc b/doc/smart_ptr/pointer_to_other.adoc new file mode 100644 index 0000000..4c4f74d --- /dev/null +++ b/doc/smart_ptr/pointer_to_other.adoc @@ -0,0 +1,15 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#pointer_to_other] +# pointer_to_other +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/scoped_array.adoc b/doc/smart_ptr/scoped_array.adoc new file mode 100644 index 0000000..9374caa --- /dev/null +++ b/doc/smart_ptr/scoped_array.adoc @@ -0,0 +1,15 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#scoped_array] +# scoped_array +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/scoped_ptr.adoc b/doc/smart_ptr/scoped_ptr.adoc new file mode 100644 index 0000000..ba71827 --- /dev/null +++ b/doc/smart_ptr/scoped_ptr.adoc @@ -0,0 +1,15 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#scoped_ptr] +# scoped_ptr +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/shared_array.adoc b/doc/smart_ptr/shared_array.adoc new file mode 100644 index 0000000..564747f --- /dev/null +++ b/doc/smart_ptr/shared_array.adoc @@ -0,0 +1,15 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[appendix,#shared_array] +# shared_array (deprecated) +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/shared_ptr.adoc b/doc/smart_ptr/shared_ptr.adoc new file mode 100644 index 0000000..50e38a0 --- /dev/null +++ b/doc/smart_ptr/shared_ptr.adoc @@ -0,0 +1,15 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#shared_ptr] +# shared_ptr +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/techniques.adoc b/doc/smart_ptr/techniques.adoc new file mode 100644 index 0000000..13a9b18 --- /dev/null +++ b/doc/smart_ptr/techniques.adoc @@ -0,0 +1,15 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[appendix,#techniques] +# Smart Pointer Programming Techniques +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/weak_ptr.adoc b/doc/smart_ptr/weak_ptr.adoc new file mode 100644 index 0000000..ceb28cf --- /dev/null +++ b/doc/smart_ptr/weak_ptr.adoc @@ -0,0 +1,15 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#weak_ptr] +# weak_ptr +:toc: +:toc-title: +:idprefix: + diff --git a/enable_shared_from_this.html b/enable_shared_from_this.html deleted file mode 100644 index f04f312..0000000 --- a/enable_shared_from_this.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - enable_shared_from_this - - - -

boost.png (6897 bytes)enable_shared_from_this

-

Purpose

-

- The header <boost/enable_shared_from_this.hpp> defines - the class template enable_shared_from_this. It is used as a - base class that allows a shared_ptr or - a weak_ptr to the current object to be obtained - from within a member function. -

-

enable_shared_from_this<T> defines two member functions - called shared_from_this that return a shared_ptr<T> - and shared_ptr<T const>, depending on constness, to this. - It also defines two member functions called weak_from_this that return - a corresponding weak_ptr. -

-

Example

-
-#include <boost/enable_shared_from_this.hpp>
-#include <boost/shared_ptr.hpp>
-#include <cassert>
-
-class Y: public boost::enable_shared_from_this<Y>
-{
-public:
-
-    boost::shared_ptr<Y> f()
-    {
-        return shared_from_this();
-    }
-};
-
-int main()
-{
-    boost::shared_ptr<Y> p(new Y);
-    boost::shared_ptr<Y> q = p->f();
-    assert(p == q);
-    assert(!(p < q || q < p)); // p and q must share ownership
-}
-
-

Synopsis

-
-namespace boost
-{
-
-template<class T> class enable_shared_from_this
-{
-public:
-
-    shared_ptr<T> shared_from_this();
-    shared_ptr<T const> shared_from_this() const;
-
-    weak_ptr<T> weak_from_this() noexcept;
-    weak_ptr<T const> weak_from_this() const noexcept;
-}
-
-}
-
-

template<class T> shared_ptr<T> - enable_shared_from_this<T>::shared_from_this();

-

template<class T> shared_ptr<T const> - enable_shared_from_this<T>::shared_from_this() const;

-
-

- Requires: enable_shared_from_this<T> must be an - accessible base class of T. *this must be a subobject - of an instance t of type T. -

-

- Returns: If a shared_ptr instance p that owns - t exists, a shared_ptr<T> instance r that shares - ownership with p. -

-

- Postconditions: r.get() == this. -

-

- Throws: bad_weak_ptr when no shared_ptr owns *this. -

-
-

template<class T> weak_ptr<T> - enable_shared_from_this<T>::weak_from_this() noexcept;

-

template<class T> weak_ptr<T const> - enable_shared_from_this<T>::weak_from_this() const noexcept;

-
-

- Requires: enable_shared_from_this<T> must be an - accessible base class of T. *this must be a subobject - of an instance t of type T. -

-

- Returns: If a shared_ptr instance p that owns - t exists or has existed in the past, a weak_ptr<T> instance - r that shares ownership with p. Otherwise, an empty weak_ptr. -

-
-
-

- Copyright © 2002, 2003, 2015 by Peter Dimov. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/gccspeed.gif b/gccspeed.gif deleted file mode 100644 index d78c06bbf8b6b72380950b597c32ada51e5186b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6603 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 XE|U^`I^D$cj~KekmiOo=FjxZs3WTu? diff --git a/index.html b/index.html index 0551e3c..7afe664 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,13 @@ - + -Smart Pointers - - + - + +

Automatic redirection failed, please go to -smart_ptr.htm. +doc/html/smart_ptr.html. +

>(std::allocator<int>(), 8); - - -
-

template<class T, class A>
shared_ptr<T> -allocate_shared(const A& a);

-
-
Returns:
-
A shared_ptr to a value-initialized object of type -E[N].
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[N].
-
Example:
-
boost::allocate_shared<int[8]>(std::allocator<int>());
-
-
-
-

template<class T, class A>
shared_ptr<T> -allocate_shared(const A& a, std::size_t n, -const E& v);

-
-
Returns:
-
A shared_ptr to an object of type -E[size], where each array element of type E is -initialized to v.
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[].
-
Example:
-
boost::allocate_shared<double[]>(std::allocator<double>(), 8, 1.0);
-
-
-
-

template<class T, class A>
shared_ptr<T> -allocate_shared(const A& a, const E& v);

-
-
Returns:
-
A shared_ptr to an object of type E[N], -where each array element of type E is initialized to -v.
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[N].
-
Example:
-
boost::allocate_shared<double[8]>(std::allocator<double>(), 1.0);
-
-
-
-

template<class T, class A>
shared_ptr<T> -allocate_shared_noinit(const A& a, std::size_t n);

-
-
Returns:
-
A shared_ptr to a default-initialized object of type -E[size].
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[].
-
Example:
-
boost::allocate_shared_noinit<int[]>(std::allocator<int>(), 8);
-
-
-
-

template<class T, class A>
shared_ptr<T> -allocate_shared_noinit(const A& a);

-
-
Returns:
-
A shared_ptr to a default-initialized object of type -E[N].
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[N].
-
Example:
-
boost::allocate_shared_noinit<int[8]>(std::allocator<int>());
-
-
-
-

template<class T>
shared_ptr<T> -make_shared(std::size_t n);

-
-
Returns:
-
allocate_shared<T>(std::allocator<S>(), n);
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[].
-
Example:
-
boost::make_shared<int[]>(8);
-
-
-
-

template<class T>
shared_ptr<T> -make_shared();

-
-
Returns:
-
allocate_shared<T>(std::allocator<S>());
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[N].
-
Example:
-
boost::make_shared<int[8]>();
-
-
-
-

template<class T>
shared_ptr<T> -make_shared(std::size_t n, const E& v);

-
-
Returns:
-
allocate_shared<T>(std::allocator<S>(), n, v);
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[].
-
Example:
-
boost::make_shared<double[]>(8, 1.0);
-
-
-
-

template<class T>
shared_ptr<T> -make_shared(const E& v);

-
-
Returns:
-
allocate_shared<T>(std::allocator<S>(), v);
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[N].
-
Example:
-
boost::make_shared<double[8]>(1.0);
-
-
-

template<class T>
shared_ptr<T> -make_shared_noinit(std::size_t n);

-
-
Returns:
-
allocate_shared_noinit<T>(std::allocator<S>(), n);
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[].
-
Example:
-
boost::make_shared_noinit<int[]>(8);
-
-
-
-

template<class T>
shared_ptr<T> -make_shared_noinit();

-
-
Returns:
-
allocate_shared_noinit<T>(std::allocator<S>());
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[N].
-
Example:
-
boost::make_shared_noinit<int[8]>();
-
-
- -
-

History

-
-
Boost 1.64
-
Glen Fernandes rewrote allocate_shared and make_shared for a more -optimal and more maintainable implementation.
-
Boost 1.56
-
Glen Fernandes updated overloads of make_shared and allocate_shared -to conform to the specification in C++ standard paper -N3870, including resolving C++ standard library -defect report DR 2070.
-
Boost 1.53
-
Glen Fernandes contributed implementations of make_shared and -allocate_shared for arrays.
-
-
-
-

References

-
    -
  1. N3870, -Extending make_shared to Support Arrays, Revision 1, Peter Dimov -& Glen Fernandes, January, 2014.
  2. -
  3. DR 2070, - -allocate_shared should use allocator_traits<A>::construct, -Jonathan Wakely, July, 2011.
  4. -
-
-
-Copyright 2012-2017 Glen Fernandes. Distributed under the -Boost Software License, -Version 1.0. - - diff --git a/make_unique.html b/make_unique.html deleted file mode 100644 index fdd5fd9..0000000 --- a/make_unique.html +++ /dev/null @@ -1,184 +0,0 @@ - - - - -make_unique - - -

make_unique

- -
-

Introduction

-

-The header file <boost/make_unique.hpp> provides overloads of -function template make_unique for convenient creation of -std::unique_ptr objects. -

-
-
-

Synopsis

-
-

Header <boost/smart_ptr/make_unique.hpp>

-namespace boost { -
-template<class T>
std::unique_ptr<T> -make_unique();
-
-
-template<class T, class... Args>
std::unique_ptr<T> -make_unique(Args&&... args);
-
-
-template<class T>
std::unique_ptr<T> -make_unique(T&& value);
-
-
-template<class T>
std::unique_ptr<T> -make_unique(std::size_t size);
-
-
-template<class T>
std::unique_ptr<T> -make_unique_noinit();
-
-
-template<class T>
std::unique_ptr<T> -make_unique_noinit(std::size_t size);
-
-} -
-
-
-

Common Requirements

-

template<class T, Args>
-std::unique_ptr<T> make_unique(args);

-
-
Effects:
-
Allocates storage for an object of type T (or -E[size] when T is E[], where -size is determined from args as specified by -the concrete overload). The storage is initialized from -args as specified by the concrete overload. If an exception -is thrown, the functions have no effect.
-
Returns:
-
A std::unique_ptr instance that stores and owns the -address of the newly allocated and constructed object.
-
Postconditions:
-
r.get() != 0, where r is the return -value.
-
Throws:
-
std::bad_alloc, or an exception thrown from the -initialization of the object.
-
Remarks:
-
-
    -
  • When an object of a scalar type T is specified to be initialized to -a value value, or to T(args...), where -args... is a list of constructor arguments, -make_unique shall perform this initialization via the -expression new T(value) or new T(args...) -respectively.
  • -
  • When an object of type T is specified to be -value-initialized, make_unique shall perform this -initialization via the expression new T().
  • -
  • When an object of type T is specified to be -default-initialized, make_unique_noinit shall perform this -initialization via the expression new T.
  • -
-
-
-
-
-

Free functions

-
-

template<class T, class... Args>
-std::unique_ptr<T> -make_unique(Args&&... args);

-
-
Returns:
-
A std::unique_ptr to an object of type T, -initialized to std::forward<Args>(args)....
-
Remarks:
-
This overload shall only participate in overload resolution when -T is not an array type.
-
Example:
-
boost::make_unique<double>(1.0);
-
-
-
-

template<class T>
std::unique_ptr<T> -make_unique(T&& value);

-
-
Returns:
-
A std::unique_ptr to an object of type T, -initialized to std::move(value).
-
Remarks:
-
This overload shall only participate in overload resolution when -T is not an array type.
-
Example:
-
boost::make_unique<point>({1.0, -1.0});
-
-
-

template<class T>
std::unique_ptr<T> -make_unique(std::size_t size);

-
-
Returns:
-
A std::unique_ptr to a value-initialized object of type -E[size].
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[].
-
Example:
-
boost::make_unique<int[]>(8);
-
-
-
-

template<class T>
std::unique_ptr<T> -make_unique_noinit();

-
-
Returns:
-
A std::unique_ptr to a default-initialized object of -type T.
-
Remarks:
-
This overload shall only participate in overload resolution when -T is not an array type.
-
Example:
-
boost::make_unique_noinit<std::tm>();
-
-
-
-

template<class T>
std::unique_ptr<T> -make_unique_noinit(std::size_t size);

-
-
Returns:
-
A std::unique_ptr to a default-initialized object of -type E[size].
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[].
-
Example:
-
boost::make_unique_noinit<char[]>(64);
-
-
-
-
-

History

-
-
Boost 1.56
-
Glen Fernandes contributed implementations of make_unique for -scalars and arrays
-
-
-
-Copyright 2012-2014 Glen Fernandes. Distributed under the -Boost Software License, -Version 1.0. - - diff --git a/msvcspeed.gif b/msvcspeed.gif deleted file mode 100644 index 56295ee9a506c65a672bf105bb1a0f357377f579..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6169 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 - - - pointer_cast - - - -

boost.png (6897 bytes)pointer_cast

-

The pointer cast functions (boost::static_pointer_cast boost::dynamic_pointer_cast - boost::reinterpret_pointer_cast boost::const_pointer_cast) - provide a way to write generic pointer castings for raw pointers, std::shared_ptr and std::unique_ptr. The functions - are defined in boost/pointer_cast.hpp.

-

There is test/example code in pointer_cast_test.cpp.

-

Rationale

-

Boost smart pointers usually overload those functions to provide a mechanism to - emulate pointers casts. For example, boost::shared_ptr<...> implements - a static pointer cast this way:

-
-template<class T, class U>
-    shared_ptr<T> static_pointer_cast(shared_ptr<U> const &r);
-
-

Pointer cast functions from boost/pointer_cast.hpp - are overloads of boost::static_pointer_cast, boost::dynamic_pointer_cast, - boost::reinterpret_pointer_cast and boost::const_pointer_cast - for raw pointers, std::shared_ptr and std::unique_ptr. This way when developing - pointer type independent classes, for example, memory managers or shared memory compatible classes, the same - code can be used for raw and smart pointers.

-

Synopsis

-
-
-namespace boost {
-
-template<class T, class U>
-inline T* static_pointer_cast(U *ptr)
-  { return static_cast<T*>(ptr); }
-
-template<class T, class U>
-inline T* dynamic_pointer_cast(U *ptr)
-  { return dynamic_cast<T*>(ptr); }
-
-template<class T, class U>
-inline T* const_pointer_cast(U *ptr)
-  { return const_cast<T*>(ptr); }
-
-template<class T, class U>
-inline T* reinterpret_pointer_cast(U *ptr)
-  { return reinterpret_cast<T*>(ptr); }
-
-template<class T, class U>
-inline std::shared_ptr<T> static_pointer_cast(std::shared_ptr<U> const& r);
-
-template<class T, class U>
-inline std::shared_ptr<T> dynamic_pointer_cast(std::shared_ptr<U> const& r);
-
-template<class T, class U>
-inline std::shared_ptr<T> const_pointer_cast(std::shared_ptr<U> const& r);
-
-template<class T, class U>
-inline std::shared_ptr<T> reinterpret_pointer_cast(std::shared_ptr<U> const& r);
-
-template<class T, class U>
-inline std::unique_ptr<T> static_pointer_cast(std::unique_ptr<U>&& r);
-
-template<class T, class U>
-inline std::unique_ptr<T> dynamic_pointer_cast(std::unique_ptr<U>&& r);
-
-template<class T, class U>
-inline std::unique_ptr<T> const_pointer_cast(std::unique_ptr<U>&& r);
-
-template<class T, class U>
-inline std::unique_ptr<T> reinterpret_pointer_cast(std::unique_ptr<U>&& r);
-  
-} // namespace boost
-
-
-

As you can see from the above synopsis, the pointer cast functions for raw pointers are just - wrappers around standard C++ cast operators.

- -

The pointer casts for std::shared_ptr are aliases of the corresponding standard - functions with the same names and equivalent to the - functions taking boost::shared_ptr.

- -

The pointer casts for std::unique_ptr are documented below.

- -

static_pointer_cast

-
template<class T, class U>
-  unique_ptr<T> static_pointer_cast(unique_ptr<U>&& r); // never throws
-
-

Requires: The expression static_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: unique_ptr<T>( static_cast<typename unique_ptr<T>::element_type*>(r.release()) ).

-

Throws: nothing.

-

Notes: the seemingly equivalent expression - unique_ptr<T>(static_cast<T*>(r.get())) - will eventually result in undefined behavior, attempting to delete the same - object twice.

-
-

const_pointer_cast

-
template<class T, class U>
-  unique_ptr<T> const_pointer_cast(unique_ptr<U>&& r); // never throws
-
-

Requires: The expression const_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: unique_ptr<T>( const_cast<typename unique_ptr<T>::element_type*>(r.release()) ).

-

Throws: nothing.

-
-

dynamic_pointer_cast

-
template<class T, class U>
-  unique_ptr<T> dynamic_pointer_cast(unique_ptr<U>&& r);
-
-

Requires: The expression dynamic_cast<T*>( (U*)0 ) - must be well-formed. T must have a virtual destructor.

-

Returns:

-
    -
  • - When dynamic_cast<typename unique_ptr<T>::element_type*>(r.get()) returns a nonzero value, - unique_ptr<T>(dynamic_cast<typename unique_ptr<T>::element_type*>(r.release()));
  • -
  • - Otherwise, unique_ptr<T>().
-

Throws: nothing.

-
-

reinterpret_pointer_cast

-
template<class T, class U>
-  unique_ptr<T> reinterpret_pointer_cast(unique_ptr<U>&& r); // never throws
-
-

Requires: The expression reinterpret_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: unique_ptr<T>( reinterpret_cast<typename unique_ptr<T>::element_type*>(r.release()) ).

-

Throws: nothing.

-
- -

Example

-
-
-#include <boost/pointer_cast.hpp>
-#include <boost/shared_ptr.hpp>
-
-class base
-{
-public:
-
-   virtual ~base()
-   {
-   }
-};
-
-class derived: public base
-{
-};
-
-template <class BasePtr>
-void check_if_it_is_derived(const BasePtr &ptr)
-{
-   assert(boost::dynamic_pointer_cast<derived>(ptr) != 0);
-}
-
-int main()
-{
-   // Create a raw and a shared_ptr
-
-   base *ptr = new derived;
-   boost::shared_ptr<base> sptr(new derived);
-   
-   // Check that base pointer points actually to derived class
-
-   check_if_it_is_derived(ptr);
-   check_if_it_is_derived(sptr);
-   
-   // Ok!
-   
-   delete ptr;
-   return 0;
-}
-
-

The example demonstrates how the generic pointer casts help us create pointer - independent code.

-
-

Copyright 2005 Ion Gaztañaga. Use, modification, and distribution are subject to - the Boost Software License, Version 1.0. (See accompanying file - LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)

- - diff --git a/pointer_to_other.html b/pointer_to_other.html deleted file mode 100644 index e9be750..0000000 --- a/pointer_to_other.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - pointer_to_other - - - -

boost.png (6897 bytes)pointer_to_other

-

- The pointer to other utility provides a way, given a source pointer type, - to obtain a pointer of the same type to another pointee type. The utility is - defined in boost/pointer_to_other.hpp.

-

There is test/example code in pointer_to_other_test.cpp.

-

Contents

- -

Rationale

-

When building pointer independent classes, like memory managers, allocators, or - containers, there is often a need to define pointers generically, so that if a - template parameter represents a pointer (for example, a raw or smart pointer to - an int), we can define another pointer of the same type to another pointee (a - raw or smart pointer to a float.)

-
template <class IntPtr>
-class FloatPointerHolder
-{   
-   // Let's define a pointer to a float
-   typedef typename boost::pointer_to_other
-      <IntPtr, float>::type float_ptr_t;
-   float_ptr_t float_ptr;
-};
-

Synopsis

-
-namespace boost {
-
-template<class T, class U>
-   struct pointer_to_other;
-
-template<class T, class U, template <class> class Sp>
-   struct pointer_to_other< Sp<T>, U >
-{
-   typedef Sp<U> type;
-};
-
-template<class T, class T2, class U,
-        template <class, class> class Sp>
-   struct pointer_to_other< Sp<T, T2>, U >
-{
-   typedef Sp<U, T2> type;
-};
-
-template<class T, class T2, class T3, class U,
-        template <class, class, class> class Sp>
-struct pointer_to_other< Sp<T, T2, T3>, U >
-{
-   typedef Sp<U, T2, T3> type;
-};
-
-template<class T, class U>
-struct pointer_to_other< T*, U > 
-{
-   typedef U* type;
-};
-
-} // namespace boost
-

If these definitions are not correct for a specific smart pointer, we can define - a specialization of pointer_to_other.

-

Example

-
// Let's define a memory allocator that can
-// work with raw and smart pointers
-
-#include <boost/pointer_to_other.hpp>
-
-template <class VoidPtr>
-class memory_allocator
-{
-   // Predefine a memory_block 
-   struct block;
-
-   // Define a pointer to a memory_block from a void pointer
-   // If VoidPtr is void *, block_ptr_t is block*
-   // If VoidPtr is smart_ptr<void>, block_ptr_t is smart_ptr<block>
-   typedef typename boost::pointer_to_other      
-            <VoidPtr, block>::type block_ptr_t;
-            
-   struct block
-   {
-      std::size_t size;
-      block_ptr_t next_block;
-   };
-
-   block_ptr_t free_blocks;
-};
-

As we can see, using pointer_to_other we can create pointer independent code.

-
-

$Date$

-

Copyright 2005, 2006 Ion Gaztañaga and Peter Dimov. Use, modification, - and distribution are subject to the Boost Software License, Version 1.0.
- (See accompanying file LICENSE_1_0.txt or a - copy at < http://www.boost.org/LICENSE_1_0.txt>.)

- - diff --git a/scoped_array.htm b/scoped_array.htm deleted file mode 100644 index 3624e5d..0000000 --- a/scoped_array.htm +++ /dev/null @@ -1,115 +0,0 @@ - - - - scoped_array - - - -

boost.png (6897 bytes)scoped_array class template

-

The scoped_array class template stores a pointer to a dynamically - allocated array. (Dynamically allocated arrays are allocated with the C++ new[] - expression.) The array pointed to is guaranteed to be deleted, either on - destruction of the scoped_array, or via an explicit reset.

-

The scoped_array template is a simple solution for simple needs. It - supplies a basic "resource acquisition is initialization" facility, without - shared-ownership or transfer-of-ownership semantics. Both its name and - enforcement of semantics (by being - noncopyable) signal its intent to retain ownership solely within the - current scope. Because it is noncopyable, - it is safer than shared_array for pointers which should not be copied.

-

Because scoped_array is so simple, in its usual implementation every - operation is as fast as a built-in array pointer and it has no more space - overhead that a built-in array pointer.

-

It cannot be used in C++ standard library containers. See - shared_array if scoped_array does not meet your needs.

-

It cannot correctly hold a pointer to a single object. See scoped_ptr - for that usage.

-

A std::vector is an alternative to a scoped_array that is a bit - heavier duty but far more flexible. A boost::array is an alternative - that does not use dynamic allocation.

-

The class template is parameterized on T, the type of the object pointed - to. T must meet the smart pointer - common requirements.

-

Synopsis

-
namespace boost {
-
-  template<class T> class scoped_array : noncopyable {
-
-    public:
-      typedef T element_type;
-
-      explicit scoped_array(T * p = 0); // never throws
-      ~scoped_array(); // never throws
-
-      void reset(T * p = 0); // never throws
-
-      T & operator[](std::ptrdiff_t i) const; // never throws
-      T * get() const; // never throws
-     
-      operator unspecified-bool-type() const; // never throws
-
-      void swap(scoped_array & b); // never throws
-  };
-
-  template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws
-
-}
-

Members

-

- element_type

-
typedef T element_type;
-

Provides the type of the stored pointer.

-

constructors

-
explicit scoped_array(T * p = 0); // never throws
-

Constructs a scoped_array, storing a copy of p, which must have - been allocated via a C++ new[] expression or be 0. T is not - required be a complete type. See the smart pointer - common requirements.

-

destructor

-
~scoped_array(); // never throws
-

Deletes the array pointed to by the stored pointer. Note that delete[] on - a pointer with a value of 0 is harmless. The guarantee that this does not throw - exceptions depends on the requirement that the deleted array's objects' - destructors do not throw exceptions. See the smart pointer - common requirements.

-

reset

-
void reset(T * p = 0); // never throws
-

- Deletes the array pointed to by the stored pointer and then stores a copy of p, - which must have been allocated via a C++ new[] expression or be 0. The - guarantee that this does not throw exceptions depends on the requirement that - the deleted array's objects' destructors do not throw exceptions. See the smart - pointer common requirements.

-

subscripting

-
T & operator[](std::ptrdiff_t i) const; // never throws
-

Returns a reference to element i of the array pointed to by the stored - pointer. Behavior is undefined and almost certainly undesirable if the stored - pointer is 0, or if i is less than 0 or is greater than or equal to the - number of elements in the array.

-

get

-
T * get() const; // never throws
-

Returns the stored pointer. T need not be a complete type. See the smart - pointer common requirements.

-

conversions

-
operator unspecified-bool-type () const; // never throws
-

Returns an unspecified value that, when used in boolean contexts, is equivalent - to get() != 0.

-

swap

-
void swap(scoped_array & b); // never throws
-

Exchanges the contents of the two smart pointers. T need not be a - complete type. See the smart pointer common - requirements.

-

Free Functions

-

swap

-
template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws
-

Equivalent to a.swap(b). Matches the interface of std::swap. - Provided as an aid to generic programming.

-
-

$Date$

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/scoped_ptr.htm b/scoped_ptr.htm deleted file mode 100644 index 1dbfbce..0000000 --- a/scoped_ptr.htm +++ /dev/null @@ -1,180 +0,0 @@ - - - - scoped_ptr - - - -

boost.png (6897 bytes)scoped_ptr class template

-

The scoped_ptr class template stores a pointer to a dynamically allocated - object. (Dynamically allocated objects are allocated with the C++ new expression.) - The object pointed to is guaranteed to be deleted, either on destruction of the scoped_ptr, - or via an explicit reset. See the example.

-

The scoped_ptr template is a simple solution for simple needs. It - supplies a basic "resource acquisition is initialization" facility, without - shared-ownership or transfer-of-ownership semantics. Both its name and - enforcement of semantics (by being - noncopyable) signal its intent to retain ownership solely within the - current scope. Because it is noncopyable, - it is safer than shared_ptr or std::auto_ptr for pointers which - should not be copied.

-

Because scoped_ptr is simple, in its usual implementation every operation - is as fast as for a built-in pointer and it has no more space overhead that a - built-in pointer.

-

scoped_ptr cannot be used in C++ Standard Library containers. - Use shared_ptr if you need a smart pointer - that can.

-

scoped_ptr cannot correctly hold a pointer to a dynamically - allocated array. See scoped_array for - that usage.

-

The class template is parameterized on T, the type of the object pointed - to. T must meet the smart pointer - common requirements.

-

Synopsis

-
namespace boost {
-
-  template<class T> class scoped_ptr : noncopyable {
-
-   public:
-     typedef T element_type;
-
-     explicit scoped_ptr(T * p = 0); // never throws
-     ~scoped_ptr(); // never throws
-
-     void reset(T * p = 0); // never throws
-
-     T & operator*() const; // never throws
-     T * operator->() const; // never throws
-     T * get() const; // never throws
-     
-     operator unspecified-bool-type() const; // never throws
-
-     void swap(scoped_ptr & b); // never throws
-  };
-
-  template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
-
-}
-

Members

-

element_type

-
typedef T element_type;
-

Provides the type of the stored pointer.

-

constructors

-
explicit scoped_ptr(T * p = 0); // never throws
-

Constructs a scoped_ptr, storing a copy of p, which must have been - allocated via a C++ new expression or be 0. T is not required be - a complete type. See the smart pointer common - requirements.

-

destructor

-
~scoped_ptr(); // never throws
-

Destroys the object pointed to by the stored pointer, if any, as if by using delete - this->get().

-

- The guarantee that this does not throw exceptions depends on the requirement - that the deleted object's destructor does not throw exceptions. See the smart - pointer common requirements.

-

reset

-
void reset(T * p = 0); // never throws
-

- Deletes the object pointed to by the stored pointer and then stores a copy of - p, which must have been allocated via a C++ new expression or be 0. The - guarantee that this does not throw exceptions depends on the requirement that - the deleted object's destructor does not throw exceptions. See the smart - pointer common requirements.

-

indirection

-
T & operator*() const; // never throws
-

Returns a reference to the object pointed to by the stored pointer. Behavior is - undefined if the stored pointer is 0.

-
T * operator->() const; // never throws
-

Returns the stored pointer. Behavior is undefined if the stored pointer is 0.

-

get

-
T * get() const; // never throws
-

Returns the stored pointer. T need not be a complete type. See the smart - pointer common requirements.

-

conversions

-
operator unspecified-bool-type () const; // never throws
-

Returns an unspecified value that, when used in boolean contexts, is equivalent - to get() != 0.

-

swap

-
void swap(scoped_ptr & b); // never throws
-

Exchanges the contents of the two smart pointers. T need not be a - complete type. See the smart pointer common - requirements.

-

Free Functions

-

swap

-
template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
-

Equivalent to a.swap(b). Matches the interface of std::swap. - Provided as an aid to generic programming.

-

Example

-

Here's an example that uses scoped_ptr.

-
-
#include <boost/scoped_ptr.hpp>
-#include <iostream>
-
-struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } };
-
-class MyClass {
-    boost::scoped_ptr<int> ptr;
-  public:
-    MyClass() : ptr(new int) { *ptr = 0; }
-    int add_one() { return ++*ptr; }
-};
-
-int main()
-{
-    boost::scoped_ptr<Shoe> x(new Shoe);
-    MyClass my_instance;
-    std::cout << my_instance.add_one() << '\n';
-    std::cout << my_instance.add_one() << '\n';
-}
-
-

The example program produces the beginning of a child's nursery rhyme:

-
-
1
-2
-Buckle my shoe
-
-

Rationale

-

The primary reason to use scoped_ptr rather than auto_ptr is to - let readers of your code know that you intend "resource acquisition is - initialization" to be applied only for the current scope, and have no intent to - transfer ownership.

-

A secondary reason to use scoped_ptr is to prevent a later maintenance - programmer from adding a function that transfers ownership by returning the auto_ptr, - because the maintenance programmer saw auto_ptr, and assumed ownership - could safely be transferred.

-

Think of bool vs int. We all know that under the covers bool - is usually just an int. Indeed, some argued against including bool - in the C++ standard because of that. But by coding bool rather than int, - you tell your readers what your intent is. Same with scoped_ptr; by - using it you are signaling intent.

-

It has been suggested that scoped_ptr<T> is equivalent to std::auto_ptr<T> - const. Ed Brey pointed out, however, that reset will not work on - a std::auto_ptr<T> const.

-

Handle/Body Idiom

-

One common usage of scoped_ptr is to implement a handle/body (also called - pimpl) idiom which avoids exposing the body (implementation) in the header - file.

-

The scoped_ptr_example_test.cpp - sample program includes a header file, scoped_ptr_example.hpp, - which uses a scoped_ptr<> to an incomplete type to hide the - implementation. The instantiation of member functions which require a complete - type occurs in the scoped_ptr_example.cpp - implementation file.

-

Frequently Asked Questions

-

Q. Why doesn't scoped_ptr have a release() member?
- A. When reading source code, it is valuable to be able to draw - conclusions about program behavior based on the types being used. If scoped_ptr - had a release() member, it would become possible to transfer ownership of the - held pointer, weakening its role as a way of limiting resource lifetime to a - given context. Use std::auto_ptr where transfer of ownership - is required. (supplied by Dave Abrahams)

-
-

$Date

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/shared_array.htm b/shared_array.htm deleted file mode 100644 index 8fa5a7f..0000000 --- a/shared_array.htm +++ /dev/null @@ -1,183 +0,0 @@ - - - - shared_array - - - -

boost.png (6897 bytes)shared_array class template

-

The shared_array class template stores a pointer to a dynamically - allocated array. (Dynamically allocated array are allocated with the C++ new[] - expression.) The object pointed to is guaranteed to be deleted when the last shared_array - pointing to it is destroyed or reset.

-

Every shared_array meets the CopyConstructible and Assignable - requirements of the C++ Standard Library, and so can be used in standard - library containers. Comparison operators are supplied so that shared_array - works with the standard library's associative containers.

-

Normally, a shared_array cannot correctly hold a pointer to an object - that has been allocated with the non-array form of new. See - shared_ptr for that usage.

-

Because the implementation uses reference counting, cycles of shared_array - instances will not be reclaimed. For example, if main() holds a shared_array - to A, which directly or indirectly holds a shared_array back to A, - A's use count will be 2. Destruction of the original shared_array - will leave A dangling with a use count of 1.

-

A shared_ptr to a std::vector is an alternative to a shared_array - that is a bit heavier duty but far more flexible.

-

The class template is parameterized on T, the type of the object pointed - to. T must meet the smart pointer - common requirements.

-

Synopsis

-
namespace boost {
-
-  template<class T> class shared_array {
-
-    public:
-      typedef T element_type;
-
-      explicit shared_array(T * p = 0);
-      template<class D> shared_array(T * p, D d);
-      ~shared_array(); // never throws
-
-      shared_array(shared_array const & r); // never throws
-
-      shared_array & operator=(shared_array const & r); // never throws
-
-      void reset(T * p = 0);
-      template<class D> void reset(T * p, D d);
-
-      T & operator[](std::ptrdiff_t i) const; // never throws
-      T * get() const; // never throws
-
-      bool unique() const; // never throws
-      long use_count() const; // never throws
-
-      operator unspecified-bool-type() const; // never throws
-
-      void swap(shared_array<T> & b); // never throws
-  };
-
-  template<class T>
-    bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws
-  template<class T>
-    bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws
-  template<class T>
-    bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws
-
-  template<class T> void swap(shared_array<T> & a, shared_array<T> & b); // never throws
-
-}
-

Members

-

element_type

-
typedef T element_type;
-

Provides the type of the stored pointer.

-

constructors

-
explicit shared_array(T * p = 0);
-

Constructs a shared_array, storing a copy of p, which must be a - pointer to an array that was allocated via a C++ new[] expression or be - 0. Afterwards, the use count is 1 (even if p == 0; see - ~shared_array). The only exception which may be thrown by this - constructor is std::bad_alloc. If an exception is thrown, delete[] p - is called.

-
template<class D> shared_array(T * p, D d);
-

Constructs a shared_array, storing a copy of p and of d. - Afterwards, the use count is 1. D's copy - constructor and destructor must not throw. When the the time comes to delete - the array pointed to by p, the object d is used in the statement d(p). - Invoking the object d with parameter p in this way must not - throw. The only exception which may be thrown by this constructor is std::bad_alloc. - If an exception is thrown, d(p) is called.

-
shared_array(shared_array const & r); // never throws
-

Constructs a shared_array, as if by storing a copy of the pointer stored - in r. Afterwards, the use count for all copies - is 1 more than the initial use count.

-

destructor

-
~shared_array(); // never throws
-

Decrements the use count. Then, if the use count is 0, - deletes the array pointed to by the stored pointer. Note that delete[] on - a pointer with a value of 0 is harmless. T need not be a complete type. - The guarantee that this 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_array & operator=(shared_array const & r); // never throws
-

Constructs a new shared_array as described above, - then replaces this shared_array with the new one, destroying the - replaced object.

-

reset

-
void reset(T * p = 0);
-

Constructs a new shared_array as described above, - then replaces this shared_array with the new one, destroying the - replaced object. The only exception which may be thrown is std::bad_alloc. - If an exception is thrown, delete[] p is called.

-
template<class D> void reset(T * p, D d);
-

Constructs a new shared_array as described above, - then replaces this shared_array with the new one, destroying the - replaced object. D's copy constructor must not throw. The only exception - which may be thrown is std::bad_alloc. If an exception is thrown, d(p) - is called.

-

indexing

-
T & operator[](std::ptrdiff_t i) const; // never throws
-

Returns a reference to element i of the array pointed to by the stored - pointer. Behavior is undefined and almost certainly undesirable if the stored - pointer is 0, or if i is less than 0 or is greater than or equal to the - number of elements in the array.

-

get

-
T * get() const; // never throws
-

Returns the stored pointer. T need not be a complete type. See the smart - pointer common requirements.

-

unique

-
bool unique() const; // never throws
-

Returns true if no other shared_array is sharing ownership of the stored - pointer, false otherwise. T need not be a complete type. See the smart - pointer common requirements.

-

use_count

-
long use_count() const; // never throws
-

Returns the number of shared_array objects sharing ownership of the - stored pointer. T need not be a complete type. See the smart pointer - common requirements.

-

Because use_count is not necessarily efficient to implement for - implementations of shared_array that do not use an explicit reference - count, it might be removed from some future version. Thus it should be used for - debugging purposes only, and not production code.

-

conversions

-
operator unspecified-bool-type () const; // never throws
-

Returns an unspecified value that, when used in boolean contexts, is equivalent - to get() != 0.

-

swap

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

Exchanges the contents of the two smart pointers. T need not be a - complete type. See the smart pointer common - requirements.

-

Free Functions

-

comparison

-
template<class T>
-  bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws
-template<class T>
-  bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws
-template<class T>
-  bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws
-

Compares the stored pointers of the two smart pointers. T need not be a - complete type. See the smart pointer common - requirements.

-

The operator< overload is provided to define an ordering so that shared_array - objects can be used in associative containers such as std::map. The - implementation uses std::less<T *> to perform the comparison. This - ensures that the comparison is handled correctly, since the standard mandates - that relational operations on pointers are unspecified (5.9 [expr.rel] - paragraph 2) but std::less<> on pointers is well-defined (20.3.3 - [lib.comparisons] paragraph 8).

-

swap

-
template<class T>
-  void swap(shared_array<T> & a, shared_array<T> & b) // never throws
-

Equivalent to a.swap(b). Matches the interface of std::swap. - Provided as an aid to generic programming.

-
-

$Date$

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/shared_ptr.htm b/shared_ptr.htm deleted file mode 100644 index 1cd0bc4..0000000 --- a/shared_ptr.htm +++ /dev/null @@ -1,858 +0,0 @@ - - - - shared_ptr - - - -

boost.png (6897 bytes)shared_ptr class template

-

Introduction
- Best Practices
- Synopsis
- Members
- Free Functions
- Example
- Handle/Body Idiom
- Thread Safety
- Frequently Asked Questions
- Smart Pointer Timings
- Programming Techniques

-

Introduction

-

The shared_ptr class template stores a pointer to a dynamically allocated - object, typically with a C++ new-expression. The object pointed to is - guaranteed to be deleted when the last shared_ptr pointing to it is - destroyed or reset.

-
Example:
shared_ptr<X> p1( new X );
-shared_ptr<void> p2( new int(5) );
-
- -

shared_ptr deletes the exact pointer that has been passed at construction time, - complete with its original type, regardless of the template parameter. In the second example above, - when p2 is destroyed or reset, it will call delete on the original int* - that has been passed to the constructor, even though p2 itself is of type - shared_ptr<void> and stores a pointer of type void*.

- -

Every shared_ptr meets the CopyConstructible, MoveConstructible, - CopyAssignable and MoveAssignable - requirements of the C++ Standard Library, and can be used in standard - library containers. Comparison operators are supplied so that shared_ptr - works with the standard library's associative containers.

-

Because the implementation uses reference counting, cycles of shared_ptr instances - will not be reclaimed. 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. Use weak_ptr - to "break cycles."

-

The class template is parameterized on T, the type of the object pointed - 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>.

-

shared_ptr is now part of the C++11 Standard, as std::shared_ptr.

-

Starting with Boost release 1.53, shared_ptr can be used to hold a pointer to a dynamically - allocated array. This is accomplished by using an array type (T[] or T[N]) as - the template parameter. There is almost no difference between using an unsized array, T[], - and a sized array, T[N]; the latter just enables operator[] to perform a range check - on the index.

-
Example:
shared_ptr<double[1024]> p1( new double[1024] );
-shared_ptr<double[]> p2( new double[n] );
-
- -

Best Practices

-

A simple guideline that nearly eliminates the possibility of memory leaks is: - always use a named smart pointer variable to hold the result of new. - Every occurence of the new keyword in the code should have the - form:

-
shared_ptr<T> p(new Y);
-

It is, of course, acceptable to use another smart pointer in place of shared_ptr - above; having T and Y be the same type, or - passing arguments to Y's constructor is also OK.

-

If you observe this guideline, it naturally follows that you will have no - explicit delete statements; try/catch constructs will - be rare.

-

Avoid using unnamed shared_ptr temporaries to save typing; to - see why this is dangerous, consider this example:

-
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() );
-}
-
-

The function ok follows the guideline to the letter, whereas - bad constructs the temporary shared_ptr in place, - admitting the possibility of a memory leak. Since function arguments are - evaluated in unspecified order, it is possible for new int(2) to - be evaluated first, g() second, and we may never get to the - shared_ptrconstructor if g throws an exception. - See Herb Sutter's treatment (also - here) of the issue for more information.

-

The exception safety problem described above may also be eliminated by using - the make_shared - or allocate_shared - factory functions defined in boost/make_shared.hpp. - These factory functions also provide an efficiency benefit by consolidating allocations.

-

Synopsis

-
namespace boost {
-
-  class bad_weak_ptr: public std::exception;
-
-  template<class T> class weak_ptr;
-
-  template<class T> class shared_ptr {
-
-    public:
-
-      typedef see below element_type;
-
-      shared_ptr(); // never throws
-      shared_ptr(std::nullptr_t); // never throws
-
-      template<class Y> explicit shared_ptr(Y * p);
-      template<class Y, class D> shared_ptr(Y * p, D d);
-      template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
-      template<class D> shared_ptr(std::nullptr_t p, D d);
-      template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);
-
-      ~shared_ptr(); // never throws
-
-      shared_ptr(shared_ptr const & r); // never throws
-      template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
-
-      shared_ptr(shared_ptr && r); // never throws
-      template<class Y> shared_ptr(shared_ptr<Y> && r); // never throws
-
-      template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p); // never throws
-
-      template<class Y> shared_ptr(shared_ptr<Y> && r, element_type * p); // never throws
-
-      template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
-
-      template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
-      template<class Y> shared_ptr(std::auto_ptr<Y> && r);
-
-      template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
-
-      shared_ptr & operator=(shared_ptr const & r); // never throws
-      template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
-
-      shared_ptr & operator=(shared_ptr const && r); // never throws
-      template<class Y> shared_ptr & operator=(shared_ptr<Y> const && r); // never throws
-
-      template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
-      template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r);
-
-      template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);
-
-      shared_ptr & operator=(std::nullptr_t); // never throws
-
-      void reset(); // never throws
-
-      template<class Y> void reset(Y * p);
-      template<class Y, class D> void reset(Y * p, D d);
-      template<class Y, class D, class A> void reset(Y * p, D d, A a);
-
-      template<class Y> void reset(shared_ptr<Y> const & r, element_type * p); // never throws
-
-      T & operator*() const; // never throws; only valid when T is not an array type
-      T * operator->() const; // never throws; only valid when T is not an array type
-
-      element_type & operator[](std::ptrdiff_t i) const; // never throws; only valid when T is an array type
-
-      element_type * get() const; // never throws
-
-      bool unique() const; // never throws
-      long use_count() const; // never throws
-
-      explicit operator bool() const; // never throws
-
-      void swap(shared_ptr & b); // never throws
-      
-      template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const; // never throws
-      template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const; // never throws
-  };
-
-  template<class T, class U>
-    bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
-
-  template<class T, class U>
-    bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
-
-  template<class T, class U>
-    bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
-
-  template<class T>
-    bool operator==(shared_ptr<T> const & p, std::nullptr_t); // never throws
-
-  template<class T>
-    bool operator==(std::nullptr_t, shared_ptr<T> const & p); // never throws
-
-  template<class T>
-    bool operator!=(shared_ptr<T> const & p, std::nullptr_t); // never throws
-
-  template<class T>
-    bool operator!=(std::nullptr_t, shared_ptr<T> const & p); // never throws
-
-  template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
-
-  template<class T> typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p); // never throws
-
-  template<class T, class U>
-    shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws
-
-  template<class T, class U>
-    shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws
-
-  template<class T, class U>
-    shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r); // never throws
-
-  template<class T, class U>
-    shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r); // never throws
-
-  template<class E, class T, class Y>
-    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
-
-  template<class D, class T>
-    D * get_deleter(shared_ptr<T> const & p);
-}
-

Members

-

element_type

-
typedef ... element_type;
-
-

element_type is T when T is not an array type, - and U when T is U[] or U[N].

-
-

default constructor

-
shared_ptr(); // never throws
-shared_ptr(std::nullptr_t); // never throws
-
-

Effects: Constructs an empty shared_ptr.

-

Postconditions: use_count() == 0 && get() == 0.

-

Throws: nothing.

-
-

[The nothrow guarantee is important, since reset() is specified - in terms of the default constructor; this implies that the constructor must not - allocate memory.]

-

pointer constructor

-
template<class Y> explicit shared_ptr(Y * p);
-
-

Requirements: - Y must be a complete type. - The expression delete[] p, when T is an array type, or delete p, - when T is not an array type, - must be well-formed, must not invoke undefined behavior, and must not throw exceptions. - When T is U[N], Y (*) [N] must be convertible to T*; - when T is U[], Y (*) [] must be convertible to T*; - otherwise, Y* must be convertible to T*. -

-

Effects: - When T is not an array type, constructs a shared_ptr that owns - the pointer p. - Otherwise, constructs a shared_ptr that owns - p and a deleter of an unspecified type that calls delete[] p.

-

Postconditions: use_count() == 1 && get() == p. - If T is not an array type and p is unambiguously convertible to - enable_shared_from_this<V>* - for some V, p->shared_from_this() returns a copy of - *this.

-

Throws: std::bad_alloc, or an implementation-defined - exception when a resource other than memory could not be obtained.

-

Exception safety: If an exception is thrown, the constructor calls - delete[] p, when T is an array type, - or delete p, when T is not an array type.

-

Notes: p must be a pointer to an object that was - allocated via a C++ new expression or be 0. The postcondition that - use count is 1 holds even if p is 0; invoking delete - on a pointer that has a value of 0 is harmless.

-
-

[This constructor is a template in order to remember the actual - pointer type passed. The destructor will call delete with the - same pointer, complete with its original type, even when T does - not have a virtual destructor, or is void.]

-

constructors taking a deleter

-
template<class Y, class D> shared_ptr(Y * p, D d);
-template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
-template<class D> shared_ptr(std::nullptr_t p, D d);
-template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);
-
-

Requirements: - D must be CopyConstructible. 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. - A must be an Allocator, as described in section 20.1.5 - (Allocator requirements) of the C++ Standard. - When T is U[N], Y (*) [N] must be convertible to T*; - when T is U[], Y (*) [] must be convertible to T*; - otherwise, Y* must be convertible to T*. -

-

Effects: Constructs a shared_ptr that owns the pointer - p and the deleter d. The constructors taking an allocator a - allocate memory using a copy of a.

-

Postconditions: use_count() == 1 && get() == p. - If T is not an array type and p is unambiguously convertible to - enable_shared_from_this<V>* - for some V, p->shared_from_this() returns a copy of - *this.

-

Throws: std::bad_alloc, or an implementation-defined - exception when a resource other than memory could not be obtained.

-

Exception safety: If an exception is thrown, d(p) is called.

-

Notes: When the the time comes to delete the object pointed to by p, - the stored copy of d is invoked with the stored copy of p - as an argument.

-
-

[Custom deallocators allow a factory function returning a shared_ptr - 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 shared_ptr - to a statically allocated object, and other variations allow a shared_ptr - to be used as a wrapper for another smart pointer, easing interoperability.

-

The support for custom deallocators does not impose significant overhead. Other - shared_ptr features still require a deallocator to be kept.

-

The requirement that the copy constructor of D does not throw comes from - the pass by value. If the copy constructor throws, the pointer would leak.]

-

copy and converting constructors

-
shared_ptr(shared_ptr const & r); // never throws
-template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
-
-

Requires: Y* should be convertible to T*.

-

Effects: If r is empty, constructs an empty shared_ptr; - otherwise, constructs a shared_ptr that shares ownership with r.

-

Postconditions: get() == r.get() && use_count() == - r.use_count().

-

Throws: nothing.

-
-

move constructors

-
shared_ptr(shared_ptr && r); // never throws
-template<class Y> shared_ptr(shared_ptr<Y> && r); // never throws
-
-

Requires: Y* should be convertible to T*.

-

Effects: Move-constructs a shared_ptr from r.

-

Postconditions: *this contains the old value of r. r is empty and r.get() == 0.

-

Throws: nothing.

-
-

aliasing constructor

-
template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p); // never throws
-
-

Effects: constructs a shared_ptr that shares ownership with - r and stores p.

-

Postconditions: get() == p && use_count() == r.use_count().

-

Throws: nothing.

-
-

aliasing move constructor

-
template<class Y> shared_ptr(shared_ptr<Y> && r, element_type * p); // never throws
-
-

- Effects: Move-constructs a shared_ptr from r, while - storing p instead. -

-

Postconditions: get() == p and use_count() equals the old count of r. r is empty and r.get() == 0.

-

Throws: nothing.

-
-

weak_ptr constructor

-
template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
-
-

Requires: Y* should be convertible to T*.

-

Effects: Constructs a shared_ptr that shares ownership with - r and stores a copy of the pointer stored in r.

-

Postconditions: use_count() == r.use_count().

-

Throws: bad_weak_ptr when r.use_count() == 0.

-

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

-
-

auto_ptr constructors

-
template<class Y> shared_ptr(std::auto_ptr<Y> & r);
-template<class Y> shared_ptr(std::auto_ptr<Y> && r);
-
-

Requires: Y* should be convertible to T*.

-

Effects: Constructs a shared_ptr, as if by storing a copy of r.release().

-

Postconditions: use_count() == 1.

-

Throws: std::bad_alloc, or an implementation-defined - exception when a resource other than memory could not be obtained.

-

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

-
-

unique_ptr constructor

-
template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
-
-

Requires: Y* should be convertible to T*.

-

Effects: - Equivalent to shared_ptr(r.release(), r.get_deleter()) when D is not a reference type. - Otherwise, equivalent to shared_ptr(r.release(), del), where del is a deleter - that stores the reference rd returned from r.get_deleter() and del(p) calls rd(p).

-

Postconditions: use_count() == 1.

-

Throws: std::bad_alloc, or an implementation-defined - exception when a resource other than memory could not be obtained.

-

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

-
-

destructor

-
~shared_ptr(); // never throws
-
-

Effects:

-
    -
  • - If *this is empty, or shares ownership with - another shared_ptr instance (use_count() > 1), - there are no side effects.
  • -
  • - Otherwise, if *this owns a pointer p - and a deleter d, d(p) - is called.
  • -
  • - Otherwise, *this owns a pointer p, - and delete p is called.
  • -
-

Throws: nothing.

-
-

assignment

-
shared_ptr & operator=(shared_ptr const & r); // never throws
-template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
-template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
-
-

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

-

Returns: *this.

-

Notes: The use count updates caused by the temporary object construction - and destruction are not considered observable side effects, and the - implementation is free to meet the effects (and the implied guarantees) via - different means, without creating a temporary. In particular, in the example:

-
shared_ptr<int> p(new int);
-shared_ptr<void> q(p);
-p = p;
-q = p;
-
-

both assignments may be no-ops.

-
-
shared_ptr & operator=(shared_ptr && r); // never throws
-template<class Y> shared_ptr & operator=(shared_ptr<Y> && r); // never throws
-template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r);
-template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);
-
-

Effects: Equivalent to shared_ptr(std::move(r)).swap(*this).

-

Returns: *this.

-
-
shared_ptr & operator=(std::nullptr_t); // never throws
-
-

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

-

Returns: *this.

-
-

reset

-
void reset(); // never throws
-
-

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

-
-
template<class Y> void reset(Y * p);
-
-

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

-
-
template<class Y, class D> void reset(Y * p, D d);
-
-

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

-
-
template<class Y, class D, class A> void reset(Y * p, D d, A a);
-
-

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

-
-
template<class Y> void reset(shared_ptr<Y> const & r, element_type * p); // never throws
-
-

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

-
-

indirection

-
T & operator*() const; // never throws
-
-

Requirements: T should not be an array type. The stored pointer must not be 0.

-

Returns: a reference to the object pointed to by the stored pointer.

-

Throws: nothing.

-
-
T * operator->() const; // never throws
-
-

Requirements: T should not be an array type. The stored pointer must not be 0.

-

Returns: the stored pointer.

-

Throws: nothing.

-
-
element_type & operator[](std::ptrdiff_t i) const; // never throws
-
-

Requirements: T should be an array type. The stored pointer must not be 0. - i >= 0. If T is U[N], i < N.

-

Returns: get()[i].

-

Throws: nothing.

-
-

get

-
element_type * get() const; // never throws
-
-

Returns: the stored pointer.

-

Throws: nothing.

-
-

unique

-
bool unique() const; // never throws
-
-

Returns: use_count() == 1.

-

Throws: nothing.

-

Notes: unique() may be faster than use_count(). - If you are using unique() to implement copy on write, do not rely - on a specific value when the stored pointer is zero.

-
-

use_count

-
long use_count() const; // never throws
-
-

Returns: the number of shared_ptr objects, *this included, - that share ownership with *this, or 0 when *this - is empty.

-

Throws: nothing.

-

Notes: use_count() is not necessarily efficient. Use only - for debugging and testing purposes, not for production code.

-
-

conversions

-
explicit operator bool() const; // never throws
-
-

Returns: get() != 0.

-

Throws: nothing.

-

Notes: This conversion operator allows shared_ptr objects to be - used in boolean contexts, like if(p && p->valid()) {}.

-
-

[The conversion to bool is not merely syntactic sugar. It allows shared_ptrs - to be declared in conditions when using dynamic_pointer_cast - or weak_ptr::lock.]

-

swap

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

Effects: Exchanges the contents of the two smart pointers.

-

Throws: nothing.

-
-

swap

-
template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const; // never throws
-template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const; // never throws
-
-

Effects: See the description of operator<.

-

Throws: nothing.

-
-

Free Functions

-

comparison

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

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

-

Throws: nothing.

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

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

-

Throws: nothing.

-
-
template<class T>
-  bool operator==(shared_ptr<T> const & p, std::nullptr_t); // never throws
-template<class T>
-  bool operator==(std::nullptr_t, shared_ptr<T> const & p); // never throws
-
-

Returns: p.get() == 0.

-

Throws: nothing.

-
-
template<class T>
-  bool operator!=(shared_ptr<T> const & p, std::nullptr_t); // never throws
-template<class T>
-  bool operator!=(std::nullptr_t, shared_ptr<T> const & p); // never throws
-
-

Returns: p.get() != 0.

-

Throws: nothing.

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

Returns: an unspecified value such that

-
    -
  • - operator< is a strict weak ordering as described in section 25.3 [lib.alg.sorting] - of the C++ standard;
  • -
  • - under the equivalence relation defined by operator<, !(a - < b) && !(b < a), two shared_ptr instances - are equivalent if and only if they share ownership or are both empty.
-

Throws: nothing.

-

Notes: Allows shared_ptr objects to be used as keys in - associative containers.

-
-

[Operator< has been preferred over a std::less - specialization for consistency and legality reasons, as std::less - is required to return the results of operator<, and many - standard algorithms use operator< instead of std::less - for comparisons when a predicate is not supplied. Composite objects, like std::pair, - also implement their operator< in terms of their contained - subobjects' operator<.

-

The rest of the comparison operators are omitted by design.]

-

swap

-
template<class T>
-  void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
-
-

Effects: Equivalent to a.swap(b).

-

Throws: nothing.

-

Notes: Matches the interface of std::swap. Provided as an aid to - generic programming.

-
-

[swap is defined in the same namespace as shared_ptr - as this is currently the only legal way to supply a swap function - that has a chance to be used by the standard library.]

-

get_pointer

-
template<class T>
-  typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p); // never throws
-
-

Returns: p.get().

-

Throws: nothing.

-

Notes: Provided as an aid to generic programming. Used by - mem_fn.

-
-

static_pointer_cast

-
template<class T, class U>
-  shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws
-
-

Requires: The expression static_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: shared_ptr<T>( r, static_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

-

Throws: nothing.

-

Notes: the seemingly equivalent expression - shared_ptr<T>(static_cast<T*>(r.get())) - will eventually result in undefined behavior, attempting to delete the same - object twice.

-
-

const_pointer_cast

-
template<class T, class U>
-  shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws
-
-

Requires: The expression const_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: shared_ptr<T>( r, const_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

-

Throws: nothing.

-
-

dynamic_pointer_cast

-
template<class T, class U>
-  shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r);
-
-

Requires: The expression dynamic_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns:

-
    -
  • - When dynamic_cast<typename shared_ptr<T>::element_type*>(r.get()) returns a nonzero value p, - shared_ptr<T>(r, p);
  • -
  • - Otherwise, shared_ptr<T>().
-

Throws: nothing.

-
-

reinterpret_pointer_cast

-
template<class T, class U>
-  shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r); // never throws
-
-

Requires: The expression reinterpret_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: shared_ptr<T>( r, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

-

Throws: nothing.

-
-

operator<<

-
template<class E, class T, class Y>
-    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
-
-

Effects: os << p.get();.

-

Returns: os.

-
-

get_deleter

-
template<class D, class T>
-    D * get_deleter(shared_ptr<T> const & p);
-
-

Returns: If *this owns a deleter d - of type (cv-unqualified) D, returns &d; - otherwise returns 0.

-

Throws: nothing.

-
-

Example

-

See shared_ptr_example.cpp for a - complete example program. The program builds a std::vector and std::set - of shared_ptr objects.

-

Note that after the containers have been populated, some of the shared_ptr - objects will have a use count of 1 rather than a use count of 2, since the set - is a std::set rather than a std::multiset, and thus does not - contain duplicate entries. Furthermore, the use count may be even higher at - various times while push_back and insert 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.

-

Handle/Body Idiom

-

One common usage of shared_ptr is to implement a handle/body (also called - pimpl) idiom which avoids exposing the body (implementation) in the header - file.

-

The shared_ptr_example2_test.cpp - sample program includes a header file, shared_ptr_example2.hpp, - which uses a shared_ptr to an incomplete type to hide the - implementation. The instantiation of member functions which require a complete - type occurs in the shared_ptr_example2.cpp - implementation file. Note that there is no need for an explicit destructor. - Unlike ~scoped_ptr, ~shared_ptr does not require that T be a complete - type.

-

Thread Safety

-

shared_ptr objects offer the same level of thread safety as - built-in types. A shared_ptr instance can be "read" (accessed - using only const operations) simultaneously by multiple threads. Different shared_ptr - instances can be "written to" (accessed using mutable operations such as operator= - or reset) simultaneously by multiple threads (even - when these instances are copies, and share the same reference count - underneath.)

-

Any other simultaneous accesses result in undefined behavior.

-

Examples:

-
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
-
-

 

-

Starting with Boost release 1.33.0, shared_ptr uses a lock-free - implementation on most common platforms.

-

If your program is single-threaded and does not link to any libraries that might - have used shared_ptr in its default configuration, you can - #define the macro BOOST_SP_DISABLE_THREADS on a - project-wide basis to switch to ordinary non-atomic reference count updates.

-

(Defining BOOST_SP_DISABLE_THREADS in some, but not all, - translation units is technically a violation of the One Definition Rule and - undefined behavior. Nevertheless, the implementation attempts to do its best to - accommodate the request to use non-atomic updates in those translation units. - No guarantees, though.)

-

You can define the macro BOOST_SP_USE_PTHREADS to turn off the - lock-free platform-specific implementation and fall back to the generic - pthread_mutex_t-based code.

-

Frequently Asked Questions

-

Q. 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?

-

- A. An important goal of shared_ptr 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.) -

-

Q. Why doesn't shared_ptr have template parameters supplying - traits or policies to allow extensive user customization?

-

- A. Parameterization discourages users. The shared_ptr 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, shared_ptr is the smart - pointer of choice for a wide range of applications. (Those interested in policy - based smart pointers should read - Modern C++ Design by Andrei Alexandrescu.) -

-

Q. I am not convinced. Default parameters can be used where appropriate - to hide the complexity. Again, why not policies?

-

- A. Template parameters affect the type. See the answer to the first - question above. -

-

Q. Why doesn't shared_ptr use a linked list implementation?

-

- A. A linked list implementation does not offer enough advantages to - offset the added cost of an extra pointer. See timings - page. In addition, it is expensive to make a linked list implementation thread - safe. -

-

Q. Why doesn't shared_ptr (or any of the other Boost smart - pointers) supply an automatic conversion to T*?

-

- A. Automatic conversion is believed to be too error prone. -

-

Q. Why does shared_ptr supply use_count()?

-

- A. 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. -

-

Q. Why doesn't shared_ptr specify complexity requirements?

-

- A. Because complexity requirements limit implementors and complicate the - specification without apparent benefit to shared_ptr users. For example, - error-checking implementations might become non-conforming if they had to meet - stringent complexity requirements. -

-

Q. Why doesn't shared_ptr provide a release() function?

-

- A. shared_ptr cannot give away ownership unless it's unique() - because the other copy will still destroy the object.

-

Consider:

-
shared_ptr<int> a(new int);
-shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
-
-int * p = a.release();
-
-// Who owns p now? b will still call delete on it in its destructor.
-
-

Furthermore, the pointer returned by release() would be difficult - to deallocate reliably, as the source shared_ptr could have been created - with a custom deleter. -

-

Q. Why is operator->() const, but its return value is a - non-const pointer to the element type?

-

- A. Shallow copy pointers, including raw pointers, typically don't - propagate constness. It makes little sense for them to do so, as you can always - obtain a non-const pointer from a const one and then proceed to modify the - object through it. shared_ptr is "as close to raw pointers as possible - but no closer". -

-
-

$Date$

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005, 2012, 2013 Peter Dimov. Distributed under the Boost Software License, - Version 1.0. See accompanying file LICENSE_1_0.txt - or copy at http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/smart_ptr.htm b/smart_ptr.htm deleted file mode 100644 index 0388cc7..0000000 --- a/smart_ptr.htm +++ /dev/null @@ -1,224 +0,0 @@ - - - - Smart Pointers - - - -

boost.png (6897 bytes)Smart Pointers

-

Introduction
- Common Requirements
- Exception Safety
- Exception-specifications
- History and Acknowledgements
- References

-

Introduction

-

Smart pointers are objects which store pointers to dynamically allocated (heap) - objects. They behave much like built-in C++ pointers except that they - automatically delete the object pointed to at the appropriate time. Smart - pointers are particularly useful in the face of exceptions as they ensure - proper destruction of dynamically allocated objects. They can also be used to - keep track of dynamically allocated objects shared by multiple owners.

-

Conceptually, smart pointers are seen as owning the object pointed to, and thus - responsible for deletion of the object when it is no longer needed.

-

The smart pointer library provides six smart pointer class templates:

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
scoped_ptr<boost/scoped_ptr.hpp>Simple sole ownership of single objects. Noncopyable.
scoped_array<boost/scoped_array.hpp>Simple sole ownership of arrays. Noncopyable.
shared_ptr<boost/shared_ptr.hpp>Object ownership shared among multiple pointers.
shared_array<boost/shared_array.hpp>Array ownership shared among multiple pointers.
weak_ptr<boost/weak_ptr.hpp>Non-owning observers of an object owned by shared_ptr.
intrusive_ptr<boost/intrusive_ptr.hpp>Shared ownership of objects with an embedded reference count.
-
-

These templates are designed to complement the std::auto_ptr template.

-

They are examples of the "resource acquisition is initialization" idiom - described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition, - Section 14.4, Resource Management.

-

Additionally, the smart pointer library provides efficient factory functions - for creating smart pointer objects:

-
- - - - - - - - - - - - - - - - -
make_shared, allocate_shared for objects<boost/make_shared.hpp>Efficient creation of shared_ptr objects.
make_shared, allocate_shared for arrays<boost/make_shared.hpp>Efficient creation of shared_ptr arrays.
make_unique<boost/make_unique.hpp>Creation of unique_ptr objects and arrays.
-
-

A test program, smart_ptr_test.cpp, is - provided to verify correct operation.

-

A page on compatibility with older versions of - the Boost smart pointer library describes some of the changes since earlier - versions of the smart pointer implementation.

-

A page on smart pointer timings will be of interest - to those curious about performance issues.

-

A page on smart pointer programming techniques lists - some advanced applications of shared_ptr and weak_ptr.

-

Common Requirements

-

These smart pointer class templates have a template parameter, T, which - specifies the type of the object pointed to by the smart pointer. The behavior - of the smart pointer templates is undefined if the destructor or operator delete - for objects of type T throw exceptions.

-

T may be an incomplete type at the point of smart pointer declaration. - Unless otherwise specified, it is required that T 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 the description of the - checked_delete function template.

-

Note that shared_ptr does not have this restriction, as most of - its member functions do not require T to be a complete type.

-

Rationale

-

The requirements on T are carefully crafted to maximize safety yet allow - handle-body (also called pimpl) and similar idioms. In these idioms a smart - pointer may appear in translation units where T is an incomplete type. - This separates interface from implementation and hides implementation from - translation units which merely use the interface. Examples described in the - documentation for specific smart pointers illustrate use of smart pointers in - these idioms.

-

Note that scoped_ptr requires that T be a complete type at - destruction time, but shared_ptr does not.

-

Exception Safety

-

Several functions in these smart pointer classes are specified as having "no - effect" or "no effect except such-and-such" if an exception is thrown. This - means that when an exception is thrown by an object of one of these classes, - the entire program state remains the same as it was prior to the function call - which resulted in the exception being thrown. This amounts to a guarantee that - there are no detectable side effects. Other functions never throw exceptions. - The only exception ever thrown by functions which do throw (assuming T meets - the common requirements) is std::bad_alloc, - and that is thrown only by functions which are explicitly documented as - possibly throwing std::bad_alloc.

-

Exception-specifications

-

Exception-specifications are not used; see - exception-specification rationale.

-

All the smart pointer templates contain member functions which can never throw - exceptions, because they neither throw exceptions themselves nor call other - functions which may throw exceptions. These members are indicated by a comment: - // never throws. -

-

Functions which destroy objects of the pointed to type are prohibited from - throwing exceptions by the common requirements.

-

History and Acknowledgements

-

February 2017. Glen Fernandes rewrote allocate_shared - and make_shared for arrays for a more optimal and more - maintainable implementation.

-

February 2014. Glen Fernandes updated overloads of make_shared and - allocate_shared to conform to the specification in C++ standard paper - [D&F-14], and implemented make_unique for - arrays and objects. Peter Dimov and Glen Fernandes updated the scalar and - array implementations, respectively, to resolve C++ standard library defect - 2070.

-

November 2012. Glen Fernandes provided implementations of make_shared - and allocate_shared for arrays. They achieve a single allocation for an - array that can be initialized with constructor arguments or initializer lists - as well as overloads for default initialization and no value initialization. - See the make_shared and allocate_shared for - arrays page for more information.

-

January 2002. Peter Dimov reworked all four classes, adding features, fixing - bugs, and splitting them into four separate headers, and added weak_ptr. - See the compatibility page for a summary of the - changes.

-

May 2001. Vladimir Prus suggested requiring a complete type on destruction. - Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman - Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and - others.

-

November 1999. Darin Adler provided operator ==, operator !=, and std::swap - and std::less specializations for shared types.

-

September 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap

-

May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a - number of suggestions resulting in numerous improvements.

-

October 1998. Beman Dawes proposed reviving the original semantics under the - names safe_ptr and counted_ptr, meeting of Per Andersson, Matt - Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar Kühl, - Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new - class names were finalized, it was decided that there was no need to exactly - follow the std::auto_ptr interface, and various function signatures and - semantics were finalized.

-

Over the next three months, several implementations were considered for shared_ptr, - and discussed on the boost.org mailing list. - The implementation questions revolved around the reference count which must be - kept, either attached to the pointed to object, or detached elsewhere. Each of - those variants have themselves two major variants: -

    -
  • - Direct detached: the shared_ptr contains a pointer to the object, and a pointer - to the count. -
  • - Indirect detached: the shared_ptr contains a pointer to a helper object, which - in turn contains a pointer to the object and the count. -
  • - Embedded attached: the count is a member of the object pointed to. -
  • - Placement attached: the count is attached via operator new manipulations.
  • -
-

Each implementation technique has advantages and disadvantages. We went so far - as to run various timings of the direct and indirect approaches, and found that - at least on Intel Pentium chips there was very little measurable difference. - Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar - Kühl suggested an elegant partial template specialization technique to allow - users to choose which implementation they preferred, and that was also - experimented with.

-

But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage - users", and in the end we choose to supply only the direct implementation.

-

Summer, 1994. Greg Colvin proposed to the C++ Standards Committee classes named auto_ptr - and counted_ptr which were very similar to what we now call scoped_ptr - and shared_ptr. [Col-94] In one of the very few - cases where the Library Working Group's recommendations were not followed by - the full committee, counted_ptr was rejected and surprising - transfer-of-ownership semantics were added to auto_ptr.

-

References

-

[D&F-14] Peter Dimov & Glen Fernandes, - Extending make_shared to Support Arrays, Revision 1, C++ committee document N3870, - January, 2014.

-

[Col-94] Gregory Colvin, - Exception Safe Smart Pointers, C++ committee document 94-168/N0555, - July, 1994.

-

[E&D-94] John R. Ellis & David L. Detlefs, - Safe, Efficient Garbage Collection for C++, Usenix Proceedings, - February, 1994. This paper includes an extensive discussion of weak pointers - and an extensive bibliography.

-
-

$Date$

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Distributed under the Boost Software License, Version 1.0. See accompanying - file LICENSE_1_0.txt or copy at - http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/smarttest.zip b/smarttest.zip deleted file mode 100644 index 2464b1046d1f8bdb59c05843bb0e04b8e26ec56b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11513 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 ISZRZJ0Kbrpg8%>k diff --git a/smarttests.htm b/smarttests.htm deleted file mode 100644 index 2551ae4..0000000 --- a/smarttests.htm +++ /dev/null @@ -1,542 +0,0 @@ - - - - - -Smart Pointer Timings - - - - - -

boost.png (6897 bytes)Smart Pointer Timings

- -

In late January 2000, Mark Borgerding put forward a suggestion to boost for - a new design of smart pointer whereby an intrusive doubly linked list is used - to join together all instances of smart pointers sharing a given raw pointer. - This allowed avoidance of the costly heap allocation of a reference count that - occurred in the initial construction of the then current version of boost::shared_ptr. - Of course, nothing is for free and the benefit here was gained at the expense - of increased size and more costly copy operations. A debate ensued on the boost - mailing list and the tests which this page describes were performed to provide - a guide for current and future investigations into smart pointer implementation - strategies.

-

Thanks are due to Dave Abrahams, -Gavin Collings, -Greg Colvin and -Beman Dawes - for test code and trial implementations, the final version of which can be found - in .zip format here.

-

Description

-

Two tests were run: the first aimed to obtain timings for two basic individual - operations:

-
    -
  1. Initial construction from raw pointer.
  2. -
  3. An amortized copy operation consisting of half an assignment and half a - copy construction - designed to reflect average usage.
  4. -
-

The second attempted to gain more insight into normal usage by timing the fill - and sort algorithms for vectors and lists filled with the various smart pointers.

-

Five smart pointer implementation strategies were tested:

-
    -
  1. Counted pointer using a heap allocated reference count, this is referred - to as simple counted.
  2. -
  3. Counted pointer using a special purpose allocator for the reference count - - special counted.
  4. -
  5. Counted pointer using an intrusive reference count - intrusive.
  6. -
  7. Linked pointer as described above - linked.
  8. -
  9. Cyclic pointer, a counted implementation using a std::deque for allocation - with provision for weak pointers and garbage collection of cycles of pointers - - cyclic.
  10. -
-

on two compilers:

-
    -
  1. MSVC 6.0 service pack 3, using default release optimization mode (/O2 - - optimized for speed, no inlining of functions defined outside a class body - unless specified as inline).
  2. -
  3. gcc 2.95.2 using full optimization (-O3 -DNDEBUG).
  4. -
-

Additionally, generated pointer sizes (taking into account struct alignment) - were compared, as were generated code sizes for MSVC mainly by manual inspection - of generated assembly code - a necessity due to function inlining.

-

All tests were run on a PII-200 running Windows NT version 4.0

-

 

-

Operation Timing Test Results

-

The following graphs show the overall time in nanoseconds to acquire a pointer - (default construction) perform n amortized copy operations on it and finally - release it. The initial allocation time for the contained pointer is not included, - although the time for it's deallocation is. The contained pointer pointed to - a trivial class, but for the inclusion of an intrusive reference count for the - benefit of the intrusive counted shared pointer. A dumb pointer (i.e. a smart - pointer that simply acquires and releases its contained pointer with no extra - overhead) and a raw pointer were also included for comparison.

- - - - - - - - - - - - - - - - - - - - - - - - - - -
   
  MSVC speed graph 
   
 GCC speed graph 
   
-

 

-

Fitting straight lines to the above plots gives the following figures for initialization - and amortized copy operation for the two compilers (times in nanoseconds, errors - at two standard deviations) : -

-

 

-

MSVC

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
initialization
-
copy operation
-
simple counted
-
3000 +/- 170104 +/- 31
-
special counted
-
1330 +/- 5085 +/- 9
-
intrusive
-
1000 +/- 2071 +/- 3
linked970 +/- 60136 +/- 10
cyclic1290 +/- 70112 +/- 12
dumb1020 +/- 2010 +/- 4
-
raw
-
1038 +/- 3010 +/- 5
-

 

-

GCC

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
initialization
-
copy operation
-
simple counted
-
4620 +/- 150301 +/- 28
-
special counted
-
1990 +/- 40264 +/- 7
-
intrusive
-
1590 +/- 70181 +/- 12
linked1470 +/- 140345 +/- 26
cyclic2180 +/- 100330 +/- 18
dumb1590 +/- 7074 +/- 12
-
raw
-
1430 +/- 6027 +/- 11
-

Note that the above times include a certain amount of loop overhead etc. for - each operation. An estimate of the pure smart pointer operation time 'overhead' - can be obtained by subtracting the dumb or raw figure from the smart pointer - time of interest.

-

Detail

-

The test involved iterating a loop which creates raw pointers. These were then - shared among a varying number (set size) of smart pointers. A range of set sizes - was used and then a line fitted to get a linear relation with number of initializations - and copy-operations. A spreadsheet was used for the line fit, and to produce - the performance graphs above.

-

 

-

Container Test Results

-

To gain some insight in to operation within real life programs, this test was - devised. Smart pointers were used to fill standard containers which were then - sorted.

-

In this case, the contained pointer pointed to a class which initializes a - private data member to a random value in its default constructor. This value - is used subsequently for the sort comparison test. The class also contains an - intrusive reference count for the benefit of the intrusive counted pointer.

-

All times are in seconds for 300,000 contained pointers.

-

GCC

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 vectorlist
-
-
-
fill
-
sortfillsort
-
simple counted
-
46.542.4447.093.22
-
special counted
-
14.022.837.283.21
-
intrusive
-
12.151.917.993.08
linked12.462.328.143.27
cyclic22.603.191.633.18
-
raw
-
11.810.2427.510.77
-

 

-

MSVC

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 vectorlist
-
-
-
fill
-
sortfillsort
-
simple counted
-
1.832.371.864.85
-
special counted
-
1.042.351.384.58
-
intrusive
-
1.041.841.164.29
linked1.082.001.214.33
cyclic1.382.841.474.73
-
raw
-
0.670.281.241.81
-

 

-

Code Size

-

The following code sizes were determined by inspection of generated code for - MSVC only. Sizes are given in the form N / M / I where:

-
    -
  • N is the instruction count of the operation
  • -
  • M is the size of the code in bytes
  • -
  • I determines whether generated code was inlined or not I = inline, O = "outline"
  • -
-

 

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
ptr()
-
ptr(p)ptr(ptr)op=() -
~ptr()
-
-
simple counted
-
38/110/O38/110/O9/23/I22/57/I17/40/I
-
special counted
-
50/141/O50/141/O9/23/I23/64/I13/38/I
-
intrusive
-
1/2/I3/6/I3/6/I6/11/I6/11/I
-
linked
-
5/19/I5/15/I10/30/I27/59/I14/38/I
-

During the code inspection, a couple of minor points were noticed: -

-
    -
  • Function inlining was critical to performance.
  • -
  • For MSVC, at least, a "delete 0" caused execution of 11 assembly - instructions, including a function call. So in cases where performance is - at an absolute premium it can be worth inserting the extra manual test.
  • -
-

 

-

Data Size

-

The following smart pointer sizes were obtained in bytes

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
MSVC
-
-
GCC
-
-
simple counted
-
-
8
-
-
8
-
-
special counted
-
-
8
-
-
12
-
-
intrusive
-
-
4
-
-
4
-
-
linked
-
-
12
-
-
12
-
-
cyclic
-
-
8
-
-
8
-
-

 

-

Summary

-

The timing results mainly speak for themselves: clearly an intrusive pointer - outperforms all others and a simple heap based counted pointer has poor performance - relative to other implementations. The selection of an optimal non-intrusive - smart pointer implementation is more application dependent, however. Where small - numbers of copies are expected, it is likely that the linked implementation - will be favoured. Conversely, for larger numbers of copies a counted pointer - with some type of special purpose allocator looks like a win. Other factors - to bear in mind are: -

-
    -
  • Deterministic individual, as opposed to amortized, operation time. This - weighs against any implementation depending on an allocator.
  • -
  • Multithreaded synchronization. This weighs against an implementation which - spreads its information as in the case of linked pointer.
  • -
-
-

$Date$

-

© Copyright Gavin Collings 2000. 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.

- - diff --git a/sp_techniques.html b/sp_techniques.html deleted file mode 100644 index 7e0ce8f..0000000 --- a/sp_techniques.html +++ /dev/null @@ -1,765 +0,0 @@ - - - - Smart Pointer Programming Techniques - - - -

boost.png (6897 bytes)Smart Pointer Programming Techniques

-

Using incomplete classes for implementation hiding
- The "Pimpl" idiom
- Using abstract classes for implementation hiding
- Preventing delete px.get()
- Using a shared_ptr to hold a pointer to an array
- Encapsulating allocation details, wrapping factory - functions
- Using a shared_ptr to hold a pointer to a statically - allocated object
- Using a shared_ptr to hold a pointer to a COM object
- Using a shared_ptr to hold a pointer to an object - with an embedded reference count
- Using a shared_ptr to hold another shared - ownership smart pointer
- Obtaining a shared_ptr from a raw pointer
- Obtaining a shared_ptr (weak_ptr) - to this in a constructor
- Obtaining a shared_ptr to this
- Using shared_ptr as a smart counted handle
- Using shared_ptr to execute code on block - exit
- Using shared_ptr<void> to hold an arbitrary - object
- Associating arbitrary data with heterogeneous shared_ptr - instances
- Using shared_ptr as a CopyConstructible mutex lock
- Using shared_ptr to wrap member function calls
- Delayed deallocation
- Weak pointers to objects not managed by a shared_ptr
-

-

Using incomplete classes for implementation hiding

-

A proven technique (that works in C, too) for separating interface from - implementation is to use a pointer to an incomplete class as an opaque handle:

-
class FILE;
-
-FILE * fopen(char const * name, char const * mode);
-void fread(FILE * f, void * data, size_t size);
-void fclose(FILE * f);
-
-

It is possible to express the above interface using shared_ptr, - eliminating the need to manually call fclose:

-
class FILE;
-
-shared_ptr<FILE> fopen(char const * name, char const * mode);
-void fread(shared_ptr<FILE> f, void * data, size_t size);
-
-

This technique relies on shared_ptr's ability to execute a custom - deleter, eliminating the explicit call to fclose, and on the fact - that shared_ptr<X> can be copied and destroyed when X - is incomplete.

-

The "Pimpl" idiom

-

A C++ specific variation of the incomplete class pattern is the "Pimpl" idiom. - The incomplete class is not exposed to the user; it is hidden behind a - forwarding facade. shared_ptr can be used to implement a "Pimpl":

-
// file.hpp:
-
-class file
-{
-private:
-
-    class impl;
-    shared_ptr<impl> pimpl_;
-
-public:
-
-    file(char const * name, char const * mode);
-
-    // compiler generated members are fine and useful
-
-    void read(void * data, size_t size);
-};
-
-
// file.cpp:
-
-#include "file.hpp"
-
-class file::impl
-{
-private:
-
-    impl(impl const &);
-    impl & operator=(impl const &);
-
-    // private data
-
-public:
-
-    impl(char const * name, char const * mode) { ... }
-    ~impl() { ... }
-    void read(void * data, size_t size) { ... }
-};
-
-file::file(char const * name, char const * mode): pimpl_(new impl(name, mode))
-{
-}
-
-void file::read(void * data, size_t size)
-{
-    pimpl_->read(data, size);
-}
-
-

The key thing to note here is that the compiler-generated copy constructor, - assignment operator, and destructor all have a sensible meaning. As a result, - file is CopyConstructible and Assignable, - allowing its use in standard containers.

-

Using abstract classes for implementation hiding

-

Another widely used C++ idiom for separating inteface and implementation is to - use abstract base classes and factory functions. The abstract classes are - sometimes called "interfaces" and the pattern is known as "interface-based - programming". Again, shared_ptr can be used as the return type of - the factory functions:

-
// X.hpp:
-
-class X
-{
-public:
-
-    virtual void f() = 0;
-    virtual void g() = 0;
-
-protected:
-
-    ~X() {}
-};
-
-shared_ptr<X> createX();
-
-
-- X.cpp:
-
-class X_impl: public X
-{
-private:
-
-    X_impl(X_impl const &);
-    X_impl & operator=(X_impl const &);
-
-public:
-
-    virtual void f()
-    {
-      // ...
-    }
-
-    virtual void g()
-    {
-      // ...
-    }
-};
-
-shared_ptr<X> createX()
-{
-    shared_ptr<X> px(new X_impl);
-    return px;
-}
-
-

A key property of shared_ptr is that the allocation, construction, deallocation, - and destruction details are captured at the point of construction, inside the - factory function. Note the protected and nonvirtual destructor in the example - above. The client code cannot, and does not need to, delete a pointer to X; - the shared_ptr<X> instance returned from createX - will correctly call ~X_impl.

-

Preventing delete px.get()

-

It is often desirable to prevent client code from deleting a pointer that is - being managed by shared_ptr. The previous technique showed one - possible approach, using a protected destructor. Another alternative is to use - a private deleter:

-
class X
-{
-private:
-
-    ~X();
-
-    class deleter;
-    friend class deleter;
-
-    class deleter
-    {
-    public:
-
-        void operator()(X * p) { delete p; }
-    };
-
-public:
-
-    static shared_ptr<X> create()
-    {
-        shared_ptr<X> px(new X, X::deleter());
-        return px;
-    }
-};
-
-

Using a shared_ptr to hold a pointer to an array

-

A shared_ptr can be used to hold a pointer to an array allocated - with new[]:

-
shared_ptr<X> px(new X[1], checked_array_deleter<X>());
-
-

Note, however, that shared_array is - often preferable, if this is an option. It has an array-specific interface, - without operator* and operator->, and does not - allow pointer conversions.

-

Encapsulating allocation details, wrapping factory - functions

-

shared_ptr can be used in creating C++ wrappers over existing C - style library interfaces that return raw pointers from their factory functions - to encapsulate allocation details. As an example, consider this interface, - where CreateX might allocate X from its own private - heap, ~X may be inaccessible, or X may be incomplete:

-
X * CreateX();
-void DestroyX(X *);
-
-

The only way to reliably destroy a pointer returned by CreateX is - to call DestroyX.

-

Here is how a shared_ptr-based wrapper may look like:

-
shared_ptr<X> createX()
-{
-    shared_ptr<X> px(CreateX(), DestroyX);
-    return px;
-}
-
-

Client code that calls createX still does not need to know how the - object has been allocated, but now the destruction is automatic.

-

Using a shared_ptr to hold a pointer to a statically - allocated object

-

Sometimes it is desirable to create a shared_ptr to an already - existing object, so that the shared_ptr does not attempt to - destroy the object when there are no more references left. As an example, the - factory function:

-
shared_ptr<X> createX();
-
-

in certain situations may need to return a pointer to a statically allocated X - instance.

-

The solution is to use a custom deleter that does nothing:

-
struct null_deleter
-{
-    void operator()(void const *) const
-    {
-    }
-};
-
-static X x;
-
-shared_ptr<X> createX()
-{
-    shared_ptr<X> px(&x, null_deleter());
-    return px;
-}
-
-

The same technique works for any object known to outlive the pointer.

-

Using a shared_ptr to hold a pointer to a COM Object

-

Background: COM objects have an embedded reference count and two member - functions that manipulate it. AddRef() increments the count. Release() - decrements the count and destroys itself when the count drops to zero.

-

It is possible to hold a pointer to a COM object in a shared_ptr:

-
shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
-{
-    p->AddRef();
-    shared_ptr<IWhatever> pw(p, mem_fn(&IWhatever::Release));
-    return pw;
-}
-
-

Note, however, that shared_ptr copies created from pw will - not "register" in the embedded count of the COM object; they will share the - single reference created in make_shared_from_COM. Weak pointers - created from pw will be invalidated when the last shared_ptr - is destroyed, regardless of whether the COM object itself is still alive.

-

As explained in the mem_fn documentation, - you need to #define - BOOST_MEM_FN_ENABLE_STDCALL first.

-

Using a shared_ptr to hold a pointer to an object - with an embedded reference count

-

This is a generalization of the above technique. The example assumes that the - object implements the two functions required by intrusive_ptr, - intrusive_ptr_add_ref and intrusive_ptr_release:

-
template<class T> struct intrusive_deleter
-{
-    void operator()(T * p)
-    {
-        if(p) intrusive_ptr_release(p);
-    }
-};
-
-shared_ptr<X> make_shared_from_intrusive(X * p)
-{
-    if(p) intrusive_ptr_add_ref(p);
-    shared_ptr<X> px(p, intrusive_deleter<X>());
-    return px;
-}
-
-

Using a shared_ptr to hold another shared - ownership smart pointer

-

One of the design goals of shared_ptr is to be used in library - interfaces. It is possible to encounter a situation where a library takes a shared_ptr - argument, but the object at hand is being managed by a different reference - counted or linked smart pointer.

-

It is possible to exploit shared_ptr's custom deleter feature to - wrap this existing smart pointer behind a shared_ptr facade:

-
template<class P> struct smart_pointer_deleter
-{
-private:
-
-    P p_;
-
-public:
-
-    smart_pointer_deleter(P const & p): p_(p)
-    {
-    }
-
-    void operator()(void const *)
-    {
-        p_.reset();
-    }
-    
-    P const & get() const
-    {
-        return p_;
-    }
-};
-
-shared_ptr<X> make_shared_from_another(another_ptr<X> qx)
-{
-    shared_ptr<X> px(qx.get(), smart_pointer_deleter< another_ptr<X> >(qx));
-    return px;
-}
-
-

One subtle point is that deleters are not allowed to throw exceptions, and the - above example as written assumes that p_.reset() doesn't throw. If - this is not the case, p_.reset() should be wrapped in a try {} - catch(...) {} block that ignores exceptions. In the (usually - unlikely) event when an exception is thrown and ignored, p_ will - be released when the lifetime of the deleter ends. This happens when all - references, including weak pointers, are destroyed or reset.

-

Another twist is that it is possible, given the above shared_ptr instance, - to recover the original smart pointer, using - get_deleter:

-
void extract_another_from_shared(shared_ptr<X> px)
-{
-    typedef smart_pointer_deleter< another_ptr<X> > deleter;
-
-    if(deleter const * pd = get_deleter<deleter>(px))
-    {
-        another_ptr<X> qx = pd->get();
-    }
-    else
-    {
-        // not one of ours
-    }
-}
-
-

Obtaining a shared_ptr from a raw pointer

-

Sometimes it is necessary to obtain a shared_ptr given a raw - pointer to an object that is already managed by another shared_ptr - instance. Example:

-
void f(X * p)
-{
-    shared_ptr<X> px(???);
-}
-
-

Inside f, we'd like to create a shared_ptr to *p.

-

In the general case, this problem has no solution. One approach is to modify f - to take a shared_ptr, if possible:

-
void f(shared_ptr<X> px);
-
-

The same transformation can be used for nonvirtual member functions, to convert - the implicit this:

-
void X::f(int m);
-
-

would become a free function with a shared_ptr first argument:

-
void f(shared_ptr<X> this_, int m);
-
-

If f cannot be changed, but X uses intrusive counting, - use make_shared_from_intrusive described - above. Or, if it's known that the shared_ptr created in f - will never outlive the object, use a null deleter.

-

Obtaining a shared_ptr (weak_ptr) - to this in a constructor

-

Some designs require objects to register themselves on construction with a - central authority. When the registration routines take a shared_ptr, this leads - to the question how could a constructor obtain a shared_ptr to this:

-
class X
-{
-public:
-
-    X()
-    {
-        shared_ptr<X> this_(???);
-    }
-};
-
-

In the general case, the problem cannot be solved. The X instance - being constructed can be an automatic variable or a static variable; it can be - created on the heap:

-
shared_ptr<X> px(new X);
-

but at construction time, px does not exist yet, and it is - impossible to create another shared_ptr instance that shares - ownership with it.

-

Depending on context, if the inner shared_ptr this_ doesn't - need to keep the object alive, use a null_deleter as explained - here and here. If X is - supposed to always live on the heap, and be managed by a shared_ptr, - use a static factory function:

-
class X
-{
-private:
-
-    X() { ... }
-
-public:
-
-    static shared_ptr<X> create()
-    {
-        shared_ptr<X> px(new X);
-        // use px as 'this_'
-        return px;
-    }
-};
-
-

Obtaining a shared_ptr to this

-

Sometimes it is needed to obtain a shared_ptr from this - in a virtual member function under the assumption that this is - already managed by a shared_ptr. The transformations - described in the previous technique cannot be applied.

-

A typical example:

-
class X
-{
-public:
-
-    virtual void f() = 0;
-
-protected:
-
-    ~X() {}
-};
-
-class Y
-{
-public:
-
-    virtual shared_ptr<X> getX() = 0;
-
-protected:
-
-    ~Y() {}
-};
-
-// --
-
-class impl: public X, public Y
-{
-public:
-
-    impl() { ... }
-
-    virtual void f() { ... }
-
-    virtual shared_ptr<X> getX()
-    {
-        shared_ptr<X> px(???);
-        return px;
-    }
-};
-
-

The solution is to keep a weak pointer to this as a member in impl:

-
class impl: public X, public Y
-{
-private:
-
-    weak_ptr<impl> weak_this;
-
-    impl(impl const &);
-    impl & operator=(impl const &);
-
-    impl() { ... }
-
-public:
-
-    static shared_ptr<impl> create()
-    {
-        shared_ptr<impl> pi(new impl);
-        pi->weak_this = pi;
-        return pi;
-    }
-
-    virtual void f() { ... }
-
-    virtual shared_ptr<X> getX()
-    {
-        shared_ptr<X> px(weak_this);
-        return px;
-    }
-};
-
-

The library now includes a helper class template - enable_shared_from_this that can be used to encapsulate the - solution:

-
class impl: public X, public Y, public enable_shared_from_this<impl>
-{
-public:
-
-    impl(impl const &);
-    impl & operator=(impl const &);
-
-public:
-
-    virtual void f() { ... }
-
-    virtual shared_ptr<X> getX()
-    {
-        return shared_from_this();
-    }
-}
-
-

Note that you no longer need to manually initialize the weak_ptr member - in enable_shared_from_this. - Constructing a shared_ptr to impl takes care of that.

-

Using shared_ptr as a smart counted handle

-

Some library interfaces use opaque handles, a variation of the - incomplete class technique described above. An example:

-
typedef void * HANDLE;
-HANDLE CreateProcess();
-void CloseHandle(HANDLE);
-
-

Instead of a raw pointer, it is possible to use shared_ptr as the - handle and get reference counting and automatic resource management for free:

-
typedef shared_ptr<void> handle;
-
-handle createProcess()
-{
-    shared_ptr<void> pv(CreateProcess(), CloseHandle);
-    return pv;
-}
-
-

Using shared_ptr to execute code on block exit

-

shared_ptr<void> can automatically execute cleanup code when - control leaves a scope.

-
    -
  • - Executing f(p), where p is a pointer:
-
    shared_ptr<void> guard(p, f);
-
-
    -
  • - Executing arbitrary code: f(x, y):
-
    shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
-
-

For a more thorough treatment, see the article "Simplify Your Exception-Safe - Code" by Andrei Alexandrescu and Petru Marginean, available online at - http://www.cuj.com/experts/1812/alexandr.htm?topic=experts.

-

Using shared_ptr<void> to hold an arbitrary - object

-

shared_ptr<void> can act as a generic object pointer similar - to void*. When a shared_ptr<void> instance - constructed as:

-
    shared_ptr<void> pv(new X);
-
-

is destroyed, it will correctly dispose of the X object by - executing ~X.

-

This propery can be used in much the same manner as a raw void* is - used to temporarily strip type information from an object pointer. A shared_ptr<void> - can later be cast back to the correct type by using - static_pointer_cast.

-

Associating arbitrary data with heterogeneous shared_ptr - instances

-

shared_ptr and weak_ptr support operator< - comparisons required by standard associative containers such as std::map. - This can be used to non-intrusively associate arbitrary data with objects - managed by shared_ptr:

-
typedef int Data;
-
-std::map< shared_ptr<void>, Data > userData;
-// or std::map< weak_ptr<void>, Data > userData; to not affect the lifetime
-
-shared_ptr<X> px(new X);
-shared_ptr<int> pi(new int(3));
-
-userData[px] = 42;
-userData[pi] = 91;
-
-

Using shared_ptr as a CopyConstructible mutex lock

-

Sometimes it's necessary to return a mutex lock from a function, and a - noncopyable lock cannot be returned by value. It is possible to use shared_ptr - as a mutex lock:

-
class mutex
-{
-public:
-
-    void lock();
-    void unlock();
-};
-
-shared_ptr<mutex> lock(mutex & m)
-{
-    m.lock();
-    return shared_ptr<mutex>(&m, mem_fn(&mutex::unlock));
-}
-
-

Better yet, the shared_ptr instance acting as a lock can be - encapsulated in a dedicated shared_lock class:

-
class shared_lock
-{
-private:
-
-    shared_ptr<void> pv;
-
-public:
-
-    template<class Mutex> explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&Mutex::unlock)) {}
-};
-
-

shared_lock can now be used as:

-
    shared_lock lock(m);
-
-

Note that shared_lock is not templated on the mutex type, thanks to - shared_ptr<void>'s ability to hide type information.

-

Using shared_ptr to wrap member function calls

-

shared_ptr implements the ownership semantics required from the Wrap/CallProxy - scheme described in Bjarne Stroustrup's article "Wrapping C++ Member Function - Calls" (available online at http://www.stroustrup.com/wrapper.pdf). - An implementation is given below:

-
template<class T> class pointer
-{
-private:
-
-    T * p_;
-
-public:
-
-    explicit pointer(T * p): p_(p)
-    {
-    }
-
-    shared_ptr<T> operator->() const
-    {
-        p_->prefix();
-        return shared_ptr<T>(p_, mem_fn(&T::suffix));
-    }
-};
-
-class X
-{
-private:
-
-    void prefix();
-    void suffix();
-    friend class pointer<X>;
-    
-public:
-
-    void f();
-    void g();
-};
-
-int main()
-{
-    X x;
-
-    pointer<X> px(&x);
-
-    px->f();
-    px->g();
-}
-
-

Delayed deallocation

-

In some situations, a single px.reset() can trigger an expensive - deallocation in a performance-critical region:

-
class X; // ~X is expensive
-
-class Y
-{
-    shared_ptr<X> px;
-
-public:
-
-    void f()
-    {
-        px.reset();
-    }
-};
-
-

The solution is to postpone the potential deallocation by moving px - to a dedicated free list that can be periodically emptied when performance and - response times are not an issue:

-
vector< shared_ptr<void> > free_list;
-
-class Y
-{
-    shared_ptr<X> px;
-
-public:
-
-    void f()
-    {
-        free_list.push_back(px);
-        px.reset();
-    }
-};
-
-// periodically invoke free_list.clear() when convenient
-
-

Another variation is to move the free list logic to the construction point by - using a delayed deleter:

-
struct delayed_deleter
-{
-    template<class T> void operator()(T * p)
-    {
-        try
-        {
-            shared_ptr<void> pv(p);
-            free_list.push_back(pv);
-        }
-        catch(...)
-        {
-        }
-    }
-};
-
-

Weak pointers to objects not managed by a shared_ptr

-

Make the object hold a shared_ptr to itself, using a null_deleter:

-
class X
-{
-private:
-
-    shared_ptr<X> this_;
-    int i_;
-
-public:
-
-    explicit X(int i): this_(this, null_deleter()), i_(i)
-    {
-    }
-
-    // repeat in all constructors (including the copy constructor!)
-
-    X(X const & rhs): this_(this, null_deleter()), i_(rhs.i_)
-    {
-    }
-
-    // do not forget to not assign this_ in the copy assignment
-
-    X & operator=(X const & rhs)
-    {
-        i_ = rhs.i_;
-    }
-
-    weak_ptr<X> get_weak_ptr() const { return this_; }
-};
-
-

When the object's lifetime ends, X::this_ will be destroyed, and - all weak pointers will automatically expire.

-
-

$Date$

-

Copyright © 2003 Peter Dimov. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/weak_ptr.htm b/weak_ptr.htm deleted file mode 100644 index 4c256b8..0000000 --- a/weak_ptr.htm +++ /dev/null @@ -1,240 +0,0 @@ - - - - weak_ptr - - - -

boost.png (6897 bytes)weak_ptr class template

-

Introduction
- Synopsis
- Members
- Free Functions
- Frequently Asked Questions -

-

Introduction

-

The weak_ptr class template stores a "weak reference" to an object that's - already managed by a shared_ptr. To access the object, a weak_ptr - can be converted to a shared_ptr using - the shared_ptr constructor or the member function - lock. When the last shared_ptr to the object goes - away and the object is deleted, the attempt to obtain a shared_ptr - from the weak_ptr instances that refer to the deleted object will fail: - the constructor will throw an exception of type boost::bad_weak_ptr, - and weak_ptr::lock will return an empty shared_ptr.

-

Every weak_ptr meets the CopyConstructible and Assignable requirements - of the C++ Standard Library, and so can be used in standard library containers. - Comparison operators are supplied so that weak_ptr works with the - standard library's associative containers.

-

weak_ptr operations never throw exceptions.

-

The class template is parameterized on T, the type of the object pointed - to.

-

Compared to shared_ptr, weak_ptr provides a - very limited subset of operations since accessing its stored pointer is often - dangerous in multithreaded programs, and sometimes unsafe even within a single - thread (that is, it may invoke undefined behavior.) Pretend for a moment that weak_ptr - has a get member function that returns a raw pointer, and consider this - innocent piece of code:

-
shared_ptr<int> p(new int(5));
-weak_ptr<int> q(p);
-
-// some time later
-
-if(int * r = q.get())
-{
-    // use *r
-}
-
-

Imagine that after the if, but immediately before r - is used, another thread executes the statement p.reset(). Now r - is a dangling pointer.

-

The solution to this problem is to create a temporary shared_ptr - from q:

-
shared_ptr<int> p(new int(5));
-weak_ptr<int> q(p);
-
-// some time later
-
-if(shared_ptr<int> r = q.lock())
-{
-    // use *r
-}
-
-

Now r holds a reference to the object that was pointed by q. - Even if p.reset() is executed in another thread, the object will - stay alive until r goes out of scope or is reset. By obtaining - a shared_ptr to the object, we have effectively locked it - against destruction.

-

Synopsis

-
namespace boost {
-
-  template<class T> class weak_ptr {
-
-    public:
-      typedef T element_type;
-
-      weak_ptr();
-
-      template<class Y> weak_ptr(shared_ptr<Y> const & r);
-      weak_ptr(weak_ptr const & r);
-      template<class Y> weak_ptr(weak_ptr<Y> const & r);
-
-      ~weak_ptr();
-
-      weak_ptr & operator=(weak_ptr const & r);
-      template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
-      template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);
-
-      long use_count() const;
-      bool expired() const;
-      shared_ptr<T> lock() const;
-
-      void reset();
-      void swap(weak_ptr<T> & b);
-  };
-
-  template<class T, class U>
-    bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);
-
-  template<class T>
-    void swap(weak_ptr<T> & a, weak_ptr<T> & b);
-}
-
-

Members

-

element_type

-
typedef T element_type;
-
-

Provides the type of the template parameter T.

-
-

constructors

-
weak_ptr();
-
-

Effects: Constructs an empty weak_ptr.

-

Postconditions: use_count() == 0.

-

Throws: nothing.

-
-
template<class Y> weak_ptr(shared_ptr<Y> const & r);
-weak_ptr(weak_ptr const & r);
-template<class Y> weak_ptr(weak_ptr<Y> const & r);
-
-

Effects: If r is empty, constructs an empty - weak_ptr; otherwise, constructs a weak_ptr that shares - ownership with r as if by storing a copy of the - pointer stored in r.

-

Postconditions: use_count() == r.use_count().

-

Throws: nothing.

-
-

destructor

-
~weak_ptr();
-
-

Effects: Destroys this weak_ptr but has no effect on the object - its stored pointer points to.

-

Throws: nothing.

-
-

assignment

-
weak_ptr & operator=(weak_ptr const & r);
-template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
-template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);
-
-

Effects: Equivalent to weak_ptr(r).swap(*this).

-

Throws: nothing.

-

Notes: The implementation is free to meet the effects (and the implied - guarantees) via different means, without creating a temporary.

-
-

use_count

-
long use_count() const;
-
-

Returns: 0 if *this is empty; otherwise, the - number of shared_ptr objects that share ownership with *this.

-

Throws: nothing.

-

Notes: use_count() is not necessarily efficient. Use only - for debugging and testing purposes, not for production code.

-
-

expired

-
bool expired() const;
-
-

Returns: use_count() == 0.

-

Throws: nothing.

-

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

-
-

lock

-
shared_ptr<T> lock() const;
-
-

Returns: expired()? shared_ptr<T>(): shared_ptr<T>(*this).

-

Throws: nothing.

-
-

reset

-
void reset();
-
-

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

-
-

swap

-
void swap(weak_ptr & b);
-
-

Effects: Exchanges the contents of the two smart pointers.

-

Throws: nothing.

-
-

Free Functions

-

comparison

-
template<class T, class U>
-  bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);
-
-

Returns: an unspecified value such that

-
    -
  • - operator< is a strict weak ordering as described in section 25.3 [lib.alg.sorting] - of the C++ standard; -
  • - under the equivalence relation defined by operator<, !(a - < b) && !(b < a), two weak_ptr instances - are equivalent if and only if they share ownership or are both empty.
-

Throws: nothing.

-

Notes: Allows weak_ptr objects to be used as keys in - associative containers.

-
-

swap

-
template<class T>
-  void swap(weak_ptr<T> & a, weak_ptr<T> & b)
-
-

Effects: Equivalent to a.swap(b).

-

Throws: nothing.

-

Notes: Matches the interface of std::swap. Provided as an aid to - generic programming.

-
-

Frequently Asked Questions

-

Q. Can an object create a weak_ptr to itself in its - constructor?

-

A. No. A weak_ptr can only be created from a shared_ptr, - and at object construction time no shared_ptr to the object - exists yet. Even if you could create a temporary shared_ptr to - this, it would go out of scope at the end of the constructor, and - all weak_ptr instances would instantly expire.

-

The solution is to make the constructor private, and supply a factory function - that returns a shared_ptr:
-

-
-class X
-{
-private:
-
-    X();
-
-public:
-
-    static shared_ptr<X> create()
-    {
-        shared_ptr<X> px(new X);
-        // create weak pointers from px here
-        return px;
-    }
-};
-
-
-

$Date$

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

- - From dea4e8129da97389b4fd6bb5dc8823f4e646c0a5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 12 Jun 2017 03:12:03 +0300 Subject: [PATCH 02/26] Complete scoped_ptr.adoc --- doc/smart_ptr.adoc | 5 +- doc/smart_ptr/enable_shared_from_this.adoc | 2 +- doc/smart_ptr/history.adoc | 5 +- doc/smart_ptr/introduction.adoc | 26 ++- doc/smart_ptr/intrusive_ptr.adoc | 4 +- doc/smart_ptr/intrusive_ref_counter.adoc | 2 +- doc/smart_ptr/make_shared.adoc | 4 +- doc/smart_ptr/make_unique.adoc | 4 +- doc/smart_ptr/pointer_cast.adoc | 2 +- doc/smart_ptr/pointer_to_other.adoc | 2 +- doc/smart_ptr/scoped_array.adoc | 4 +- doc/smart_ptr/scoped_ptr.adoc | 200 ++++++++++++++++++++- doc/smart_ptr/shared_array.adoc | 5 +- doc/smart_ptr/shared_ptr.adoc | 4 +- doc/smart_ptr/techniques.adoc | 5 +- doc/smart_ptr/weak_ptr.adoc | 4 +- 16 files changed, 238 insertions(+), 40 deletions(-) diff --git a/doc/smart_ptr.adoc b/doc/smart_ptr.adoc index e85479b..361b528 100644 --- a/doc/smart_ptr.adoc +++ b/doc/smart_ptr.adoc @@ -7,10 +7,10 @@ See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt //// -# Boost.SmartPtr: Smart Pointer Library +# Boost.SmartPtr: The Smart Pointer Library Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes :toc: left -:toclevels: 3 +:toclevels: 2 :idprefix: :listing-caption: Code Example :table-caption: Illustration @@ -53,6 +53,7 @@ include::smart_ptr/shared_array.adoc[] :leveloffset: -1 +[[copyright]] [appendix] ## Copyright and License diff --git a/doc/smart_ptr/enable_shared_from_this.adoc b/doc/smart_ptr/enable_shared_from_this.adoc index 5b385cb..428fc30 100644 --- a/doc/smart_ptr/enable_shared_from_this.adoc +++ b/doc/smart_ptr/enable_shared_from_this.adoc @@ -11,5 +11,5 @@ http://www.boost.org/LICENSE_1_0.txt # enable_shared_from_this :toc: :toc-title: -:idprefix: +:idprefix: enable_shared_from_this_ diff --git a/doc/smart_ptr/history.adoc b/doc/smart_ptr/history.adoc index ffdb9af..9d3c9f6 100644 --- a/doc/smart_ptr/history.adoc +++ b/doc/smart_ptr/history.adoc @@ -9,9 +9,10 @@ See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt //// -[appendix,#history] +[[history]] +[appendix] # History and Acknowledgments -:idprefix: +:idprefix: history_ ## Summer 1994 diff --git a/doc/smart_ptr/introduction.adoc b/doc/smart_ptr/introduction.adoc index dec424e..ecbef1d 100644 --- a/doc/smart_ptr/introduction.adoc +++ b/doc/smart_ptr/introduction.adoc @@ -11,9 +11,7 @@ http://www.boost.org/LICENSE_1_0.txt [#introduction] # Introduction -:toc: -:toc-title: -:idprefix: +:idprefix: intro Smart pointers are objects which store pointers to dynamically allocated (heap) objects. They behave much like built-in {cpp} pointers except that they automatically delete the object @@ -28,22 +26,22 @@ acquisition is initialization" idiom described in Bjarne Stroustrup's "The C++ P This library provides five smart pointer class templates: -* `scoped_ptr`, used to contain ownership of a dynamically allocated object to the current scope; -* `scoped_array`, which provides scoped ownership for a dynamically allocated array; -* `shared_ptr`, a versatile tool for managing shared ownership of an object or array; -* `weak_ptr`, a non-owning observer to a shared_ptr-managed object that can be promoted temporarily to shared_ptr; -* `intrusive_ptr`, a pointer to objects with an embedded reference count. +* `<>`, used to contain ownership of a dynamically allocated object to the current scope; +* `<>`, which provides scoped ownership for a dynamically allocated array; +* `<>`, a versatile tool for managing shared ownership of an object or array; +* `<>`, a non-owning observer to a shared_ptr-managed object that can be promoted temporarily to shared_ptr; +* `<>`, a pointer to objects with an embedded reference count. `shared_ptr` and `weak_ptr` are part of the {cpp} standard since its 2011 iteration. In addition, the library contains the following supporting utility functions and classes: -* `make_shared`, a factory function for creating objects that returns a `shared_ptr`; -* `make_unique`, a factory function returning `std::unique_ptr`; -* `enable_shared_from_this`, a helper base class that enables the acquisition of a `shared_ptr` pointing to `this`; -* `pointer_to_other`, a helper trait for converting one smart pointer type to another; -* `static_pointer_cast` and companions, generic smart pointer casts; -* `intrusive_ref_counter`, a helper base class containing a reference count. +* `<>`, a factory function for creating objects that returns a `shared_ptr`; +* `<>`, a factory function returning `std::unique_ptr`; +* `<>`, a helper base class that enables the acquisition of a `shared_ptr` pointing to `this`; +* `<>`, a helper trait for converting one smart pointer type to another; +* `<>` and companions, generic smart pointer casts; +* `<>`, a helper base class containing a reference count. As a general rule, the destructor or `operator delete` for an object managed by pointers in the library are not allowed to throw exceptions. diff --git a/doc/smart_ptr/intrusive_ptr.adoc b/doc/smart_ptr/intrusive_ptr.adoc index 6bf4843..c22a128 100644 --- a/doc/smart_ptr/intrusive_ptr.adoc +++ b/doc/smart_ptr/intrusive_ptr.adoc @@ -8,8 +8,8 @@ http://www.boost.org/LICENSE_1_0.txt //// [#intrusive_ptr] -# intrusive_ptr +# intrusive_ptr: Managing Objects with Embedded Counts :toc: :toc-title: -:idprefix: +:idprefix: intrusive_ptr_ diff --git a/doc/smart_ptr/intrusive_ref_counter.adoc b/doc/smart_ptr/intrusive_ref_counter.adoc index 4a9885a..61f9ed6 100644 --- a/doc/smart_ptr/intrusive_ref_counter.adoc +++ b/doc/smart_ptr/intrusive_ref_counter.adoc @@ -11,5 +11,5 @@ http://www.boost.org/LICENSE_1_0.txt # intrusive_ref_counter :toc: :toc-title: -:idprefix: +:idprefix: intrusive_ref_counter_ diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc index 2531cfe..53af79d 100644 --- a/doc/smart_ptr/make_shared.adoc +++ b/doc/smart_ptr/make_shared.adoc @@ -8,8 +8,8 @@ http://www.boost.org/LICENSE_1_0.txt //// [#make_shared] -# make_shared +# make_shared: Creating shared_ptr :toc: :toc-title: -:idprefix: +:idprefix: make_shared_ diff --git a/doc/smart_ptr/make_unique.adoc b/doc/smart_ptr/make_unique.adoc index 9cfec90..5caf392 100644 --- a/doc/smart_ptr/make_unique.adoc +++ b/doc/smart_ptr/make_unique.adoc @@ -8,8 +8,8 @@ http://www.boost.org/LICENSE_1_0.txt //// [#make_unique] -# make_unique +# make_unique: Creating unique_ptr :toc: :toc-title: -:idprefix: +:idprefix: make_unique_ diff --git a/doc/smart_ptr/pointer_cast.adoc b/doc/smart_ptr/pointer_cast.adoc index 3041eeb..cd65e4e 100644 --- a/doc/smart_ptr/pointer_cast.adoc +++ b/doc/smart_ptr/pointer_cast.adoc @@ -11,5 +11,5 @@ http://www.boost.org/LICENSE_1_0.txt # Generic Pointer Casts :toc: :toc-title: -:idprefix: +:idprefix: pointer_cast_ diff --git a/doc/smart_ptr/pointer_to_other.adoc b/doc/smart_ptr/pointer_to_other.adoc index 4c4f74d..8522622 100644 --- a/doc/smart_ptr/pointer_to_other.adoc +++ b/doc/smart_ptr/pointer_to_other.adoc @@ -11,5 +11,5 @@ http://www.boost.org/LICENSE_1_0.txt # pointer_to_other :toc: :toc-title: -:idprefix: +:idprefix: pointer_to_other_ diff --git a/doc/smart_ptr/scoped_array.adoc b/doc/smart_ptr/scoped_array.adoc index 9374caa..3fbc835 100644 --- a/doc/smart_ptr/scoped_array.adoc +++ b/doc/smart_ptr/scoped_array.adoc @@ -8,8 +8,8 @@ http://www.boost.org/LICENSE_1_0.txt //// [#scoped_array] -# scoped_array +# scoped_array: Scoped Array Ownership :toc: :toc-title: -:idprefix: +:idprefix: scoped_array_ diff --git a/doc/smart_ptr/scoped_ptr.adoc b/doc/smart_ptr/scoped_ptr.adoc index ba71827..d60df72 100644 --- a/doc/smart_ptr/scoped_ptr.adoc +++ b/doc/smart_ptr/scoped_ptr.adoc @@ -8,8 +8,204 @@ http://www.boost.org/LICENSE_1_0.txt //// [#scoped_ptr] -# scoped_ptr +# scoped_ptr: Scoped Object Ownership :toc: :toc-title: -:idprefix: +:idprefix: scoped_ptr_ +## Description + +The `scoped_ptr` class template stores a pointer to a dynamically allocated object. +(Dynamically allocated objects are allocated with the {cpp} `new` expression.) The +object pointed to is guaranteed to be deleted, either on destruction of the `scoped_ptr`, +or via an explicit `reset`. See the <>. + +`scoped_ptr` is a simple solution for simple needs. It supplies a basic "resource acquisition +is initialization" facility, without shared-ownership or transfer-of-ownership semantics. +Both its name and enforcement of semantics (by being noncopyable) signal its intent to retain +ownership solely within the current scope. Because it is noncopyable, it is safer than `shared_ptr` +for pointers which should not be copied. + +Because `scoped_ptr` is simple, in its usual implementation every operation is as fast as for a +built-in pointer and it has no more space overhead that a built-in pointer. + +`scoped_ptr` cannot be used in {cpp} Standard Library containers. Use `shared_ptr` or `std::unique_ptr` +if you need a smart pointer that can. + +`scoped_ptr` cannot correctly hold a pointer to a dynamically allocated array. See `scoped_array` for that usage. + +The class template is parameterized on `T`, the type of the object pointed to. Destroying `T` must not thow exceptions, +and `T` must be complete at the point `scoped_ptr::~scoped_ptr` is instantiated. + +## Synopsis + +`scoped_ptr` is defined in ``. + +``` +namespace boost +{ + +template class scoped_ptr +{ +private: + + scoped_ptr(scoped_ptr const&); + scoped_ptr& operator=(scoped_ptr const&); + + void operator==(scoped_ptr const&) const; + void operator!=(scoped_ptr const&) const; + +public: + + typedef T element_type; + + explicit scoped_ptr(T * p = 0) noexcept; + ~scoped_ptr() noexcept; + + void reset(T * p = 0) noexcept; + + T & operator*() const noexcept; + T * operator->() const noexcept; + T * get() const noexcept; + + explicit operator bool() const noexcept; + + void swap(scoped_ptr & b) noexcept; +}; + +template void swap(scoped_ptr & a, scoped_ptr & b) noexcept; + +} // namespace boost +``` + +## Members + +### element_type + + typedef T element_type; + +Provides the type of the stored pointer. + +### constructor + + explicit scoped_ptr(T * p = 0) noexcept; + +Constructs a `scoped_ptr`, storing a copy of `p`, which must have been allocated via a +{cpp} `new` expression or be 0. `T` is not required be a complete type. + +### destructor + + ~scoped_ptr() noexcept; + +Destroys the object pointed to by the stored pointer, if any, as if by using +`delete this\->get()`. `T` must be a complete type. + +### reset + + void reset(T * p = 0) noexcept; + +Deletes the object pointed to by the stored pointer and then stores a copy of +`p`, which must have been allocated via a {cpp} `new` expression or be 0. + +Since the previous object needs to be deleted, `T` must be a complete type. + +### indirection + + T & operator*() const noexcept; + +Returns a reference to the object pointed to by the stored pointer. Behavior is undefined if the stored pointer is 0. + + T * operator->() const noexcept; + +Returns the stored pointer. Behavior is undefined if the stored pointer is 0. + +### get + + T * get() const noexcept; + +Returns the stored pointer. `T` need not be a complete type. + +### conversions + + explicit operator bool () const noexcept; // never throws + +Returns `get() != 0`. + +### swap + + void swap(scoped_ptr & b) noexcept; + +Exchanges the contents of the two smart pointers. `T` need not be a complete type. + +## Free Functions + +### swap + + template void swap(scoped_ptr & a, scoped_ptr & b) noexcept; + +Equivalent to `a.swap(b)`. + +## Example + +Here's an example that uses `scoped_ptr`. + +``` +#include +#include + +struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } }; + +class MyClass { + boost::scoped_ptr ptr; + public: + MyClass() : ptr(new int) { *ptr = 0; } + int add_one() { return ++*ptr; } +}; + +int main() +{ + boost::scoped_ptr x(new Shoe); + MyClass my_instance; + std::cout << my_instance.add_one() << '\n'; + std::cout << my_instance.add_one() << '\n'; +} +``` + +The example program produces the beginning of a child's nursery rhyme: + +``` +1 +2 +Buckle my shoe +``` + +## Rationale + +The primary reason to use `scoped_ptr` rather than `std::auto_ptr` or `std::unique_ptr` is to let readers of your code +know that you intend "resource acquisition is initialization" to be applied only for the current scope, and have no intent to transfer ownership. + +A secondary reason to use `scoped_ptr` is to prevent a later maintenance programmer from adding a function that transfers +ownership by returning the `auto_ptr`, because the maintenance programmer saw `auto_ptr`, and assumed ownership could safely be transferred. + +Think of `bool` vs `int`. We all know that under the covers `bool` is usually just an `int`. Indeed, some argued against including bool in the {cpp} +standard because of that. But by coding `bool` rather than `int`, you tell your readers what your intent is. Same with `scoped_ptr`; by using it you are signaling intent. + +It has been suggested that `scoped_ptr` is equivalent to `std::auto_ptr const`. Ed Brey pointed out, however, that `reset` will not work on a `std::auto_ptr const`. + +## Handle/Body Idiom + +One common usage of `scoped_ptr` is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) in the header file. + +The `link:../../example/scoped_ptr_example_test.cpp[scoped_ptr_example_test.cpp]` sample program includes a header file, +`link:../../example/scoped_ptr_example.hpp[scoped_ptr_example.hpp]`, which uses a `scoped_ptr<>` to an incomplete type to hide the +implementation. The instantiation of member functions which require a complete type occurs in the `link:../../example/scoped_ptr_example.cpp[scoped_ptr_example.cpp]` +implementation file. + +## Frequently Asked Questions + +[qanda] +Why doesn't `scoped_ptr` have a `release()` member?:: + + When reading source code, it is valuable to be able to draw conclusions about program behavior based on the types being used. If `scoped_ptr` had a `release()` member, + it would become possible to transfer ownership of the held pointer, weakening its role as a way of limiting resource lifetime to a given context. Use `std::auto_ptr` where + transfer of ownership is required. (supplied by Dave Abrahams) diff --git a/doc/smart_ptr/shared_array.adoc b/doc/smart_ptr/shared_array.adoc index 564747f..aa2933f 100644 --- a/doc/smart_ptr/shared_array.adoc +++ b/doc/smart_ptr/shared_array.adoc @@ -7,9 +7,10 @@ See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt //// -[appendix,#shared_array] +[[shared_array]] +[appendix] # shared_array (deprecated) :toc: :toc-title: -:idprefix: +:idprefix: shared_array_ diff --git a/doc/smart_ptr/shared_ptr.adoc b/doc/smart_ptr/shared_ptr.adoc index 50e38a0..5a34eeb 100644 --- a/doc/smart_ptr/shared_ptr.adoc +++ b/doc/smart_ptr/shared_ptr.adoc @@ -8,8 +8,8 @@ http://www.boost.org/LICENSE_1_0.txt //// [#shared_ptr] -# shared_ptr +# shared_ptr: Shared Ownership :toc: :toc-title: -:idprefix: +:idprefix: shared_ptr_ diff --git a/doc/smart_ptr/techniques.adoc b/doc/smart_ptr/techniques.adoc index 13a9b18..5f26036 100644 --- a/doc/smart_ptr/techniques.adoc +++ b/doc/smart_ptr/techniques.adoc @@ -7,9 +7,10 @@ See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt //// -[appendix,#techniques] +[[techniques]] +[appendix] # Smart Pointer Programming Techniques :toc: :toc-title: -:idprefix: +:idprefix: techniques_ diff --git a/doc/smart_ptr/weak_ptr.adoc b/doc/smart_ptr/weak_ptr.adoc index ceb28cf..c5a740c 100644 --- a/doc/smart_ptr/weak_ptr.adoc +++ b/doc/smart_ptr/weak_ptr.adoc @@ -8,8 +8,8 @@ http://www.boost.org/LICENSE_1_0.txt //// [#weak_ptr] -# weak_ptr +# weak_ptr: Non-owning Observer :toc: :toc-title: -:idprefix: +:idprefix: weak_ptr_ From 392b3c76f0413107e24d3115a0cef631cb8c092d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 12 Jun 2017 04:06:27 +0300 Subject: [PATCH 03/26] Add techniques.adoc --- doc/smart_ptr/techniques.adoc | 754 +++++++++++++++++++++++++++++++++- 1 file changed, 753 insertions(+), 1 deletion(-) diff --git a/doc/smart_ptr/techniques.adoc b/doc/smart_ptr/techniques.adoc index 5f26036..f6da9f6 100644 --- a/doc/smart_ptr/techniques.adoc +++ b/doc/smart_ptr/techniques.adoc @@ -1,5 +1,5 @@ //// -Copyright 2017 Peter Dimov +Copyright 2003, 2017 Peter Dimov Distributed under the Boost Software License, Version 1.0. @@ -14,3 +14,755 @@ http://www.boost.org/LICENSE_1_0.txt :toc-title: :idprefix: techniques_ +[#techniques_incomplete] +## Using incomplete classes for implementation hiding + +A proven technique (that works in C, too) for separating interface from implementation is to use a pointer to an incomplete class as an opaque handle: + +``` +class FILE; + +FILE * fopen(char const * name, char const * mode); +void fread(FILE * f, void * data, size_t size); +void fclose(FILE * f); +``` + + +It is possible to express the above interface using `shared_ptr`, eliminating the need to manually call `fclose`: + +``` +class FILE; + +shared_ptr fopen(char const * name, char const * mode); +void fread(shared_ptr f, void * data, size_t size); +``` + +This technique relies on `shared_ptr`’s ability to execute a custom deleter, eliminating the explicit call to `fclose`, and on the fact that `shared_ptr` can be copied and destroyed when `X` is incomplete. + +## The "Pimpl" idiom + +A {cpp} specific variation of the incomplete class pattern is the "Pimpl" idiom. The incomplete class is not exposed to the user; it is hidden behind a forwarding facade. `shared_ptr` can be used to implement a "Pimpl": + +``` +// file.hpp: + +class file +{ +private: + + class impl; + shared_ptr pimpl_; + +public: + + file(char const * name, char const * mode); + + // compiler generated members are fine and useful + + void read(void * data, size_t size); +}; + +// file.cpp: + +#include "file.hpp" + +class file::impl +{ +private: + + impl(impl const &); + impl & operator=(impl const &); + + // private data + +public: + + impl(char const * name, char const * mode) { ... } + ~impl() { ... } + void read(void * data, size_t size) { ... } +}; + +file::file(char const * name, char const * mode): pimpl_(new impl(name, mode)) +{ +} + +void file::read(void * data, size_t size) +{ + pimpl_->read(data, size); +} +``` + +The key thing to note here is that the compiler-generated copy constructor, assignment operator, and destructor all have a sensible meaning. As a result, `file` is `CopyConstructible` and `Assignable`, allowing its use in standard containers. + +## Using abstract classes for implementation hiding + +Another widely used C++ idiom for separating inteface and implementation is to use abstract base classes and factory functions. +The abstract classes are sometimes called "interfaces" and the pattern is known as "interface-based programming". Again, +`shared_ptr` can be used as the return type of the factory functions: + +``` +// X.hpp: + +class X +{ +public: + + virtual void f() = 0; + virtual void g() = 0; + +protected: + + ~X() {} +}; + +shared_ptr createX(); + +// X.cpp: + +class X_impl: public X +{ +private: + + X_impl(X_impl const &); + X_impl & operator=(X_impl const &); + +public: + + virtual void f() + { + // ... + } + + virtual void g() + { + // ... + } +}; + +shared_ptr createX() +{ + shared_ptr px(new X_impl); + return px; +} +``` + +A key property of `shared_ptr` is that the allocation, construction, deallocation, and destruction details are captured at the point of construction, inside the factory function. + +Note the protected and nonvirtual destructor in the example above. The client code cannot, and does not need to, delete a pointer to `X`; the `shared_ptr` instance returned from `createX` will correctly call `~X_impl`. + +## Preventing `delete px.get()` + +It is often desirable to prevent client code from deleting a pointer that is being managed by `shared_ptr`. The previous technique showed one possible approach, using a protected destructor. Another alternative is to use a private deleter: + +``` +class X +{ +private: + + ~X(); + + class deleter; + friend class deleter; + + class deleter + { + public: + + void operator()(X * p) { delete p; } + }; + +public: + + static shared_ptr create() + { + shared_ptr px(new X, X::deleter()); + return px; + } +}; +``` + +## Encapsulating allocation details, wrapping factory functions + +`shared_ptr` can be used in creating {cpp} wrappers over existing C style library interfaces that return raw pointers from their factory functions +to encapsulate allocation details. As an example, consider this interface, where `CreateX` might allocate `X` from its own private heap, `~X` may +be inaccessible, or `X` may be incomplete: + + X * CreateX(); + void DestroyX(X *); + +The only way to reliably destroy a pointer returned by `CreateX` is to call `DestroyX`. + +Here is how a `shared_ptr`-based wrapper may look like: + + shared_ptr createX() + { + shared_ptr px(CreateX(), DestroyX); + return px; + } + +Client code that calls `createX` still does not need to know how the object has been allocated, but now the destruction is automatic. + +[#techniques_static] +## Using a shared_ptr to hold a pointer to a statically allocated object + +Sometimes it is desirable to create a `shared_ptr` to an already existing object, so that the `shared_ptr` does not attempt to destroy the +object when there are no more references left. As an example, the factory function: + + shared_ptr createX(); + +in certain situations may need to return a pointer to a statically allocated `X` instance. + +The solution is to use a custom deleter that does nothing: + +``` +struct null_deleter +{ + void operator()(void const *) const + { + } +}; + +static X x; + +shared_ptr createX() +{ + shared_ptr px(&x, null_deleter()); + return px; +} +``` + +The same technique works for any object known to outlive the pointer. + +## Using a shared_ptr to hold a pointer to a COM Object + +Background: COM objects have an embedded reference count and two member functions that manipulate it. `AddRef()` increments the count. +`Release()` decrements the count and destroys itself when the count drops to zero. + +It is possible to hold a pointer to a COM object in a `shared_ptr`: + + shared_ptr make_shared_from_COM(IWhatever * p) + { + p->AddRef(); + shared_ptr pw(p, mem_fn(&IWhatever::Release)); + return pw; + } + +Note, however, that `shared_ptr` copies created from `pw` will not "register" in the embedded count of the COM object; +they will share the single reference created in `make_shared_from_COM`. Weak pointers created from `pw` will be invalidated when the last +`shared_ptr` is destroyed, regardless of whether the COM object itself is still alive. + +As link:../../libs/bind/mem_fn.html#Q3[explained] in the `mem_fn` documentation, you need to `#define BOOST_MEM_FN_ENABLE_STDCALL` first. + +[#techniques_intrusive] +## Using a shared_ptr to hold a pointer to an object with an embedded reference count + +This is a generalization of the above technique. The example assumes that the object implements the two functions required by `<>`, +`intrusive_ptr_add_ref` and `intrusive_ptr_release`: + +``` +template struct intrusive_deleter +{ + void operator()(T * p) + { + if(p) intrusive_ptr_release(p); + } +}; + +shared_ptr make_shared_from_intrusive(X * p) +{ + if(p) intrusive_ptr_add_ref(p); + shared_ptr px(p, intrusive_deleter()); + return px; +} +``` + +## Using a shared_ptr to hold another shared ownership smart pointer + +One of the design goals of `shared_ptr` is to be used in library interfaces. It is possible to encounter a situation where a library takes a +`shared_ptr` argument, but the object at hand is being managed by a different reference counted or linked smart pointer. + +It is possible to exploit `shared_ptr`’s custom deleter feature to wrap this existing smart pointer behind a `shared_ptr` facade: + +``` +template struct smart_pointer_deleter +{ +private: + + P p_; + +public: + + smart_pointer_deleter(P const & p): p_(p) + { + } + + void operator()(void const *) + { + p_.reset(); + } + + P const & get() const + { + return p_; + } +}; + +shared_ptr make_shared_from_another(another_ptr qx) +{ + shared_ptr px(qx.get(), smart_pointer_deleter< another_ptr >(qx)); + return px; +} +``` + +One subtle point is that deleters are not allowed to throw exceptions, and the above example as written assumes that `p_.reset()` doesn't throw. +If this is not the case, `p_.reset();` should be wrapped in a `try {} catch(...) {}` block that ignores exceptions. In the (usually unlikely) event +when an exception is thrown and ignored, `p_` will be released when the lifetime of the deleter ends. This happens when all references, including +weak pointers, are destroyed or reset. + +Another twist is that it is possible, given the above `shared_ptr` instance, to recover the original smart pointer, using `<>`: + +``` +void extract_another_from_shared(shared_ptr px) +{ + typedef smart_pointer_deleter< another_ptr > deleter; + + if(deleter const * pd = get_deleter(px)) + { + another_ptr qx = pd->get(); + } + else + { + // not one of ours + } +} +``` + +[#techniques_from_raw] +## Obtaining a shared_ptr from a raw pointer + +Sometimes it is necessary to obtain a `shared_ptr` given a raw pointer to an object that is already managed by another `shared_ptr` instance. Example: + + void f(X * p) + { + shared_ptr px(???); + } + +Inside `f`, we'd like to create a `shared_ptr` to `*p`. + +In the general case, this problem has no solution. One approach is to modify `f` to take a `shared_ptr`, if possible: + + void f(shared_ptr px); + +The same transformation can be used for nonvirtual member functions, to convert the implicit `this`: + + void X::f(int m); + +would become a free function with a `shared_ptr` first argument: + + void f(shared_ptr this_, int m); + +If `f` cannot be changed, but `X` uses intrusive counting, use `<>` described above. Or, if it's known that the `shared_ptr` created in `f` will never outlive the object, use <>. + +## Obtaining a shared_ptr (weak_ptr) to this in a constructor + +Some designs require objects to register themselves on construction with a central authority. When the registration routines take a `shared_ptr`, this leads to the question how could a constructor obtain a `shared_ptr` to `this`: + +``` +class X +{ +public: + + X() + { + shared_ptr this_(???); + } +}; +``` + +In the general case, the problem cannot be solved. The `X` instance being constructed can be an automatic variable or a static variable; it can be created on the heap: + + shared_ptr px(new X); + +but at construction time, `px` does not exist yet, and it is impossible to create another `shared_ptr` instance that shares ownership with it. + +Depending on context, if the inner `shared_ptr this_` doesn't need to keep the object alive, use a `null_deleter` as explained <> and <>. +If `X` is supposed to always live on the heap, and be managed by a `shared_ptr`, use a static factory function: + +``` +class X +{ +private: + + X() { ... } + +public: + + static shared_ptr create() + { + shared_ptr px(new X); + // use px as 'this_' + return px; + } +}; +``` + +## Obtaining a shared_ptr to this + +Sometimes it is needed to obtain a `shared_ptr` from `this` in a virtual member function under the assumption that `this` is already managed by a `shared_ptr`. +The transformations <> cannot be applied. + +A typical example: + +``` +class X +{ +public: + + virtual void f() = 0; + +protected: + + ~X() {} +}; + +class Y +{ +public: + + virtual shared_ptr getX() = 0; + +protected: + + ~Y() {} +}; + +// -- + +class impl: public X, public Y +{ +public: + + impl() { ... } + + virtual void f() { ... } + + virtual shared_ptr getX() + { + shared_ptr px(???); + return px; + } +}; +``` + +The solution is to keep a weak pointer to `this` as a member in `impl`: + +``` +class impl: public X, public Y +{ +private: + + weak_ptr weak_this; + + impl(impl const &); + impl & operator=(impl const &); + + impl() { ... } + +public: + + static shared_ptr create() + { + shared_ptr pi(new impl); + pi->weak_this = pi; + return pi; + } + + virtual void f() { ... } + + virtual shared_ptr getX() + { + shared_ptr px(weak_this); + return px; + } +}; +``` + +The library now includes a helper class template `<>` that can be used to encapsulate the solution: + +``` +class impl: public X, public Y, public enable_shared_from_this +{ +public: + + impl(impl const &); + impl & operator=(impl const &); + +public: + + virtual void f() { ... } + + virtual shared_ptr getX() + { + return shared_from_this(); + } +} +``` + +Note that you no longer need to manually initialize the `weak_ptr` member in `enable_shared_from_this`. Constructing a `shared_ptr` to `impl` takes care of that. + +## Using shared_ptr as a smart counted handle + +Some library interfaces use opaque handles, a variation of the <> described above. An example: + +``` +typedef void * HANDLE; + +HANDLE CreateProcess(); +void CloseHandle(HANDLE); +``` + +Instead of a raw pointer, it is possible to use `shared_ptr` as the handle and get reference counting and automatic resource management for free: + +``` +typedef shared_ptr handle; + +handle createProcess() +{ + shared_ptr pv(CreateProcess(), CloseHandle); + return pv; +} +``` + +## Using shared_ptr to execute code on block exit + +`shared_ptr` can automatically execute cleanup code when control leaves a scope. + +* Executing `f(p)`, where `p` is a pointer: ++ +``` +shared_ptr guard(p, f); +``` + +* Executing arbitrary code: `f(x, y)`: ++ +``` +shared_ptr guard(static_cast(0), bind(f, x, y)); +``` + +## Using shared_ptr to hold an arbitrary object + +`shared_ptr` can act as a generic object pointer similar to `void*`. When a `shared_ptr` instance constructed as: + + shared_ptr pv(new X); + +is destroyed, it will correctly dispose of the `X` object by executing `~X`. + +This propery can be used in much the same manner as a raw `void*` is used to temporarily strip type information from an object pointer. +A `shared_ptr` can later be cast back to the correct type by using `<>`. + +## Associating arbitrary data with heterogeneous `shared_ptr` instances + +`shared_ptr` and `weak_ptr` support `operator<` comparisons required by standard associative containers such as `std::map`. This can be +used to non-intrusively associate arbitrary data with objects managed by `shared_ptr`: + +``` +typedef int Data; + +std::map, Data> userData; +// or std::map, Data> userData; to not affect the lifetime + +shared_ptr px(new X); +shared_ptr pi(new int(3)); + +userData[px] = 42; +userData[pi] = 91; +``` + +## Using `shared_ptr` as a `CopyConstructible` mutex lock + +Sometimes it's necessary to return a mutex lock from a function, and a noncopyable lock cannot be returned by value. It is possible to use `shared_ptr` as a mutex lock: + +``` +class mutex +{ +public: + + void lock(); + void unlock(); +}; + +shared_ptr lock(mutex & m) +{ + m.lock(); + return shared_ptr(&m, mem_fn(&mutex::unlock)); +} +``` + +Better yet, the `shared_ptr` instance acting as a lock can be encapsulated in a dedicated `shared_lock` class: + +``` +class shared_lock +{ +private: + + shared_ptr pv; + +public: + + template explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&Mutex::unlock)) {} +}; +``` + +`shared_lock` can now be used as: + + shared_lock lock(m); + +Note that `shared_lock` is not templated on the mutex type, thanks to `shared_ptr`’s ability to hide type information. + +## Using shared_ptr to wrap member function calls + +`shared_ptr` implements the ownership semantics required from the `Wrap/CallProxy` scheme described in Bjarne Stroustrup's article +"Wrapping C++ Member Function Calls" (available online at http://www.stroustrup.com/wrapper.pdf). An implementation is given below: + +``` +template class pointer +{ +private: + + T * p_; + +public: + + explicit pointer(T * p): p_(p) + { + } + + shared_ptr operator->() const + { + p_->prefix(); + return shared_ptr(p_, mem_fn(&T::suffix)); + } +}; + +class X +{ +private: + + void prefix(); + void suffix(); + friend class pointer; + +public: + + void f(); + void g(); +}; + +int main() +{ + X x; + + pointer px(&x); + + px->f(); + px->g(); +} +``` + +## Delayed deallocation + +In some situations, a single `px.reset()` can trigger an expensive deallocation in a performance-critical region: + +``` +class X; // ~X is expensive + +class Y +{ + shared_ptr px; + +public: + + void f() + { + px.reset(); + } +}; +``` + +The solution is to postpone the potential deallocation by moving `px` to a dedicated free list that can be periodically emptied when performance and response times are not an issue: + +``` +vector< shared_ptr > free_list; + +class Y +{ + shared_ptr px; + +public: + + void f() + { + free_list.push_back(px); + px.reset(); + } +}; + +// periodically invoke free_list.clear() when convenient +``` + +Another variation is to move the free list logic to the construction point by using a delayed deleter: + +``` +struct delayed_deleter +{ + template void operator()(T * p) + { + try + { + shared_ptr pv(p); + free_list.push_back(pv); + } + catch(...) + { + } + } +}; +``` + +[#techniques_weak_without_shared] +## Weak pointers to objects not managed by a shared_ptr + +Make the object hold a `shared_ptr` to itself, using a `null_deleter`: + +``` +class X +{ +private: + + shared_ptr this_; + int i_; + +public: + + explicit X(int i): this_(this, null_deleter()), i_(i) + { + } + + // repeat in all constructors (including the copy constructor!) + + X(X const & rhs): this_(this, null_deleter()), i_(rhs.i_) + { + } + + // do not forget to not assign this_ in the copy assignment + + X & operator=(X const & rhs) + { + i_ = rhs.i_; + } + + weak_ptr get_weak_ptr() const { return this_; } +}; +``` + +When the object's lifetime ends, `X::this_` will be destroyed, and all weak pointers will automatically expire. From 3b16e1cc3e268a43330700891051510ba0ab5306 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 12 Jun 2017 05:17:34 +0300 Subject: [PATCH 04/26] Add intrusive_ptr.adoc --- doc/smart_ptr/intrusive_ptr.adoc | 434 ++++++++++++++++++++++++++++++- 1 file changed, 433 insertions(+), 1 deletion(-) diff --git a/doc/smart_ptr/intrusive_ptr.adoc b/doc/smart_ptr/intrusive_ptr.adoc index c22a128..3dd7047 100644 --- a/doc/smart_ptr/intrusive_ptr.adoc +++ b/doc/smart_ptr/intrusive_ptr.adoc @@ -1,5 +1,5 @@ //// -Copyright 2017 Peter Dimov +Copyright 2003-2005, 2013, 2017 Peter Dimov Distributed under the Boost Software License, Version 1.0. @@ -13,3 +13,435 @@ http://www.boost.org/LICENSE_1_0.txt :toc-title: :idprefix: intrusive_ptr_ +## Introduction + +The `intrusive_ptr` class template stores a pointer to an object with an embedded reference count. +Every new `intrusive_ptr` instance increments the reference count by using an unqualified call to the +function `intrusive_ptr_add_ref`, passing it the pointer as an argument. Similarly, when an `intrusive_ptr` +is destroyed, it calls `intrusive_ptr_release`; this function is responsible for destroying the object when +its reference count drops to zero. The user is expected to provide suitable definitions of these two functions. +On compilers that support argument-dependent lookup, `intrusive_ptr_add_ref` and `intrusive_ptr_release` should +be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in namespace +`boost`. The library provides a helper base class template `<>` which +may help adding support for `intrusive_ptr` to user types. + +The class template is parameterized on `T`, the type of the object pointed to. `intrusive_ptr` can be implicitly +converted to `intrusive_ptr` whenever `T*` can be implicitly converted to `U*`. + +The main reasons to use `intrusive_ptr` are: + +* Some existing frameworks or OSes provide objects with embedded reference counts; +* The memory footprint of `intrusive_ptr` is the same as the corresponding raw pointer; +* `intrusive_ptr` can be constructed from an arbitrary raw pointer of type `T*`. + +As a general rule, if it isn't obvious whether `intrusive_ptr` better fits your needs than `shared_ptr`, try a `shared_ptr`-based design first. + +## Synopsis + +``` +namespace boost +{ + +template class intrusive_ptr +{ +public: + + typedef T element_type; + + intrusive_ptr() noexcept; + intrusive_ptr(T * p, bool add_ref = true); + + intrusive_ptr(intrusive_ptr const & r); + template intrusive_ptr(intrusive_ptr const & r); + + ~intrusive_ptr(); + + intrusive_ptr & operator=(intrusive_ptr const & r); + template intrusive_ptr & operator=(intrusive_ptr const & r); + intrusive_ptr & operator=(T * r); + + void reset(); + void reset(T * r); + void reset(T * r, bool add_ref); + + T & operator*() const noexcept; + T * operator->() const noexcept; + T * get() const noexcept; + T * detach() noexcept; + + operator unspecified-bool-type() const noexcept; + + void swap(intrusive_ptr & b) noexept; +}; + +template +bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; + +template +bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; + +template +bool operator==(intrusive_ptr const & a, U * b) noexcept; + +template +bool operator!=(intrusive_ptr const & a, U * b) noexcept; + +template +bool operator==(T * a, intrusive_ptr const & b) noexcept; + +template +bool operator!=(T * a, intrusive_ptr const & b) noexcept; + +template +bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; + +template void swap(intrusive_ptr & a, intrusive_ptr & b) noexcept; + +template T * get_pointer(intrusive_ptr const & p) noexcept; + +template +intrusive_ptr static_pointer_cast(intrusive_ptr const & r) noexcept; + +template +intrusive_ptr const_pointer_cast(intrusive_ptr const & r) noexcept; + +template +intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & r) noexcept; + +template +std::basic_ostream & operator<< (std::basic_ostream & os, + intrusive_ptr const & p); + +} // namespace boost +``` + +## Members + +### element_type + +``` +typedef T element_type; +``` + +Provides the type of the template parameter T. + +### constructors + +``` +intrusive_ptr() noexcept; +``` + +[none] +* {blank} ++ +Postconditions:: `get() == 0`. + +``` +intrusive_ptr(T * p, bool add_ref = true); +``` + +[none] +* {blank} ++ +Effects:: `if(p != 0 && add_ref) intrusive_ptr_add_ref(p);`. +Postconditions:: `get() == p`. + +``` +intrusive_ptr(intrusive_ptr const & r); +``` +``` +template intrusive_ptr(intrusive_ptr const & r); +``` + +[none] +* {blank} ++ +Effects:: `if(r.get() != 0) intrusive_ptr_add_ref(r.get());`. +Postconditions:: `get() == r.get()`. + +### destructor + +``` +~intrusive_ptr(); +``` + +[none] +* {blank} ++ +Effects:: `if(get() != 0) intrusive_ptr_release(get());`. + +### assignment + +``` +intrusive_ptr & operator=(intrusive_ptr const & r); +``` +``` +template intrusive_ptr & operator=(intrusive_ptr const & r); +``` +``` +intrusive_ptr & operator=(T * r); +``` + +[none] +* {blank} ++ +Effects:: Equivalent to `intrusive_ptr(r).swap(*this)`. +Returns:: `*this`. + +### reset + +``` +void reset(); +``` + +[none] +* {blank} ++ +Effects:: Equivalent to `intrusive_ptr().swap(*this)`. + +``` +void reset(T * r); +``` + +[none] +* {blank} ++ +Effects:: Equivalent to `intrusive_ptr(r).swap(*this)`. + +``` +void reset(T * r, bool add_ref); +``` + +[none] +* {blank} ++ +Effects:: Equivalent to `intrusive_ptr(r, add_ref).swap(*this)`. + +### indirection + +``` +T & operator*() const noexcept; +``` + +[none] +* {blank} ++ +Requirements:: `get() != 0`. +Returns:: `*get()`. + +``` +T * operator->() const noexcept; +``` + +[none] +* {blank} ++ +Requirements:: `get() != 0`. +Returns:: `get()`. + +### get + +``` +T * get() const noexcept; +``` + +[none] +* {blank} ++ +Returns:: the stored pointer. + +### detach + +``` +T * detach() noexcept; +``` + +[none] +* {blank} ++ +Returns:: the stored pointer. +Postconditions:: `get() == 0`. + +NOTE: The returned pointer has an elevated reference count. This allows conversion of an `intrusive_ptr` +back to a raw pointer, without the performance overhead of acquiring and dropping an extra reference. +It can be viewed as the complement of the non-reference-incrementing constructor. + +CAUTION: Using `detach` escapes the safety of automatic reference counting provided by `intrusive_ptr`. +It should by used only where strictly necessary (such as when interfacing to an existing API), and when +the implications are thoroughly understood. + +### conversions + +``` +operator unspecified-bool-type () const noexcept; +``` + +[none] +* {blank} ++ +Returns:: an unspecified value that, when used in boolean contexts, is equivalent to `get() != 0`. + +NOTE: This conversion operator allows `intrusive_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, +avoiding many of the implicit conversion pitfalls. + +### swap + +``` +void swap(intrusive_ptr & b) noexcept; +``` + +[none] +* {blank} ++ +Effects:: Exchanges the contents of the two smart pointers. + +## Free Functions + +### comparison + +``` +template +bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `a.get() == b.get()`. + +``` +template +bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `a.get() != b.get()`. + +``` +template +bool operator==(intrusive_ptr const & a, U * b) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `a.get() == b`. + +``` +template +bool operator!=(intrusive_ptr const & a, U * b) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `a.get() != b`. + +``` +template +bool operator==(T * a, intrusive_ptr const & b) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `a == b.get()`. + +``` +template +bool operator!=(T * a, intrusive_ptr const & b) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `a != b.get()`. + +``` +template +bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `std::less()(a.get(), b.get())`. + +NOTE: Allows `intrusive_ptr` objects to be used as keys in associative containers. + +### swap + +``` +template void swap(intrusive_ptr & a, intrusive_ptr & b) noexcept; +``` + +[none] +* {blank} ++ +Effects:: Equivalent to `a.swap(b)`. + +### get_pointer + +``` +template T * get_pointer(intrusive_ptr const & p) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `p.get()`. + +NOTE: Provided as an aid to generic programming. Used by `mem_fn`. + +### static_pointer_cast + +``` +template +intrusive_ptr static_pointer_cast(intrusive_ptr const & r) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `intrusive_ptr(static_cast(r.get()))`. + +### const_pointer_cast + +``` +template +intrusive_ptr const_pointer_cast(intrusive_ptr const & r) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `intrusive_ptr(const_cast(r.get()))`. + +### dynamic_pointer_cast + +``` +template +intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & r) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `intrusive_ptr(dynamic_cast(r.get()))`. + +### operator<< + +``` +template +std::basic_ostream & operator<< (std::basic_ostream & os, + intrusive_ptr const & p); +``` + +[none] +* {blank} ++ +Effects:: `os << p.get();`. +Returns:: `os`. From a6031ff8e20090df8764271427c6fe5323748592 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 12 Jun 2017 16:53:57 +0300 Subject: [PATCH 05/26] Add scoped_array.adoc --- doc/smart_ptr/scoped_array.adoc | 155 +++++++++++++++++++++++++++++++- doc/smart_ptr/scoped_ptr.adoc | 22 +++++ 2 files changed, 176 insertions(+), 1 deletion(-) diff --git a/doc/smart_ptr/scoped_array.adoc b/doc/smart_ptr/scoped_array.adoc index 3fbc835..7a755c7 100644 --- a/doc/smart_ptr/scoped_array.adoc +++ b/doc/smart_ptr/scoped_array.adoc @@ -1,5 +1,7 @@ //// -Copyright 2017 Peter Dimov +Copyright 1999 Greg Colvin and Beman Dawes +Copyright 2002 Darin Adler +Copyright 2002-2005, 2017 Peter Dimov Distributed under the Boost Software License, Version 1.0. @@ -13,3 +15,154 @@ http://www.boost.org/LICENSE_1_0.txt :toc-title: :idprefix: scoped_array_ +## Description + +The `scoped_array` class template stores a pointer to a dynamically allocated array. +(Dynamically allocated arrays are allocated with the {cpp} `new[]` expression.) The array +pointed to is guaranteed to be deleted, either on destruction of the `scoped_array`, +or via an explicit `reset`. + +The `scoped_array` template is a simple solution for simple needs. It supplies a basic +"resource acquisition is initialization" facility, without shared-ownership or +transfer-of-ownership semantics. Both its name and enforcement of semantics +(by being noncopyable) signal its intent to retain ownership solely within the current scope. +Because it is noncopyable, it is safer than `shared_ptr` for pointers which should not be copied. + +Because `scoped_array` is so simple, in its usual implementation every operation is as fast as a +built-in array pointer and it has no more space overhead that a built-in array pointer. + +It cannot be used in {cpp} standard library containers. See `shared_ptr` if `scoped_array` +does not meet your needs. + +It cannot correctly hold a pointer to a single object. See `scoped_ptr` for that usage. + +`std::vector` is an alternative to `scoped_array` that is a bit heavier duty but far more flexible. +`boost::array` is an alternative that does not use dynamic allocation. + +The class template is parameterized on `T`, the type of the object pointed to. + +## Synopsis + +``` +namespace boost +{ + +template class scoped_array +{ +private: + + scoped_array(scoped_array const &); + scoped_array & operator=(scoped_array const &); + + void operator==( scoped_array const& ) const; + void operator!=( scoped_array const& ) const; + +public: + + typedef T element_type; + + explicit scoped_array(T * p = 0) noexcept; + ~scoped_array() noexcept; + + void reset(T * p = 0) noexcept; + + T & operator[](std::ptrdiff_t i) const noexcept; + T * get() const noexcept; + + explicit operator bool () const noexcept; + + void swap(scoped_array & b) noexcept; +}; + +template void swap(scoped_array & a, scoped_array & b) noexcept; + +template bool operator==( scoped_array const & p, std::nullptr_t ) noexcept; +template bool operator==( std::nullptr_t, scoped_array const & p ) noexcept; + +template bool operator!=( scoped_array const & p, std::nullptr_t ) noexcept; +template bool operator!=( std::nullptr_t, scoped_array const & p ) noexcept; + +} // namespace boost +``` + +## Members + +### element_type + + typedef T element_type; + +Provides the type of the stored pointer. + +### constructors + + explicit scoped_array(T * p = 0) noexcept; + +Constructs a `scoped_array`, storing a copy of `p`, which must have been +allocated via a {cpp} `new[]` expression or be 0. `T` is not required be a complete type. + +### destructor + + ~scoped_array() noexcept; + +Deletes the array pointed to by the stored pointer. Note that `delete[]` on a pointer with +a value of 0 is harmless. `T` must be complete, and `delete[]` on the stored pointer must +not throw exceptions. + +### reset + + void reset(T * p = 0) noexcept; + +Deletes the array pointed to by the stored pointer and then stores a copy of `p`, +which must have been allocated via a {cpp} `new[]` expression or be 0. `T` must be complete, +and `delete[]` on the stored pointer must not throw exceptions. + +### subscripting + + T & operator[](std::ptrdiff_t i) const noexcept; + +Returns a reference to element `i` of the array pointed to by the stored pointer. +Behavior is undefined and almost certainly undesirable if the stored pointer is 0, +or if `i` is less than 0 or is greater than or equal to the number of elements in +the array. + +### get + + T * get() const noexcept; + +Returns the stored pointer. `T` need not be a complete type. + +### conversions + + explicit operator bool () const noexcept; + +Returns `get() != 0`. + +NOTE: On C++03 compilers, the return value is of an unspecified type. + +### swap + + void swap(scoped_array & b) noexcept; + +Exchanges the contents of the two smart pointers. `T` need not be a complete type. + +## Free Functions + +### swap + + template void swap(scoped_array & a, scoped_array & b) noexcept; + +Equivalent to `a.swap(b)`. + +### comparisons + + template bool operator==( scoped_array const & p, std::nullptr_t ) noexcept; + + template bool operator==( std::nullptr_t, scoped_array const & p ) noexcept; + +Returns `p.get() == nullptr`. + + template bool operator!=( scoped_array const & p, std::nullptr_t ) noexcept; + + template bool operator!=( std::nullptr_t, scoped_array const & p ) noexcept; + +Returns `p.get() != nullptr`. diff --git a/doc/smart_ptr/scoped_ptr.adoc b/doc/smart_ptr/scoped_ptr.adoc index d60df72..dcd616c 100644 --- a/doc/smart_ptr/scoped_ptr.adoc +++ b/doc/smart_ptr/scoped_ptr.adoc @@ -75,6 +75,12 @@ public: template void swap(scoped_ptr & a, scoped_ptr & b) noexcept; +template bool operator==( scoped_ptr const & p, std::nullptr_t ) noexcept; +template bool operator==( std::nullptr_t, scoped_ptr const & p ) noexcept; + +template bool operator!=( scoped_ptr const & p, std::nullptr_t ) noexcept; +template bool operator!=( std::nullptr_t, scoped_ptr const & p ) noexcept; + } // namespace boost ``` @@ -131,6 +137,8 @@ Returns the stored pointer. `T` need not be a complete type. Returns `get() != 0`. +NOTE: On C++03 compilers, the return value is of an unspecified type. + ### swap void swap(scoped_ptr & b) noexcept; @@ -145,6 +153,20 @@ Exchanges the contents of the two smart pointers. `T` need not be a complete typ Equivalent to `a.swap(b)`. +### comparisons + + template bool operator==( scoped_ptr const & p, std::nullptr_t ) noexcept; + + template bool operator==( std::nullptr_t, scoped_ptr const & p ) noexcept; + +Returns `p.get() == nullptr`. + + template bool operator!=( scoped_ptr const & p, std::nullptr_t ) noexcept; + + template bool operator!=( std::nullptr_t, scoped_ptr const & p ) noexcept; + +Returns `p.get() != nullptr`. + ## Example Here's an example that uses `scoped_ptr`. From a88d8b5b294119b3db2ee4808668d6630b0e19df Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 12 Jun 2017 18:20:54 +0300 Subject: [PATCH 06/26] Add pointer_to_other.adoc --- doc/smart_ptr/intrusive_ptr.adoc | 4 +- doc/smart_ptr/pointer_to_other.adoc | 103 +++++++++++++++++++++++++++- doc/smart_ptr/scoped_array.adoc | 2 + 3 files changed, 107 insertions(+), 2 deletions(-) diff --git a/doc/smart_ptr/intrusive_ptr.adoc b/doc/smart_ptr/intrusive_ptr.adoc index 3dd7047..392f1c3 100644 --- a/doc/smart_ptr/intrusive_ptr.adoc +++ b/doc/smart_ptr/intrusive_ptr.adoc @@ -13,7 +13,7 @@ http://www.boost.org/LICENSE_1_0.txt :toc-title: :idprefix: intrusive_ptr_ -## Introduction +## Description The `intrusive_ptr` class template stores a pointer to an object with an embedded reference count. Every new `intrusive_ptr` instance increments the reference count by using an unqualified call to the @@ -38,6 +38,8 @@ As a general rule, if it isn't obvious whether `intrusive_ptr` better fits your ## Synopsis +`intrusive_ptr` is defined in ``. + ``` namespace boost { diff --git a/doc/smart_ptr/pointer_to_other.adoc b/doc/smart_ptr/pointer_to_other.adoc index 8522622..d8c5a52 100644 --- a/doc/smart_ptr/pointer_to_other.adoc +++ b/doc/smart_ptr/pointer_to_other.adoc @@ -1,5 +1,6 @@ //// -Copyright 2017 Peter Dimov +Copyright 2005, 2006 Ion Gaztañaga +Copyright 2005, 2006, 2017 Peter Dimov Distributed under the Boost Software License, Version 1.0. @@ -13,3 +14,103 @@ http://www.boost.org/LICENSE_1_0.txt :toc-title: :idprefix: pointer_to_other_ +## Description + +The `pointer_to_other` utility provides a way, given a source pointer type, to obtain a pointer of the same type +to another pointee type. + +There is test/example code in link:../../test/pointer_to_other_test.cpp[pointer_to_other_test.cpp]. + +## Rationale + +When building pointer independent classes, like memory managers, allocators, or containers, there is often a need to +define pointers generically, so that if a template parameter represents a pointer (for example, a raw or smart pointer +to an `int`), we can define another pointer of the same type to another pointee (a raw or smart pointer to a `float`.) + +``` +template class FloatPointerHolder +{ + // Let's define a pointer to a float + + typedef typename boost::pointer_to_other + ::type float_ptr_t; + + float_ptr_t float_ptr; +}; +``` + +## Synopsis + +`pointer_to_other` is defined in ``. + +``` +namespace boost +{ + +template struct pointer_to_other; + +template class Sp> + struct pointer_to_other< Sp, U > +{ + typedef Sp type; +}; + +template class Sp> + struct pointer_to_other< Sp, U > +{ + typedef Sp type; +}; + +template class Sp> + struct pointer_to_other< Sp, U > +{ + typedef Sp type; +}; + +template + struct pointer_to_other< T*, U > +{ + typedef U* type; +}; + +} // namespace boost +``` + +If these definitions are not correct for a specific smart pointer, we can define a specialization of `pointer_to_other`. + +## Example + +``` +// Let's define a memory allocator that can +// work with raw and smart pointers + +#include + +template +class memory_allocator +{ + // Predefine a memory_block + + struct block; + + // Define a pointer to a memory_block from a void pointer + // If VoidPtr is void *, block_ptr_t is block* + // If VoidPtr is smart_ptr, block_ptr_t is smart_ptr + + typedef typename boost::pointer_to_other + ::type block_ptr_t; + + struct block + { + std::size_t size; + block_ptr_t next_block; + }; + + block_ptr_t free_blocks; +}; +``` + +As we can see, using `pointer_to_other` we can create pointer independent code. diff --git a/doc/smart_ptr/scoped_array.adoc b/doc/smart_ptr/scoped_array.adoc index 7a755c7..74aa96e 100644 --- a/doc/smart_ptr/scoped_array.adoc +++ b/doc/smart_ptr/scoped_array.adoc @@ -43,6 +43,8 @@ The class template is parameterized on `T`, the type of the object pointed to. ## Synopsis +`scoped_array` is defined in ``. + ``` namespace boost { From bd2474e7f3d8ef96f2ecd230306e47f894136208 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 12 Jun 2017 20:06:12 +0300 Subject: [PATCH 07/26] Add shared_ptr.adoc --- doc/smart_ptr/shared_ptr.adoc | 922 +++++++++++++++++++++++++++++++++- 1 file changed, 921 insertions(+), 1 deletion(-) diff --git a/doc/smart_ptr/shared_ptr.adoc b/doc/smart_ptr/shared_ptr.adoc index 5a34eeb..8208c90 100644 --- a/doc/smart_ptr/shared_ptr.adoc +++ b/doc/smart_ptr/shared_ptr.adoc @@ -1,5 +1,7 @@ //// -Copyright 2017 Peter Dimov +Copyright 1999 Greg Colvin and Beman Dawes +Copyright 2002 Darin Adler +Copyright 2002-2017 Peter Dimov Distributed under the Boost Software License, Version 1.0. @@ -13,3 +15,921 @@ http://www.boost.org/LICENSE_1_0.txt :toc-title: :idprefix: shared_ptr_ +## Description + +The `shared_ptr` class template stores a pointer to a dynamically allocated object, typically with a {cpp} `new`-expression. +The object pointed to is guaranteed to be deleted when the last `shared_ptr` pointing to it is destroyed or reset. + +.Using shared_ptr +``` +shared_ptr p1( new X ); +shared_ptr p2( new int(5) ); +``` + +`shared_ptr` deletes the exact pointer that has been passed at construction time, complete with its original type, regardless +of the template parameter. In the second example above, when `p2` is destroyed or reset, it will call `delete` on the original +`int*` that has been passed to the constructor, even though `p2` itself is of type `shared_ptr` and stores a pointer of +type `void*`. + +Every `shared_ptr` meets the `CopyConstructible`, `MoveConstructible`, `CopyAssignable` and `MoveAssignable` requirements of the +{cpp} Standard Library, and can be used in standard library containers. Comparison operators are supplied so that `shared_ptr` +works with the standard library's associative containers. + +Because the implementation uses reference counting, cycles of `shared_ptr` instances will not be reclaimed. 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. Use `<>` to "break cycles." + +The class template is parameterized on `T`, the type of the object pointed 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` can be implicitly converted to `shared_ptr` whenever `T*` can be implicitly converted to `U*`. In particular, +`shared_ptr` is implicitly convertible to `shared_ptr`, to `shared_ptr` where `U` is an accessible base of `T`, +and to `shared_ptr`. + +`shared_ptr` is now part of the C++11 Standard, as `std::shared_ptr`. + +Starting with Boost release 1.53, `shared_ptr` can be used to hold a pointer to a dynamically allocated array. This is accomplished +by using an array type (`T[]` or `T[N]`) as the template parameter. There is almost no difference between using an unsized array, +`T[]`, and a sized array, `T[N]`; the latter just enables `operator[]` to perform a range check on the index. + +.Using shared_ptr with arrays +``` +shared_ptr p1( new double[1024] ); +shared_ptr p2( new double[n] ); +``` + +## Best Practices + +A simple guideline that nearly eliminates the possibility of memory leaks is: always use a named smart pointer variable to hold the result +of `new`. Every occurence of the `new` keyword in the code should have the form: + + shared_ptr p(new Y); + +It is, of course, acceptable to use another smart pointer in place of `shared_ptr` above; having `T` and `Y` be the same type, or passing +arguments to the constructor of `Y` is also OK. + +If you observe this guideline, it naturally follows that you will have no explicit `delete` statements; `try`/`catch` constructs will be rare. + +Avoid using unnamed `shared_ptr` temporaries to save typing; to see why this is dangerous, consider this example: + +.Exception-safe and -unsafe use of shared_ptr +``` +void f(shared_ptr, int); +int g(); + +void ok() +{ + shared_ptr p( new int(2) ); + f( p, g() ); +} + +void bad() +{ + f( shared_ptr( new int(2) ), g() ); +} +``` + +The function `ok` follows the guideline to the letter, whereas `bad` constructs the temporary `shared_ptr` in place, admitting the possibility of +a memory leak. Since function arguments are evaluated in unspecified order, it is possible for `new int(2)` to be evaluated first, `g()` second, +and we may never get to the `shared_ptr` constructor if `g` throws an exception. See http://www.gotw.ca/gotw/056.htm[Herb Sutter's treatment] of +the issue for more information. + +The exception safety problem described above may also be eliminated by using the `<>` or `allocate_shared` factory +functions defined in ``. These factory functions also provide an efficiency benefit by consolidating allocations. + +## Synopsis + +`shared_ptr` is defined in ``. + +``` +namespace boost +{ + +class bad_weak_ptr: public std::exception; + +template class weak_ptr; + +template class shared_ptr +{ +public: + + typedef /*see below*/ element_type; + + shared_ptr() noexcept; + shared_ptr(std::nullptr_t) noexcept; + + template explicit shared_ptr(Y * p); + template shared_ptr(Y * p, D d); + template shared_ptr(Y * p, D d, A a); + template shared_ptr(std::nullptr_t p, D d); + template shared_ptr(std::nullptr_t p, D d, A a); + + ~shared_ptr() noexcept; + + shared_ptr(shared_ptr const & r) noexcept; + template shared_ptr(shared_ptr const & r) noexcept; + + shared_ptr(shared_ptr && r) noexcept; + template shared_ptr(shared_ptr && r) noexcept; + + template shared_ptr(shared_ptr const & r, element_type * p) noexcept; + + template shared_ptr(shared_ptr && r, element_type * p) noexcept; + + template explicit shared_ptr(weak_ptr const & r); + + template explicit shared_ptr(std::auto_ptr & r); + template shared_ptr(std::auto_ptr && r); + + template shared_ptr(std::unique_ptr && r); + + shared_ptr & operator=(shared_ptr const & r) noexcept; + template shared_ptr & operator=(shared_ptr const & r) noexcept; + + shared_ptr & operator=(shared_ptr const && r) noexcept; + template shared_ptr & operator=(shared_ptr const && r) noexcept; + + template shared_ptr & operator=(std::auto_ptr & r); + template shared_ptr & operator=(std::auto_ptr && r); + + template shared_ptr & operator=(std::unique_ptr && r); + + shared_ptr & operator=(std::nullptr_t) noexcept; + + void reset() noexcept; + + template void reset(Y * p); + template void reset(Y * p, D d); + template void reset(Y * p, D d, A a); + + template void reset(shared_ptr const & r, element_type * p) noexcept; + + T & operator*() const noexcept; // only valid when T is not an array type + T * operator->() const noexcept; // only valid when T is not an array type + + // only valid when T is an array type + element_type & operator[](std::ptrdiff_t i) const noexcept; + + element_type * get() const noexcept; + + bool unique() const noexcept; + long use_count() const noexcept; + + explicit operator bool() const noexcept; + + void swap(shared_ptr & b) noexcept; + + template bool owner_before(shared_ptr const & rhs) const noexcept; + template bool owner_before(weak_ptr const & rhs) const noexcept; +}; + +template + bool operator==(shared_ptr const & a, shared_ptr const & b) noexcept; + +template + bool operator!=(shared_ptr const & a, shared_ptr const & b) noexcept; + +template + bool operator<(shared_ptr const & a, shared_ptr const & b) noexcept; + +template bool operator==(shared_ptr const & p, std::nullptr_t) noexcept; +template bool operator==(std::nullptr_t, shared_ptr const & p) noexcept; + +template bool operator!=(shared_ptr const & p, std::nullptr_t) noexcept; +template bool operator!=(std::nullptr_t, shared_ptr const & p) noexcept; + +template void swap(shared_ptr & a, shared_ptr & b) noexcept; + +template + typename shared_ptr::element_type * + get_pointer(shared_ptr const & p) noexcept; + +template + shared_ptr static_pointer_cast(shared_ptr const & r) noexcept; + +template + shared_ptr const_pointer_cast(shared_ptr const & r) noexcept; + +template + shared_ptr dynamic_pointer_cast(shared_ptr const & r) noexcept; + +template + shared_ptr reinterpret_pointer_cast(shared_ptr const & r) noexcept; + +template + std::basic_ostream & + operator<< (std::basic_ostream & os, shared_ptr const & p); + +template D * get_deleter(shared_ptr const & p) noexcept; + +} // namespace boost +``` + +## Members + +### element_type +``` +typedef ... element_type; +``` +`element_type` is `T` when `T` is not an array type, and `U` when `T` is `U[]` or `U[N]`. + +### default constructor +``` +shared_ptr() noexcept; +``` +``` +shared_ptr(std::nullptr_t) noexcept; +``` +[none] +* {blank} ++ +Effects:: Constructs an empty `shared_ptr`. +Postconditions:: `use_count() == 0 && get() == 0`. + +### pointer constructor +``` +template explicit shared_ptr(Y * p); +``` +[none] +* {blank} ++ +Requires:: `Y` must be a complete type. The expression `delete[] p`, when `T` is an array type, or `delete p`, when `T` is not an array type, + must be well-formed, well-defined, and not throw exceptions. When `T` is `U[N]`, `Y(\*)[N]` must be convertible to `T*`; when `T` is `U[]`, `Y(\*)[]` + must be convertible to `T*`; otherwise, `Y\*` must be convertible to `T*`. + +Effects:: When `T` is not an array type, constructs a `shared_ptr` that owns the pointer `p`. Otherwise, constructs a `shared_ptr` that owns `p` and + a deleter of an unspecified type that calls `delete[] p`. + +Postconditions:: `use_count() == 1 && get() == p`. If `T` is not an array type and `p` is unambiguously convertible to `enable_shared_from_this*` + for some `V`, `p\->shared_from_this()` returns a copy of `*this`. + +Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained. + +Exception safety:: If an exception is thrown, the constructor calls `delete[] p`, when `T` is an array type, or `delete p`, when `T` is not an array type. + +NOTE: `p` must be a pointer to an object that was allocated via a {cpp} `new` expression or be 0. The postcondition that use count is 1 holds even if `p` +is 0; invoking `delete` on a pointer that has a value of 0 is harmless. + +NOTE: This constructor is a template in order to remember the actual pointer type passed. The destructor will call delete with the same pointer, complete +with its original type, even when `T` does not have a virtual destructor, or is `void`. + +### constructors taking a deleter +``` +template shared_ptr(Y * p, D d); +``` +``` +template shared_ptr(Y * p, D d, A a); +``` +``` +template shared_ptr(std::nullptr_t p, D d); +``` +``` +template shared_ptr(std::nullptr_t p, D d, A a); +``` +[none] +* {blank} ++ +Requires:: `D` must be `CopyConstructible`. The copy constructor and destructor of `D` must not throw. The expression `d(p)` must be well-formed, well-defined, + and not throw exceptions. `A` must be an `Allocator`, as described in section Allocator Requirements [allocator.requirements] of the {cpp} Standard. + When `T` is `U[N]`, `Y(\*)[N]` must be convertible to `T*`; when `T` is `U[]`, `Y(\*)[]` must be convertible to `T*`; otherwise, `Y\*` must be convertible to `T*`. + +Effects:: Constructs a `shared_ptr` that owns the pointer `p` and the deleter `d`. The constructors taking an allocator a allocate memory using a copy of `a`. + +Postconditions:: `use_count() == 1 && get() == p`. If `T` is not an array type and `p` is unambiguously convertible to `enable_shared_from_this*` for some `V`, + `p\->shared_from_this()` returns a copy of `*this`. + +Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained. + +Exception safety:: If an exception is thrown, `d(p)` is called. + +NOTE: When the the time comes to delete the object pointed to by `p`, the stored copy of `d` is invoked with the stored copy of `p` as an argument. + +NOTE: Custom deallocators allow a factory function returning a `shared_ptr` 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 `shared_ptr` to a statically allocated object, and other variations allow a `shared_ptr` to be used as a wrapper +for another smart pointer, easing interoperability. + +NOTE: The requirement that the copy constructor of `D` does not throw comes from the pass by value. If the copy constructor throws, the pointer would leak. + +### copy and converting constructors +``` +shared_ptr(shared_ptr const & r) noexcept; +``` +``` +template shared_ptr(shared_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Requires:: `Y*` should be convertible to `T*`. + +Effects:: If `r` is empty, constructs an empty `shared_ptr`; otherwise, constructs a `shared_ptr` that shares ownership with `r`. + +Postconditions:: `get() == r.get() && use_count() == r.use_count()`. + +### move constructors +``` +shared_ptr(shared_ptr && r) noexcept; +``` +``` +template shared_ptr(shared_ptr && r) noexcept; +``` +[none] +* {blank} ++ +Requires:: `Y*` should be convertible to `T*`. + +Effects:: Move-constructs a `shared_ptr` from `r`. + +Postconditions:: `*this` contains the old value of `r`. `r` is empty and `r.get() == 0`. + +### aliasing constructor +``` +template shared_ptr(shared_ptr const & r, element_type * p) noexcept; +``` +[none] +* {blank} ++ +Effects:: constructs a shared_ptr that shares ownership with r and stores p. + +Postconditions:: `get() == p && use_count() == r.use_count()`. + +### aliasing move constructor +``` +template shared_ptr(shared_ptr && r, element_type * p) noexcept; +``` +[none] +* {blank} ++ +Effects:: Move-constructs a `shared_ptr` from `r`, while storing `p` instead. + +Postconditions:: `get() == p` and `use_count()` equals the old count of `r`. `r` is empty and `r.get() == 0`. + +### weak_ptr constructor +``` +template explicit shared_ptr(weak_ptr const & r); +``` +[none] +* {blank} ++ +Requires:: `Y*` should be convertible to `T*`. + +Effects:: Constructs a `shared_ptr` that shares ownership with `r` and stores a copy of the pointer stored in `r`. + +Postconditions:: `use_count() == r.use_count()`. + +Throws:: `bad_weak_ptr` when `r.use_count() == 0`. + +Exception safety:: If an exception is thrown, the constructor has no effect. + +### auto_ptr constructors +``` +template shared_ptr(std::auto_ptr & r); +``` +``` +template shared_ptr(std::auto_ptr && r); +``` +[none] +* {blank} ++ +Requires:: `Y*` should be convertible to `T*`. + +Effects:: Constructs a `shared_ptr`, as if by storing a copy of `r.release()`. + +Postconditions:: `use_count() == 1`. + +Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained. + +Exception safety:: If an exception is thrown, the constructor has no effect. + +### unique_ptr constructor +``` +template shared_ptr(std::unique_ptr && r); +``` +[none] +* {blank} ++ +Requires:: `Y*` should be convertible to `T*`. + +Effects:: Equivalent to `shared_ptr(r.release(), r.get_deleter())` when `D` is not a reference type. Otherwise, equivalent to + `shared_ptr(r.release(), del)`, where `del` is a deleter that stores the reference `rd` returned from `r.get_deleter()` and + `del(p)` calls `rd(p)`. + +Postconditions:: `use_count() == 1`. + +Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained. + +Exception safety:: If an exception is thrown, the constructor has no effect. + +### destructor +``` +~shared_ptr() noexcept; +``` +[none] +* {blank} ++ +Effects:: +- If `*this` is empty, or shares ownership with another `shared_ptr` instance (`use_count() > 1`), there are no side effects. +- Otherwise, if `*this` owns a pointer `p` and a deleter `d`, `d(p)` is called. +- Otherwise, `*this` owns a pointer `p`, and `delete p` is called. + +### assignment +``` +shared_ptr & operator=(shared_ptr const & r) noexcept; +``` +``` +template shared_ptr & operator=(shared_ptr const & r) noexcept; +``` +``` +template shared_ptr & operator=(std::auto_ptr & r); +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr(r).swap(*this)`. +Returns:: `*this`. + +NOTE: The use count updates caused by the temporary object construction and destruction are not considered observable side effects, +and the implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary. + +[NOTE] +==== +In particular, in the example: +``` +shared_ptr p(new int); +shared_ptr q(p); +p = p; +q = p; +``` +both assignments may be no-ops. +==== + +``` +shared_ptr & operator=(shared_ptr && r) noexcept; +``` +``` +template shared_ptr & operator=(shared_ptr && r) noexcept; +``` +``` +template shared_ptr & operator=(std::auto_ptr && r); +``` +``` +template shared_ptr & operator=(std::unique_ptr && r); +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr(std::move(r)).swap(*this)`. +Returns:: `*this`. + +``` +shared_ptr & operator=(std::nullptr_t) noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr().swap(*this)`. +Returns:: `*this`. + +### reset +``` +void reset() noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr().swap(*this)`. + +``` +template void reset(Y * p); +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr(p).swap(*this)`. + +``` +template void reset(Y * p, D d); +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr(p, d).swap(*this)`. + +``` +template void reset(Y * p, D d, A a); +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr(p, d, a).swap(*this)`. + +``` +template void reset(shared_ptr const & r, element_type * p) noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr(r, p).swap(*this)`. + +``` +template void reset(shared_ptr && r, element_type * p) noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr(std::move(r), p).swap(*this)`. + +### indirection +``` +T & operator*() const noexcept; +``` +[none] +* {blank} ++ +Requires:: `T` should not be an array type. The stored pointer must not be 0. +Returns:: `*get()`. + +``` +T * operator->() const noexcept; +``` +[none] +* {blank} ++ +Requires:: `T` should not be an array type. The stored pointer must not be 0. +Returns:: `get()`. + +``` +element_type & operator[](std::ptrdiff_t i) const noexcept; +``` +[none] +* {blank} ++ +Requires:: `T` should be an array type. The stored pointer must not be 0. `i >= 0`. If `T` is `U[N]`, `i < N`. +Returns:: `get()[i]`. + +### get + +``` +element_type * get() const noexcept; +``` +[none] +* {blank} ++ +Returns:: the stored pointer. + +### unique +``` +bool unique() const noexcept; +``` +[none] +* {blank} ++ +Returns:: `use_count() == 1`. + +### use_count +``` +long use_count() const noexcept; +``` +[none] +* {blank} ++ +Returns:: the number of `shared_ptr` objects, `*this` included, that share ownership with `*this`, or 0 when `*this` is empty. + +### conversions +``` +explicit operator bool() const noexcept; +``` +[none] +* {blank} ++ +Returns:: `get() != 0`. + +NOTE: This conversion operator allows `shared_ptr` objects to be used in boolean contexts, like `if(p && p\->valid()) {}`. + +NOTE: The conversion to `bool` is not merely syntactic sugar. It allows `shared_ptr` variables to be declared in conditions when using +`dynamic_pointer_cast` or `weak_ptr::lock`. + +### swap +``` +void swap(shared_ptr & b) noexcept; +``` +[none] +* {blank} ++ +Effects:: Exchanges the contents of the two smart pointers. + +### owner_before +``` +template bool owner_before(shared_ptr const & rhs) const noexcept; +``` +``` +template bool owner_before(weak_ptr const & rhs) const noexcept; +``` +[none] +* {blank} ++ +Effects:: See the description of `operator<`. + +## Free Functions + +### comparison +``` +template + bool operator==(shared_ptr const & a, shared_ptr const & b) noexcept; +``` +[none] +* {blank} ++ +Returns:: `a.get() == b.get()`. + +``` +template + bool operator!=(shared_ptr const & a, shared_ptr const & b) noexcept; +``` +[none] +* {blank} ++ +Returns:: `a.get() != b.get()`. + +``` +template bool operator==(shared_ptr const & p, std::nullptr_t) noexcept; +``` +``` +template bool operator==(std::nullptr_t, shared_ptr const & p) noexcept; +``` +[none] +* {blank} ++ +Returns:: `p.get() == 0`. + +``` +template bool operator!=(shared_ptr const & p, std::nullptr_t) noexcept; +``` +``` +template bool operator!=(std::nullptr_t, shared_ptr const & p) noexcept; +``` +[none] +* {blank} ++ +Returns:: `p.get() != 0`. + +``` +template + bool operator<(shared_ptr const & a, shared_ptr const & b) noexcept; +``` +[none] +* {blank} ++ +Returns:: an unspecified value such that + - `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard; + - under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `shared_ptr` instances + are equivalent if and only if they share ownership or are both empty. + +NOTE: Allows `shared_ptr` objects to be used as keys in associative containers. + +NOTE: The rest of the comparison operators are omitted by design. + +### swap +``` +template void swap(shared_ptr & a, shared_ptr & b) noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `a.swap(b)`. + +### get_pointer +``` +template + typename shared_ptr::element_type * + get_pointer(shared_ptr const & p) noexcept; +``` +[none] +* {blank} ++ +Returns:: `p.get()`. + +NOTE: Provided as an aid to generic programming. Used by `mem_fn`. + +### static_pointer_cast +``` +template + shared_ptr static_pointer_cast(shared_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Requires:: The expression `static_cast( (U*)0 )` must be well-formed. +Returns:: `shared_ptr( r, static_cast::element_type*>(r.get()) )`. + +CAUTION: The seemingly equivalent expression `shared_ptr(static_cast(r.get()))` will eventually +result in undefined behavior, attempting to delete the same object twice. + +### const_pointer_cast +``` +template + shared_ptr const_pointer_cast(shared_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Requires:: The expression `const_cast( (U*)0 )` must be well-formed. +Returns:: `shared_ptr( r, const_cast::element_type*>(r.get()) )`. + +### dynamic_pointer_cast +``` +template + shared_ptr dynamic_pointer_cast(shared_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Requires:: The expression `dynamic_cast( (U*)0 )` must be well-formed. +Returns:: + - When `dynamic_cast::element_type*>(r.get())` returns a nonzero value `p`, `shared_ptr(r, p)`; + - Otherwise, `shared_ptr()`. + +### reinterpret_pointer_cast +``` +template + shared_ptr reinterpret_pointer_cast(shared_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Requires:: The expression `reinterpret_cast( (U*)0 )` must be well-formed. +Returns:: `shared_ptr( r, reinterpret_cast::element_type*>(r.get()) )`. + +### operator<< +``` +template + std::basic_ostream & + operator<< (std::basic_ostream & os, shared_ptr const & p); +``` +[none] +* {blank} ++ +Effects:: `os << p.get();`. +Returns:: `os`. + +### get_deleter +``` +template + D * get_deleter(shared_ptr const & p) noexcept; +``` +[none] +* {blank} ++ +Returns:: If `*this` owns a deleter `d` of type (cv-unqualified) `D`, returns `&d`; otherwise returns 0. + +## Example + +See link:../../example/shared_ptr_example.cpp[shared_ptr_example.cpp] for a complete example program. The program builds a +`std::vector` and `std::set` of `shared_ptr` objects. + +Note that after the containers have been populated, some of the `shared_ptr` objects will have a use count of 1 rather than +a use count of 2, since the set is a `std::set` rather than a `std::multiset`, and thus does not contain duplicate entries. +Furthermore, the use count may be even higher at various times while `push_back` and `insert` 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. + +## Handle/Body Idiom + +One common usage of `shared_ptr` is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) +in the header file. + +The link:../../example/shared_ptr_example2_test.cpp[shared_ptr_example2_test.cpp] sample program includes a header file, +link:../../example/shared_ptr_example2.hpp[shared_ptr_example2.hpp], which uses a `shared_ptr` to an incomplete type to hide the implementation. +The instantiation of member functions which require a complete type occurs in the link:../../example/shared_ptr_example2.cpp[shared_ptr_example2.cpp] +implementation file. Note that there is no need for an explicit destructor. Unlike `~scoped_ptr`, `~shared_ptr` does not require that `T` be a complete type. + +## Thread Safety + +`shared_ptr` objects offer the same level of thread safety as built-in types. A `shared_ptr` instance can be "read" (accessed using only const operations) +simultaneously by multiple threads. Different `shared_ptr` instances can be "written to" (accessed using mutable operations such as `operator=` or `reset`) +simultaneously by multiple threads (even when these instances are copies, and share the same reference count underneath.) + +Any other simultaneous accesses result in undefined behavior. + +Examples: +``` +shared_ptr p(new int(42)); +``` + +.Reading a `shared_ptr` from two threads +``` +// thread A +shared_ptr p2(p); // reads p + +// thread B +shared_ptr p3(p); // OK, multiple reads are safe +``` + +.Writing different `shared_ptr` instances from two threads +``` +// thread A +p.reset(new int(1912)); // writes p + +// thread B +p2.reset(); // OK, writes p2 +``` + +.Reading and writing a `shared_ptr` from two threads +``` +// thread A +p = p3; // reads p3, writes p + +// thread B +p3.reset(); // writes p3; undefined, simultaneous read/write +``` + +.Reading and destroying a `shared_ptr` from two threads +``` +// thread A +p3 = p2; // reads p2, writes p3 + +// thread B +// p2 goes out of scope: undefined, the destructor is considered a "write access" +``` + +.Writing a `shared_ptr` from two threads +``` +// thread A +p3.reset(new int(1)); + +// thread B +p3.reset(new int(2)); // undefined, multiple writes +``` + +Starting with Boost release 1.33.0, `shared_ptr` uses a lock-free implementation on most common platforms. + +If your program is single-threaded and does not link to any libraries that might have used `shared_ptr` in its default configuration, +you can `#define` the macro `BOOST_SP_DISABLE_THREADS` on a project-wide basis to switch to ordinary non-atomic reference count updates. + +(Defining `BOOST_SP_DISABLE_THREADS` in some, but not all, translation units is technically a violation of the One Definition Rule and +undefined behavior. Nevertheless, the implementation attempts to do its best to accommodate the request to use non-atomic updates in those +translation units. No guarantees, though.) + +You can define the macro `BOOST_SP_USE_PTHREADS` to turn off the lock-free platform-specific implementation and fall back to the generic +`pthread_mutex_t`-based code. + +## Frequently Asked Questions + +[qanda] +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?:: + + An important goal of `shared_ptr` 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.) + +Why doesn't shared_ptr have template parameters supplying traits or policies to allow extensive user customization?:: + + Parameterization discourages users. The `shared_ptr` template is carefully crafted to meet common needs without extensive parameterization. + +I am not convinced. Default parameters can be used where appropriate to hide the complexity. Again, why not policies?:: + + Template parameters affect the type. See the answer to the first question above. + +Why doesn't `shared_ptr` use a linked list implementation?:: + + A linked list implementation does not offer enough advantages to offset the added cost of an extra pointer. In addition, it is expensive to + make a linked list implementation thread safe. + +Why doesn't `shared_ptr` (or any of the other Boost smart pointers) supply an automatic conversion to T*?:: + + Automatic conversion is believed to be too error prone. + +Why does `shared_ptr` supply `use_count()`?:: + + 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. + +Why doesn't `shared_ptr` specify complexity requirements?:: + + Because complexity requirements limit implementors and complicate the specification without apparent benefit to `shared_ptr` users. For example, + error-checking implementations might become non-conforming if they had to meet stringent complexity requirements. + +Why doesn't `shared_ptr` provide a `release()` function?:: + + `shared_ptr` cannot give away ownership unless it's `unique()` because the other copy will still destroy the object. ++ +Consider: ++ +``` +shared_ptr a(new int); +shared_ptr b(a); // a.use_count() == b.use_count() == 2 + +int * p = a.release(); + +// Who owns p now? b will still call delete on it in its destructor. +``` ++ +Furthermore, the pointer returned by `release()` would be difficult to deallocate reliably, as the source `shared_ptr` could have been created with a +custom deleter, or may have pointed to an object of a different type. + +Why is `operator\->()` const, but its return value is a non-const pointer to the element type?:: + + Shallow copy pointers, including raw pointers, typically don't propagate constness. It makes little sense for them to do so, as you can always obtain a + non-const pointer from a const one and then proceed to modify the object through it. `shared_ptr` is "as close to raw pointers as possible but no closer". From f90b418460135fe52036c8764957c3eb7e336cac Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 13 Jun 2017 01:34:31 +0300 Subject: [PATCH 08/26] Add enable_shared_from_this.adoc --- doc/smart_ptr/enable_shared_from_this.adoc | 136 ++++++++++++++++++++- 1 file changed, 135 insertions(+), 1 deletion(-) diff --git a/doc/smart_ptr/enable_shared_from_this.adoc b/doc/smart_ptr/enable_shared_from_this.adoc index 428fc30..62c16d0 100644 --- a/doc/smart_ptr/enable_shared_from_this.adoc +++ b/doc/smart_ptr/enable_shared_from_this.adoc @@ -1,5 +1,5 @@ //// -Copyright 2017 Peter Dimov +Copyright 2002, 2003, 2015, 2017 Peter Dimov Distributed under the Boost Software License, Version 1.0. @@ -13,3 +13,137 @@ http://www.boost.org/LICENSE_1_0.txt :toc-title: :idprefix: enable_shared_from_this_ +## Description + +The class template `enable_shared_from_this` is used as a base class that allows +a `shared_ptr` or a `weak_ptr` to the current object to be obtained from within a +member function. + +`enable_shared_from_this` defines two member functions called `shared_from_this` +that return a `shared_ptr` and `shared_ptr`, depending on constness, to +`this`. It also defines two member functions called `weak_from_this` that return a +corresponding `weak_ptr`. + +## Example + +``` +#include +#include +#include + +class Y: public boost::enable_shared_from_this +{ +public: + + boost::shared_ptr f() + { + return shared_from_this(); + } +}; + +int main() +{ + boost::shared_ptr p(new Y); + boost::shared_ptr q = p->f(); + assert(p == q); + assert(!(p < q || q < p)); // p and q must share ownership +} +``` + +## Synopsis + +`enable_shared_from_this` is defined in ``. + +``` +namespace boost +{ + +template class enable_shared_from_this +{ +private: + + // exposition only + weak_ptr weak_this_; + +protected: + + enable_shared_from_this() = default; + ~enable_shared_from_this() = default; + + enable_shared_from_this(const enable_shared_from_this&) noexcept; + enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; + +public: + + shared_ptr shared_from_this(); + shared_ptr shared_from_this() const; + + weak_ptr weak_from_this() noexcept; + weak_ptr weak_from_this() const noexcept; +} + +} // namespace boost +``` + +## Members + +``` +enable_shared_from_this(enable_shared_from_this const &) noexcept; +``` +[none] +* {blank} ++ +Effects:: Default-constructs `weak_this_`. + +NOTE: `weak_this_` is _not_ copied from the argument. + +``` +enable_shared_from_this& operator=(enable_shared_from_this const &) noexcept; +``` +[none] +* {blank} ++ +Returns:: `*this`. + +NOTE: `weak_this_` is unchanged. + +``` +template shared_ptr enable_shared_from_this::shared_from_this(); +``` +``` +template shared_ptr enable_shared_from_this::shared_from_this() const; +``` +[none] +* {blank} ++ +Returns:: `shared_ptr(weak_this_)`. + +NOTE: These members throw `bad_weak_ptr` when `*this` is not owned by a `shared_ptr`. + +[NOTE] +==== +`weak_this_` is initialized by `shared_ptr` to a copy of itself when it's constructed by a pointer to `*this`. +For example, in the following code: +``` +class Y: public boost::enable_shared_from_this +{ +}; + +int main() +{ + boost::shared_ptr p(new Y); +} +``` +the construction of `p` will automatically initialize `p->weak_this_` to `p`. +==== + +``` +template weak_ptr enable_shared_from_this::weak_from_this() noexcept; +``` +``` +template weak_ptr enable_shared_from_this::weak_from_this() const noexcept; +``` +[none] +* {blank} ++ +Returns:: `weak_this_`. From 65e616c90b120a5b1efa04acfe1c597cf7231843 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 13 Jun 2017 01:45:18 +0300 Subject: [PATCH 09/26] Add a history item for the N1450 formal proposal --- doc/smart_ptr/history.adoc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/smart_ptr/history.adoc b/doc/smart_ptr/history.adoc index 9d3c9f6..5e1a2c9 100644 --- a/doc/smart_ptr/history.adoc +++ b/doc/smart_ptr/history.adoc @@ -71,6 +71,12 @@ Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus Peter Dimov reworked all four classes, adding features, fixing bugs, splitting them into four separate headers, and adding `weak_ptr`. +## March 2003 + +Peter Dimov, Beman Dawes and Greg Colvin http://open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html[proposed] `shared_ptr` +and `weak_ptr` for inclusion in the Standard Library via the first Library Technical Report (known as TR1). The proposal was +accepted and eventually went on to become a part of the {cpp} standard in its 2011 iteration. + ## November 2012 Glen Fernandes provided implementations of `make_shared` and `allocate_shared` for arrays. They achieve a single allocation From c4d07defcd1947a9175dd7c6fe10786988c5154a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 13 Jun 2017 01:46:50 +0300 Subject: [PATCH 10/26] Add .gitignore --- doc/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 doc/.gitignore diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..0972e2d --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1,2 @@ +/html/ +/pdf/ From f770e5398901a55fb2b7d7e19d50e4a1c3a4c3c8 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 13 Jun 2017 02:22:51 +0300 Subject: [PATCH 11/26] More history --- doc/smart_ptr/history.adoc | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/doc/smart_ptr/history.adoc b/doc/smart_ptr/history.adoc index 5e1a2c9..9e60a7a 100644 --- a/doc/smart_ptr/history.adoc +++ b/doc/smart_ptr/history.adoc @@ -77,18 +77,30 @@ Peter Dimov, Beman Dawes and Greg Colvin http://open-std.org/jtc1/sc22/wg21/docs and `weak_ptr` for inclusion in the Standard Library via the first Library Technical Report (known as TR1). The proposal was accepted and eventually went on to become a part of the {cpp} standard in its 2011 iteration. +## July 2007 + +Peter Dimov and Beman Dawes http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2351.htm[proposed] a number of enhancements +to `shared_ptr` as it was entering the working paper that eventually became the {cpp}11 standard. + ## November 2012 Glen Fernandes provided implementations of `make_shared` and `allocate_shared` for arrays. They achieve a single allocation for an array that can be initialized with constructor arguments or initializer lists as well as overloads for default initialization and no value initialization. +Peter Dimov aided this development by extending `shared_ptr` to support arrays via the syntax `shared_ptr` and `shared_ptr`. + +## April 2013 + +Peter Dimov http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3640.html[proposed] the extension of `shared_ptr` to support +arrays for inclusion into the standard, and it was accepted. + ## February 2014 -Glen Fernandes updated overloads of `make_shared` and `allocate_shared` to conform to the specification in {cpp} standard paper -http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3870.html[N3870], -and implemented `make_unique` for arrays and objects. Peter Dimov and Glen Fernandes updated the scalar and array implementations, -respectively, to resolve {cpp} standard library defect 2070. +Glen Fernandes updated `make_shared` and `allocate_shared` to conform to the specification in {cpp} standard paper +http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3870.html[N3870], and implemented `make_unique` for arrays and objects. + +Peter Dimov and Glen Fernandes updated the scalar and array implementations, respectively, to resolve {cpp} standard library defect 2070. ## February 2017 From 5b7d3c08abca6b3e65a183e5a25e44f91452cd24 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 13 Jun 2017 02:51:02 +0300 Subject: [PATCH 12/26] Small fix to enable_shared_from_this.adoc --- doc/smart_ptr/enable_shared_from_this.adoc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/smart_ptr/enable_shared_from_this.adoc b/doc/smart_ptr/enable_shared_from_this.adoc index 62c16d0..77037d3 100644 --- a/doc/smart_ptr/enable_shared_from_this.adoc +++ b/doc/smart_ptr/enable_shared_from_this.adoc @@ -125,16 +125,14 @@ NOTE: These members throw `bad_weak_ptr` when `*this` is not owned by a `shared_ `weak_this_` is initialized by `shared_ptr` to a copy of itself when it's constructed by a pointer to `*this`. For example, in the following code: ``` -class Y: public boost::enable_shared_from_this -{ -}; +class Y: public boost::enable_shared_from_this {}; int main() { boost::shared_ptr p(new Y); } ``` -the construction of `p` will automatically initialize `p->weak_this_` to `p`. +the construction of `p` will automatically initialize `p\->weak_this_` to `p`. ==== ``` From ab99c8f7aa1a57e503122acf921c3b7e82020d18 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 13 Jun 2017 05:56:19 +0300 Subject: [PATCH 13/26] Reflect unique_ptr constructor change --- doc/smart_ptr/shared_ptr.adoc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/smart_ptr/shared_ptr.adoc b/doc/smart_ptr/shared_ptr.adoc index 8208c90..f7e5335 100644 --- a/doc/smart_ptr/shared_ptr.adoc +++ b/doc/smart_ptr/shared_ptr.adoc @@ -412,11 +412,11 @@ template shared_ptr(std::unique_ptr && r); + Requires:: `Y*` should be convertible to `T*`. -Effects:: Equivalent to `shared_ptr(r.release(), r.get_deleter())` when `D` is not a reference type. Otherwise, equivalent to - `shared_ptr(r.release(), del)`, where `del` is a deleter that stores the reference `rd` returned from `r.get_deleter()` and - `del(p)` calls `rd(p)`. - -Postconditions:: `use_count() == 1`. +Effects:: +- When `r.get() == 0`, equivalent to `shared_ptr()`; +- When `D` is not a reference type, equivalent to `shared_ptr(r.release(), r.get_deleter())`; +- Otherwise, equivalent to `shared_ptr(r.release(), del)`, where `del` is a deleter that stores the reference `rd` returned + from `r.get_deleter()` and `del(p)` calls `rd(p)`. Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained. From 420626d6d90b38a8241cba1d63c8ba876767e8ce Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 13 Jun 2017 06:34:16 +0300 Subject: [PATCH 14/26] Add weak_ptr.adoc --- doc/smart_ptr/shared_ptr.adoc | 6 +- doc/smart_ptr/weak_ptr.adoc | 288 +++++++++++++++++++++++++++++++++- 2 files changed, 290 insertions(+), 4 deletions(-) diff --git a/doc/smart_ptr/shared_ptr.adoc b/doc/smart_ptr/shared_ptr.adoc index f7e5335..52aa1be 100644 --- a/doc/smart_ptr/shared_ptr.adoc +++ b/doc/smart_ptr/shared_ptr.adoc @@ -577,7 +577,7 @@ element_type * get() const noexcept; [none] * {blank} + -Returns:: the stored pointer. +Returns:: The stored pointer. ### unique ``` @@ -595,7 +595,7 @@ long use_count() const noexcept; [none] * {blank} + -Returns:: the number of `shared_ptr` objects, `*this` included, that share ownership with `*this`, or 0 when `*this` is empty. +Returns:: The number of `shared_ptr` objects, `*this` included, that share ownership with `*this`, or 0 when `*this` is empty. ### conversions ``` @@ -682,7 +682,7 @@ template [none] * {blank} + -Returns:: an unspecified value such that +Returns:: An unspecified value such that - `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard; - under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `shared_ptr` instances are equivalent if and only if they share ownership or are both empty. diff --git a/doc/smart_ptr/weak_ptr.adoc b/doc/smart_ptr/weak_ptr.adoc index c5a740c..b605949 100644 --- a/doc/smart_ptr/weak_ptr.adoc +++ b/doc/smart_ptr/weak_ptr.adoc @@ -1,5 +1,7 @@ //// -Copyright 2017 Peter Dimov +Copyright 1999 Greg Colvin and Beman Dawes +Copyright 2002 Darin Adler +Copyright 2002-2005, 2017 Peter Dimov Distributed under the Boost Software License, Version 1.0. @@ -13,3 +15,287 @@ http://www.boost.org/LICENSE_1_0.txt :toc-title: :idprefix: weak_ptr_ +## Description + +The `weak_ptr` class template stores a "weak reference" to an object that's already managed by a `shared_ptr`. +To access the object, a `weak_ptr` can be converted to a `shared_ptr` using the `shared_ptr` constructor taking +`weak_ptr`, or the `weak_ptr` member function `lock`. When the last `shared_ptr` to the object goes away and the +object is deleted, the attempt to obtain a `shared_ptr` from the `weak_ptr` instances that refer to the deleted +object will fail: the constructor will throw an exception of type `boost::bad_weak_ptr`, and `weak_ptr::lock` will +return an empty `shared_ptr`. + +Every `weak_ptr` meets the `CopyConstructible` and `Assignable` requirements of the {cpp} Standard Library, and so +can be used in standard library containers. Comparison operators are supplied so that `weak_ptr` works with the standard +library's associative containers. + +`weak_ptr` operations never throw exceptions. + +The class template is parameterized on `T`, the type of the object pointed to. + +Compared to `shared_ptr`, `weak_ptr` provides a very limited subset of operations since accessing its stored pointer is +often dangerous in multithreaded programs, and sometimes unsafe even within a single thread (that is, it may invoke undefined +behavior.) Pretend for a moment that `weak_ptr` had a get member function that returned a raw pointer, and consider this innocent +piece of code: + +``` +shared_ptr p(new int(5)); +weak_ptr q(p); + +// some time later + +if(int * r = q.get()) +{ + // use *r +} +``` + +Imagine that after the `if`, but immediately before `r` is used, another thread executes the statement `p.reset()`. Now `r` is a dangling pointer. + +The solution to this problem is to create a temporary `shared_ptr` from `q`: + +``` +shared_ptr p(new int(5)); +weak_ptr q(p); + +// some time later + +if(shared_ptr r = q.lock()) +{ + // use *r +} +``` + +Now `r` holds a reference to the object that was pointed by `q`. Even if `p.reset()` is executed in another thread, the object will stay alive until +`r` goes out of scope or is reset. By obtaining a `shared_ptr` to the object, we have effectively locked it against destruction. + +## Synopsis + +`weak_ptr` is defined in ``. + +``` +namespace boost +{ + +template class weak_ptr +{ +public: + + typedef /*see below*/ element_type; + + weak_ptr() noexcept; + + template weak_ptr(shared_ptr const & r) noexcept; + weak_ptr(weak_ptr const & r) noexcept; + template weak_ptr(weak_ptr const & r) noexcept; + + weak_ptr(weak_ptr && r) noexcept; + + ~weak_ptr() noexcept; + + weak_ptr & operator=(weak_ptr const & r) noexcept; + weak_ptr & operator=(weak_ptr && r) noexcept; + template weak_ptr & operator=(weak_ptr const & r) noexcept; + template weak_ptr & operator=(shared_ptr const & r) noexcept; + + long use_count() const noexcept; + bool expired() const noexcept; + + shared_ptr lock() const noexcept; + + void reset() noexcept; + + void swap(weak_ptr & b) noexcept; + + template bool owner_before( weak_ptr const & r ) const noexcept; + template bool owner_before( shared_ptr const & r ) const noexcept; +}; + +template + bool operator<(weak_ptr const & a, weak_ptr const & b) noexcept; + +template void swap(weak_ptr & a, weak_ptr & b) noexcept; + +} // namespace boost +``` + +## Members + +### element_type +``` +typedef ... element_type; +``` +`element_type` is `T` when `T` is not an array type, and `U` when `T` is `U[]` or `U[N]`. + +### constructors +``` +weak_ptr() noexcept; +``` +[none] +* {blank} ++ +Effects:: Constructs an empty `weak_ptr`. +Postconditions:: `use_count() == 0`. + +``` +template weak_ptr(shared_ptr const & r) noexcept; +``` +``` +weak_ptr(weak_ptr const & r) noexcept; +``` +``` +template weak_ptr(weak_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Effects:: If `r` is empty, constructs an empty `weak_ptr`; otherwise, constructs a `weak_ptr` that shares ownership with `r` as if by storing a copy of the pointer stored in `r`. +Postconditions:: `use_count() == r.use_count()`. + +``` +weak_ptr(weak_ptr && r) noexcept; +``` +[none] +* {blank} ++ +Effects:: Constructs a `weak_ptr` that has the value `r` held. +Postconditions:: `r` is empty. + +### destructor +``` +~weak_ptr() noexcept; +``` +[none] +* {blank} ++ +Effects:: Destroys this `weak_ptr` but has no effect on the object its stored pointer points to. + +### assignment +``` +weak_ptr & operator=(weak_ptr const & r) noexcept; +``` +``` +weak_ptr & operator=(weak_ptr && r) noexcept; +``` +``` +template weak_ptr & operator=(weak_ptr const & r) noexcept; +``` +``` +template weak_ptr & operator=(shared_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `weak_ptr(r).swap(*this)`. + +NOTE: The implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary. + +### use_count +``` +long use_count() const noexcept; +``` +[none] +* {blank} ++ +Returns:: 0 if `*this` is empty; otherwise, the number of `shared_ptr` objects that share ownership with `*this`. + +### expired +``` +bool expired() const noexcept; +``` +[none] +* {blank} ++ +Returns:: `use_count() == 0`. + +### lock +``` +shared_ptr lock() const noexcept; +``` +[none] +* {blank} ++ +Returns:: `expired()? shared_ptr(): shared_ptr(*this)`. + +### reset +``` +void reset() noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `weak_ptr().swap(*this)`. + +### swap +``` +void swap(weak_ptr & b) noexcept; +``` +[none] +* {blank} ++ +Effects:: Exchanges the contents of the two smart pointers. + +``` +template bool owner_before( weak_ptr const & r ) const noexcept; +``` +``` +template bool owner_before( shared_ptr const & r ) const noexcept; +``` +[none] +* {blank} ++ +Returns:: See the description of `operator<`. + +## Free Functions + +### comparison +``` +template + bool operator<(weak_ptr const & a, weak_ptr const & b) noexcept; +``` +[none] +* {blank} ++ +Returns:: An unspecified value such that +- `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard; +- under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `weak_ptr` instances + are equivalent if and only if they share ownership or are both empty. + +NOTE: Allows `weak_ptr` objects to be used as keys in associative containers. + +### swap +``` +template void swap(weak_ptr & a, weak_ptr & b) noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `a.swap(b)`. + +## Frequently Asked Questions + +[qanda] +Can an object create a weak_ptr to itself in its constructor?:: + + No. A `weak_ptr` can only be created from a `shared_ptr`, and at object construction time no + `shared_ptr` to the object exists yet. Even if you could create a temporary `shared_ptr` to `this`, + it would go out of scope at the end of the constructor, and all `weak_ptr` instances would instantly expire. ++ +The solution is to make the constructor private, and supply a factory function that returns a `shared_ptr`: ++ +``` +class X +{ +private: + + X(); + +public: + + static shared_ptr create() + { + shared_ptr px(new X); + // create weak pointers from px here + return px; + } +}; +``` From 8f99919102fb35f6703ce14f706826c436bd5f55 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 13 Jun 2017 23:08:38 -0400 Subject: [PATCH 15/26] Update make_shared documentation --- doc/smart_ptr/make_shared.adoc | 256 +++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc index 53af79d..22522e8 100644 --- a/doc/smart_ptr/make_shared.adoc +++ b/doc/smart_ptr/make_shared.adoc @@ -1,5 +1,6 @@ //// Copyright 2017 Peter Dimov +Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. @@ -13,3 +14,258 @@ http://www.boost.org/LICENSE_1_0.txt :toc-title: :idprefix: make_shared_ +## Description + +The function templates `make_shared` and `allocate_shared` provide convenient, +safe and efficient ways to create `shared_ptr` objects. + +## Rationale + +Consistent use of `shared_ptr` can eliminate the need to use an explicit +`delete`, but alone it provides no support in avoiding explicit `new`. There +were repeated requests from users for a factory function that creates an +object of a given type and returns a `shared_ptr` to it. Besides convenience +and style, such a function is also exception safe and considerably faster +because it can use a single allocation for both the object and its +corresponding control block, eliminating a significant portion of +`shared_ptr` construction overhead. This eliminates one of the major +efficiency complaints about `shared_ptr`. + +The family of overloaded function templates, `make_shared` and +`allocate_shared`, were provided to address this need. `make_shared` uses the +global `operator new` to allocate memory, whereas `allocate_shared` uses an +user-supplied allocator, allowing finer control. + +The rationale for choosing the name `make_shared` is that the expression +`make_shared()` can be read aloud and conveys the intended meaning. + +Originally the Boost function templates `allocate_shared` and `make_shared` +were provided for scalar objects only. There was a need to have efficient +allocation of array objects. One criticism of class template `shared_array` +was always the lack of a utility like `make_shared` that uses only a single +allocation. When `shared_ptr` was enhanced to support array types, additional +overloads of `allocate_shared` and `make_shared` were provided for array +types. + +## Synopsis + +`make_shared` and `allocate_shared` are defined in +``. + +[subs=+quotes] +``` +namespace boost { + template + shared_ptr make_shared(Args&&... args); + template + shared_ptr allocate_shared(const A& a, Args&&... args); + + template + shared_ptr make_shared(std::size_t n); + template + shared_ptr allocate_shared(const A& a, std::size_t n); + + template + shared_ptr make_shared(); + template + shared_ptr allocate_shared(const A& a); + + template + shared_ptr make_shared(std::size_t n, _see below_ v); + template + shared_ptr allocate_shared(const A& a, std::size_t n, _see below_ v); + + template + shared_ptr make_shared(_see below_ v); + template + shared_ptr allocate_shared(const A& a, _see below_ v); + + template + shared_ptr make_shared_noinit(); + template + shared_ptr allocate_shared_noinit(const A& a); + + template + shared_ptr make_shared_noinit(std::size_t n); + template + shared_ptr allocate_shared_noinit(const A& a, std::size_t n); +} +``` + +## Free Functions + +The common requirements that apply to all `make_shared` and `allocate_shared` +overloads, unless specified otherwise, are described below. + +Requires:: `A` shall be an _allocator_. The copy constructor and destructor +of `A` shall not throw exceptions. + +Effects:: Allocates memory for an object of type `T` or `n` objects of `_U_` +(if `T` is an array type of the form `__U__[]` and `n` is determined by +arguments, as specified by the concrete overload). The object is initialized +from arguments as specified by the concrete overload. Uses a rebound copy of +`a` (for an unspecified `value_type`) to allocate memory. If an exception is +thrown, the functions have no effect. + +Returns:: A `shared_ptr` instance that stores and owns the address of the +newly constructed object. + +Postconditions:: `__r__.get() != 0` and `__r__.use_count() == 1`, where `_r_` +is the return value. + +Throws:: An exception thrown from `A::allocate`, or from the initialization +of the object. + +Remarks:: +* Performs no more than one memory allocation. This provides efficiency +equivalent to an intrusive smart pointer. +* When an object of an array type is specified to be initialized to a value of +the same type `v`, this shall be interpreted to mean that each array element +of the object is initialized to the corresponding element from `v`. +* When an object of an array type is specified to be value-initialized, this +shall be interpreted to mean that each array element of the object is +value-initialized. +* When a (sub)object of non-array type `_U_` is specified to be initialized to +a value `v`, or constructed from `args$$...$$`, `make_shared` shall perform +this initialization via the expression `::new(__p__) __U__(__expr__)` (where +`_expr_` is `v` or `std::forward(args)$$...$$)` respectively) and `_p_` +has type `void*` and points to storage suitable to hold an object of type +`_U_`. +* When a (sub)object of non-array type `_U_` is specified to be initialized to +a value `v`, or constructed from `args$$...$$`, `allocate_shared` shall +perform this initialization via the expression +`std::allocator_traits<__A2__>::construct(__a2__, __p__, __expr__)` (where +`_expr_` is `v` or `std::forward(args)$$...$$)` respectively), `_p_` +points to storage suitable to hold an object of type `_U_`, and `_a2_` of +type `_A2_` is a rebound copy `a` such that its `value_type` is `_U_`. +* When a (sub)object of non-array type `_U_` is specified to be +default-initialized, `make_shared_noinit` and `allocate_shared_noinit` shall +perform this initialization via the expression `::new(__p__) __U__`, where +`_p_` has type `void*` and points to storage suitable to hold an object of +type `_U_`. +* When a (sub)object of non-array type `_U_` is specified to be +value-initialized, `make_shared` shall perform this initialization via the +expression `::new(__p__) __U__()`, where `_p_` has type `void*` and points to +storage suitable to hold an object of type `_U_`. +* When a (sub)object of non-array type `_U_` is specified to be +value-initialized, `allocate_shared` shall perform this initialization via the +expression `std::allocator_traits<__A2__>::construct(__a2__, __p__)`, where +`p` points to storage suitable to hold an object of type `_U_` and `_a2_` of +type `_A2_` is a rebound copy of `a` such that its value_type is `_U_`. +* Array elements are initialized in ascending order of their addresses. +* When the lifetime of the object managed by the return value ends, or when +the initialization of an array element throws an exception, the initialized +elements should be destroyed in the reverse order of their construction. + +NOTE: These functions will typically allocate more memory than the total size +of the element objects to allow for internal bookkeeping structures such as +the reference counts. + +``` +template + shared_ptr make_shared(Args&&... args); +``` +:: +``` +template + shared_ptr allocate_shared(const A& a, Args&&... args); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is not an array type. +Returns::: A `shared_ptr` to an object of type `T`, constructed from +`args$$...$$`. + +``` +template + shared_ptr make_shared(std::size_t n); +``` +:: +``` +template + shared_ptr allocate_shared(const A& a, std::size_t n); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is an array type of the form `__U__[]`. +Returns::: A `shared_ptr` to a sequence of `n` value-initialized objects of +type `_U_`. + +``` +template + shared_ptr make_shared(); +``` +:: +``` +template + shared_ptr allocate_shared(const A& a); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is an array type of the form `__U__[__N__]`. +Returns::: A `shared_ptr` to a sequence of `_N_` value-initialized objects of +type `_U_`. + +[subs=+quotes] +``` +template + shared_ptr make_shared(std::size_t n, _see below_ v); +``` +:: +[subs=+quotes] +``` +template + shared_ptr allocate_shared(const A& a, std::size_t n, _see below_ v); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is an array type of the form `__U__[]`. +Returns::: A `shared_ptr` to a sequence of `n` objects of type `_U_`, each +initialized to `v`. + +[subs=+quotes] +``` +template + shared_ptr make_shared(_see below_ v); +``` +:: +[subs=+quotes] +``` +template + shared_ptr allocate_shared(const A& a, _see below_ v); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is an array type of the form `__U__[__N__]`. +Returns::: A `shared_ptr` to a sequence of `_N_` objects of type `_U_`, each +initialized to `v`. + +``` +template + shared_ptr make_shared_noinit(); +``` +:: +``` +template + shared_ptr allocate_shared_noinit(const A& a); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is not an array type, or an array type of the `__U__[__N__]`. +Returns::: A `shared_ptr` to a default-initialized object of type `T`, or a +sequence of `_N_` default-initialized objects of type `_U_`, respectively. + +``` +template + shared_ptr make_shared_noinit(std::size_t n); +``` +:: +``` +template + shared_ptr allocate_shared_noinit(const A& a, std::size_t n); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is an array type of the form `__U__[]`. +Returns::: A `shared_ptr` to a sequence of `_n_` default-initialized objects +of type `_U_`. From bdcab9df474fde3f7bf7ae248881bb8be69e835a Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 14 Jun 2017 01:20:58 -0400 Subject: [PATCH 16/26] Add examples to make_shared documentation --- doc/smart_ptr/make_shared.adoc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc index 22522e8..350b8b5 100644 --- a/doc/smart_ptr/make_shared.adoc +++ b/doc/smart_ptr/make_shared.adoc @@ -175,6 +175,9 @@ Remarks::: These overloads shall only participate in overload resolution when `T` is not an array type. Returns::: A `shared_ptr` to an object of type `T`, constructed from `args$$...$$`. +Examples::: +* `auto p = make_shared();` +* `auto p = make_shared >(16, 1);` ``` template @@ -190,6 +193,9 @@ Remarks::: These overloads shall only participate in overload resolution when `T` is an array type of the form `__U__[]`. Returns::: A `shared_ptr` to a sequence of `n` value-initialized objects of type `_U_`. +Examples::: +* `auto p = make_shared(1024);` +* `auto p = make_shared(6);` ``` template @@ -205,6 +211,9 @@ Remarks::: These overloads shall only participate in overload resolution when `T` is an array type of the form `__U__[__N__]`. Returns::: A `shared_ptr` to a sequence of `_N_` value-initialized objects of type `_U_`. +Examples::: +* `auto p = make_shared();` +* `auto p = make_shared();` [subs=+quotes] ``` @@ -222,6 +231,10 @@ Remarks::: These overloads shall only participate in overload resolution when `T` is an array type of the form `__U__[]`. Returns::: A `shared_ptr` to a sequence of `n` objects of type `_U_`, each initialized to `v`. +Examples::: +* `auto p = make_shared(1024, 1.0);` +* `auto p = make_shared(6, {1.0, 0.0});` +* `auto p = make_shared[]>(4, {1, 2});` [subs=+quotes] ``` @@ -239,6 +252,10 @@ Remarks::: These overloads shall only participate in overload resolution when `T` is an array type of the form `__U__[__N__]`. Returns::: A `shared_ptr` to a sequence of `_N_` objects of type `_U_`, each initialized to `v`. +Examples::: +* `auto p = make_shared(1.0);` +* `auto p = make_shared({1.0, 0.0});` +* `auto p = make_shared[4]>({1, 2});` ``` template @@ -254,6 +271,10 @@ Remarks::: These overloads shall only participate in overload resolution when `T` is not an array type, or an array type of the `__U__[__N__]`. Returns::: A `shared_ptr` to a default-initialized object of type `T`, or a sequence of `_N_` default-initialized objects of type `_U_`, respectively. +Examples::: +* `struct X { double data[1024]; }; + + auto p = make_shared_noinit();` +* `auto p = make_shared_noinit();` ``` template @@ -269,3 +290,4 @@ Remarks::: These overloads shall only participate in overload resolution when `T` is an array type of the form `__U__[]`. Returns::: A `shared_ptr` to a sequence of `_n_` default-initialized objects of type `_U_`. +Example::: `auto p = make_shared_noinit(1024);` \ No newline at end of file From 8096b7d3242c94292915df517cf75b8a041d9c17 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 14 Jun 2017 08:24:31 -0400 Subject: [PATCH 17/26] Add make_unique documentation --- doc/smart_ptr/make_shared.adoc | 5 +- doc/smart_ptr/make_unique.adoc | 98 ++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 4 deletions(-) diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc index 350b8b5..662a05c 100644 --- a/doc/smart_ptr/make_shared.adoc +++ b/doc/smart_ptr/make_shared.adoc @@ -271,10 +271,7 @@ Remarks::: These overloads shall only participate in overload resolution when `T` is not an array type, or an array type of the `__U__[__N__]`. Returns::: A `shared_ptr` to a default-initialized object of type `T`, or a sequence of `_N_` default-initialized objects of type `_U_`, respectively. -Examples::: -* `struct X { double data[1024]; }; + - auto p = make_shared_noinit();` -* `auto p = make_shared_noinit();` +Example::: `auto p = make_shared_noinit();` ``` template diff --git a/doc/smart_ptr/make_unique.adoc b/doc/smart_ptr/make_unique.adoc index 5caf392..13d247c 100644 --- a/doc/smart_ptr/make_unique.adoc +++ b/doc/smart_ptr/make_unique.adoc @@ -1,5 +1,6 @@ //// Copyright 2017 Peter Dimov +Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. @@ -13,3 +14,100 @@ http://www.boost.org/LICENSE_1_0.txt :toc-title: :idprefix: make_unique_ +## Description + +The `make_unique` function templates provide convenient and safe ways to +create `std::unique_ptr` objects. + +## Rationale + +The C$$++$$11 standard introduced `std::unique_ptr` but did not provide any +`make_unique` utility like `std::make_shared` that provided the same +exception safety and facility to avoid writing `new` expressions. Before it +was implemented by some standard library vendors (and prior to the C$$++$$14 +standard introducing `std::make_unique`), this library provided it due to +requests from users. + +This library also provides additional overloads of `make_unique` for +default-initialization, when users do not need or want to incur the expense +of value-initialization. The C$$++$$ standard does not yet provide this +feature with `std::make_unique`. + +## Synopsis + +`make_unique` is defined in ``. + +[subs=+quotes] +``` +namespace boost { + template + std::unique_ptr make_unique(Args&&... args); + + template + std::unique_ptr make_unique(_see below_ v); + + template + std::unique_ptr make_shared(std::size_t n); + + template + std::unique_ptr make_shared_noinit(); + + template + std::unique_ptr make_shared_noinit(std::size_t n); +} +``` + +## Free Functions + +``` +template + std::unique_ptr make_unique(Args&&... args); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is not an array type. +Returns::: `std::unique_ptr(new T(std::forward(args)$$...$$)`. +Example::: `auto p = make_unique();` + +[subs=+quotes] +``` +template + std::unique_ptr make_unique(_see below_ v); +``` +:: +Remarks::: +* These overloads shall only participate in overload resolution when `T` is +not an array type. +* The type of `v` is `std::remove_reference_t&&`. +Returns::: `std::unique_ptr(new T(std::move(v))`. +Example::: `auto p = make_unique >({1, 2});` + +``` +template + std::unique_ptr make_unique(std::size_t n); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is an array type of the form `__U__[]`. +Returns::: `std::unique_ptr<__U__[]>(new __U__[n]())`. +Example::: `auto p = make_unique(1024);` + +``` +template + std::unique_ptr make_unique_noinit(); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is not an array type. +Returns::: `std::unique_ptr(new T)`. +Example::: `auto p = make_unique_noinit();` + +``` +template + std::unique_ptr make_unique_noinit(std::size_t n); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is an array type of the form `__U__[]`. +Returns::: `std::unique_ptr<__U__[]>(new __U__[n])`. +Example::: `auto p = make_unique_noinit(1024);` \ No newline at end of file From c1820b4a2758f249486c7cd4dca538edf0d1cb0c Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 14 Jun 2017 10:27:46 -0400 Subject: [PATCH 18/26] Various documentation fixes --- doc/smart_ptr/make_shared.adoc | 98 +++++++++++++++++++--------------- doc/smart_ptr/make_unique.adoc | 23 ++++---- 2 files changed, 68 insertions(+), 53 deletions(-) diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc index 662a05c..dc2d688 100644 --- a/doc/smart_ptr/make_shared.adoc +++ b/doc/smart_ptr/make_shared.adoc @@ -55,36 +55,43 @@ types. [subs=+quotes] ``` namespace boost { + // only if T is not an array type template shared_ptr make_shared(Args&&... args); template shared_ptr allocate_shared(const A& a, Args&&... args); + // only if T is an array type of the form U[] template shared_ptr make_shared(std::size_t n); template shared_ptr allocate_shared(const A& a, std::size_t n); + // only if T is an array type of the form U[N] template shared_ptr make_shared(); template shared_ptr allocate_shared(const A& a); + // only if T is an array type of the form U[] template shared_ptr make_shared(std::size_t n, _see below_ v); template shared_ptr allocate_shared(const A& a, std::size_t n, _see below_ v); + // only if T is an array type of the form U[N] template shared_ptr make_shared(_see below_ v); template shared_ptr allocate_shared(const A& a, _see below_ v); + // only if T is not an array type of the form U[] template shared_ptr make_shared_noinit(); template shared_ptr allocate_shared_noinit(const A& a); + // only if T is an array type of the form U[N] template shared_ptr make_shared_noinit(std::size_t n); template @@ -92,7 +99,7 @@ namespace boost { } ``` -## Free Functions +## Common Requirements The common requirements that apply to all `make_shared` and `allocate_shared` overloads, unless specified otherwise, are described below. @@ -100,8 +107,8 @@ overloads, unless specified otherwise, are described below. Requires:: `A` shall be an _allocator_. The copy constructor and destructor of `A` shall not throw exceptions. -Effects:: Allocates memory for an object of type `T` or `n` objects of `_U_` -(if `T` is an array type of the form `__U__[]` and `n` is determined by +Effects:: Allocates memory for an object of type `T` or `n` objects of `U` +(if `T` is an array type of the form `U[]` and `n` is determined by arguments, as specified by the concrete overload). The object is initialized from arguments as specified by the concrete overload. Uses a rebound copy of `a` (for an unspecified `value_type`) to allocate memory. If an exception is @@ -110,48 +117,49 @@ thrown, the functions have no effect. Returns:: A `shared_ptr` instance that stores and owns the address of the newly constructed object. -Postconditions:: `__r__.get() != 0` and `__r__.use_count() == 1`, where `_r_` +Postconditions:: `r.get() != 0` and `r.use_count() == 1`, where `r` is the return value. -Throws:: An exception thrown from `A::allocate`, or from the initialization -of the object. +Throws:: `std::bad_alloc`, an exception thrown from `A::allocate`, or from the +initialization of the object. Remarks:: * Performs no more than one memory allocation. This provides efficiency equivalent to an intrusive smart pointer. +* The type of `v` is equivalent to `const std::remove_extent_t&`. * When an object of an array type is specified to be initialized to a value of the same type `v`, this shall be interpreted to mean that each array element of the object is initialized to the corresponding element from `v`. * When an object of an array type is specified to be value-initialized, this shall be interpreted to mean that each array element of the object is value-initialized. -* When a (sub)object of non-array type `_U_` is specified to be initialized to +* When a (sub)object of non-array type `U` is specified to be initialized to a value `v`, or constructed from `args$$...$$`, `make_shared` shall perform -this initialization via the expression `::new(__p__) __U__(__expr__)` (where -`_expr_` is `v` or `std::forward(args)$$...$$)` respectively) and `_p_` +this initialization via the expression `::new(p) U(expr)` (where +`_expr_` is `v` or `std::forward(args)$$...$$)` respectively) and `p` has type `void*` and points to storage suitable to hold an object of type -`_U_`. -* When a (sub)object of non-array type `_U_` is specified to be initialized to +`U`. +* When a (sub)object of non-array type `U` is specified to be initialized to a value `v`, or constructed from `args$$...$$`, `allocate_shared` shall perform this initialization via the expression -`std::allocator_traits<__A2__>::construct(__a2__, __p__, __expr__)` (where -`_expr_` is `v` or `std::forward(args)$$...$$)` respectively), `_p_` -points to storage suitable to hold an object of type `_U_`, and `_a2_` of -type `_A2_` is a rebound copy `a` such that its `value_type` is `_U_`. -* When a (sub)object of non-array type `_U_` is specified to be +`std::allocator_traits::construct(a2, p, expr)` (where +`_expr_` is `v` or `std::forward(args)$$...$$)` respectively), `p` +points to storage suitable to hold an object of type `U`, and `a2` of +type `A2` is a rebound copy `a` such that its `value_type` is `U`. +* When a (sub)object of non-array type `U` is specified to be default-initialized, `make_shared_noinit` and `allocate_shared_noinit` shall -perform this initialization via the expression `::new(__p__) __U__`, where -`_p_` has type `void*` and points to storage suitable to hold an object of -type `_U_`. -* When a (sub)object of non-array type `_U_` is specified to be +perform this initialization via the expression `::new(p) U`, where +`p` has type `void*` and points to storage suitable to hold an object of +type `U`. +* When a (sub)object of non-array type `U` is specified to be value-initialized, `make_shared` shall perform this initialization via the -expression `::new(__p__) __U__()`, where `_p_` has type `void*` and points to -storage suitable to hold an object of type `_U_`. -* When a (sub)object of non-array type `_U_` is specified to be +expression `::new(p) U()`, where `p` has type `void*` and points to +storage suitable to hold an object of type `U`. +* When a (sub)object of non-array type `U` is specified to be value-initialized, `allocate_shared` shall perform this initialization via the -expression `std::allocator_traits<__A2__>::construct(__a2__, __p__)`, where -`p` points to storage suitable to hold an object of type `_U_` and `_a2_` of -type `_A2_` is a rebound copy of `a` such that its value_type is `_U_`. +expression `std::allocator_traits::construct(a2, p)`, where +`p` points to storage suitable to hold an object of type `U` and `a2` of +type `A2` is a rebound copy of `a` such that its value_type is `U`. * Array elements are initialized in ascending order of their addresses. * When the lifetime of the object managed by the return value ends, or when the initialization of an array element throws an exception, the initialized @@ -161,6 +169,8 @@ NOTE: These functions will typically allocate more memory than the total size of the element objects to allow for internal bookkeeping structures such as the reference counts. +## Free Functions + ``` template shared_ptr make_shared(Args&&... args); @@ -190,9 +200,9 @@ template ``` :: Remarks::: These overloads shall only participate in overload resolution when -`T` is an array type of the form `__U__[]`. +`T` is an array type of the form `U[]`. Returns::: A `shared_ptr` to a sequence of `n` value-initialized objects of -type `_U_`. +type `U`. Examples::: * `auto p = make_shared(1024);` * `auto p = make_shared(6);` @@ -208,9 +218,9 @@ template ``` :: Remarks::: These overloads shall only participate in overload resolution when -`T` is an array type of the form `__U__[__N__]`. -Returns::: A `shared_ptr` to a sequence of `_N_` value-initialized objects of -type `_U_`. +`T` is an array type of the form `U[N]`. +Returns::: A `shared_ptr` to a sequence of `N` value-initialized objects of +type `U`. Examples::: * `auto p = make_shared();` * `auto p = make_shared();` @@ -218,18 +228,18 @@ Examples::: [subs=+quotes] ``` template - shared_ptr make_shared(std::size_t n, _see below_ v); + shared_ptr make_shared(std::size_t n, _see above_ v); ``` :: [subs=+quotes] ``` template - shared_ptr allocate_shared(const A& a, std::size_t n, _see below_ v); + shared_ptr allocate_shared(const A& a, std::size_t n, _see above_ v); ``` :: Remarks::: These overloads shall only participate in overload resolution when -`T` is an array type of the form `__U__[]`. -Returns::: A `shared_ptr` to a sequence of `n` objects of type `_U_`, each +`T` is an array type of the form `U[]`. +Returns::: A `shared_ptr` to a sequence of `n` objects of type `U`, each initialized to `v`. Examples::: * `auto p = make_shared(1024, 1.0);` @@ -239,18 +249,18 @@ Examples::: [subs=+quotes] ``` template - shared_ptr make_shared(_see below_ v); + shared_ptr make_shared(_see above_ v); ``` :: [subs=+quotes] ``` template - shared_ptr allocate_shared(const A& a, _see below_ v); + shared_ptr allocate_shared(const A& a, _see above_ v); ``` :: Remarks::: These overloads shall only participate in overload resolution when -`T` is an array type of the form `__U__[__N__]`. -Returns::: A `shared_ptr` to a sequence of `_N_` objects of type `_U_`, each +`T` is an array type of the form `U[N]`. +Returns::: A `shared_ptr` to a sequence of `N` objects of type `U`, each initialized to `v`. Examples::: * `auto p = make_shared(1.0);` @@ -268,9 +278,9 @@ template ``` :: Remarks::: These overloads shall only participate in overload resolution when -`T` is not an array type, or an array type of the `__U__[__N__]`. +`T` is not an array type, or an array type of the `U[N]`. Returns::: A `shared_ptr` to a default-initialized object of type `T`, or a -sequence of `_N_` default-initialized objects of type `_U_`, respectively. +sequence of `N` default-initialized objects of type `U`, respectively. Example::: `auto p = make_shared_noinit();` ``` @@ -284,7 +294,7 @@ template ``` :: Remarks::: These overloads shall only participate in overload resolution when -`T` is an array type of the form `__U__[]`. +`T` is an array type of the form `U[]`. Returns::: A `shared_ptr` to a sequence of `_n_` default-initialized objects -of type `_U_`. -Example::: `auto p = make_shared_noinit(1024);` \ No newline at end of file +of type `U`. +Example::: `auto p = make_shared_noinit(1024);` diff --git a/doc/smart_ptr/make_unique.adoc b/doc/smart_ptr/make_unique.adoc index 13d247c..048f9c6 100644 --- a/doc/smart_ptr/make_unique.adoc +++ b/doc/smart_ptr/make_unique.adoc @@ -40,20 +40,25 @@ feature with `std::make_unique`. [subs=+quotes] ``` namespace boost { + // only if T is not an array type template std::unique_ptr make_unique(Args&&... args); + // only if T is not an array type template std::unique_ptr make_unique(_see below_ v); + // only if T is an array type of the form U[] template - std::unique_ptr make_shared(std::size_t n); + std::unique_ptr make_unique(std::size_t n); + // only if T is not an array type template - std::unique_ptr make_shared_noinit(); + std::unique_ptr make_unique_noinit(); + // only if T is an array type of the form U[] template - std::unique_ptr make_shared_noinit(std::size_t n); + std::unique_ptr make_unique_noinit(std::size_t n); } ``` @@ -78,7 +83,7 @@ template Remarks::: * These overloads shall only participate in overload resolution when `T` is not an array type. -* The type of `v` is `std::remove_reference_t&&`. +* The type of `v` is equivalent to `std::remove_reference_t&&`. Returns::: `std::unique_ptr(new T(std::move(v))`. Example::: `auto p = make_unique >({1, 2});` @@ -88,8 +93,8 @@ template ``` :: Remarks::: These overloads shall only participate in overload resolution when -`T` is an array type of the form `__U__[]`. -Returns::: `std::unique_ptr<__U__[]>(new __U__[n]())`. +`T` is an array type of the form `U[]`. +Returns::: `std::unique_ptr(new U[n]())`. Example::: `auto p = make_unique(1024);` ``` @@ -108,6 +113,6 @@ template ``` :: Remarks::: These overloads shall only participate in overload resolution when -`T` is an array type of the form `__U__[]`. -Returns::: `std::unique_ptr<__U__[]>(new __U__[n])`. -Example::: `auto p = make_unique_noinit(1024);` \ No newline at end of file +`T` is an array type of the form `U[]`. +Returns::: `std::unique_ptr(new U[n])`. +Example::: `auto p = make_unique_noinit(1024);` From 074882976f0e1b55c2ae747e168b185d416d6414 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 14 Jun 2017 11:28:09 -0400 Subject: [PATCH 19/26] Slightly better looking comments in documentation --- doc/smart_ptr/make_shared.adoc | 14 +++++++------- doc/smart_ptr/make_unique.adoc | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc index dc2d688..af59deb 100644 --- a/doc/smart_ptr/make_shared.adoc +++ b/doc/smart_ptr/make_shared.adoc @@ -55,43 +55,43 @@ types. [subs=+quotes] ``` namespace boost { - // only if T is not an array type + `// only if T is not an array type` template shared_ptr make_shared(Args&&... args); template shared_ptr allocate_shared(const A& a, Args&&... args); - // only if T is an array type of the form U[] + `// only if T is an array type of the form U[]` template shared_ptr make_shared(std::size_t n); template shared_ptr allocate_shared(const A& a, std::size_t n); - // only if T is an array type of the form U[N] + `// only if T is an array type of the form U[N]` template shared_ptr make_shared(); template shared_ptr allocate_shared(const A& a); - // only if T is an array type of the form U[] + `// only if T is an array type of the form U[]` template shared_ptr make_shared(std::size_t n, _see below_ v); template shared_ptr allocate_shared(const A& a, std::size_t n, _see below_ v); - // only if T is an array type of the form U[N] + `// only if T is an array type of the form U[N]` template shared_ptr make_shared(_see below_ v); template shared_ptr allocate_shared(const A& a, _see below_ v); - // only if T is not an array type of the form U[] + `// only if T is not an array type of the form U[]` template shared_ptr make_shared_noinit(); template shared_ptr allocate_shared_noinit(const A& a); - // only if T is an array type of the form U[N] + `// only if T is an array type of the form U[N]` template shared_ptr make_shared_noinit(std::size_t n); template diff --git a/doc/smart_ptr/make_unique.adoc b/doc/smart_ptr/make_unique.adoc index 048f9c6..30b7137 100644 --- a/doc/smart_ptr/make_unique.adoc +++ b/doc/smart_ptr/make_unique.adoc @@ -40,23 +40,23 @@ feature with `std::make_unique`. [subs=+quotes] ``` namespace boost { - // only if T is not an array type + `// only if T is not an array type` template std::unique_ptr make_unique(Args&&... args); - // only if T is not an array type + `// only if T is not an array type` template std::unique_ptr make_unique(_see below_ v); - // only if T is an array type of the form U[] + `// only if T is an array type of the form U[]` template std::unique_ptr make_unique(std::size_t n); - // only if T is not an array type + `// only if T is not an array type` template std::unique_ptr make_unique_noinit(); - // only if T is an array type of the form U[] + `// only if T is an array type of the form U[]` template std::unique_ptr make_unique_noinit(std::size_t n); } From 902ca6fdf3cf93af0d01c4066d7297f7ddb0c22f Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 14 Jun 2017 20:39:49 -0400 Subject: [PATCH 20/26] Remove 'see below' in documentation --- doc/smart_ptr/make_shared.adoc | 23 ++++++++++------------- doc/smart_ptr/make_unique.adoc | 6 ++---- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc index af59deb..80afd39 100644 --- a/doc/smart_ptr/make_shared.adoc +++ b/doc/smart_ptr/make_shared.adoc @@ -75,15 +75,16 @@ namespace boost { `// only if T is an array type of the form U[]` template - shared_ptr make_shared(std::size_t n, _see below_ v); + shared_ptr make_shared(std::size_t n, const remove_extent_t& v); template - shared_ptr allocate_shared(const A& a, std::size_t n, _see below_ v); + shared_ptr + allocate_shared(const A& a, std::size_t n, const remove_extent_t& v); `// only if T is an array type of the form U[N]` template - shared_ptr make_shared(_see below_ v); + shared_ptr make_shared(const remove_extent_t& v); template - shared_ptr allocate_shared(const A& a, _see below_ v); + shared_ptr allocate_shared(const A& a, const remove_extent_t& v); `// only if T is not an array type of the form U[]` template @@ -126,7 +127,6 @@ initialization of the object. Remarks:: * Performs no more than one memory allocation. This provides efficiency equivalent to an intrusive smart pointer. -* The type of `v` is equivalent to `const std::remove_extent_t&`. * When an object of an array type is specified to be initialized to a value of the same type `v`, this shall be interpreted to mean that each array element of the object is initialized to the corresponding element from `v`. @@ -225,16 +225,15 @@ Examples::: * `auto p = make_shared();` * `auto p = make_shared();` -[subs=+quotes] ``` template - shared_ptr make_shared(std::size_t n, _see above_ v); + shared_ptr make_shared(std::size_t n, const remove_extent_t& v); ``` :: -[subs=+quotes] ``` template - shared_ptr allocate_shared(const A& a, std::size_t n, _see above_ v); + shared_ptr + allocate_shared(const A& a, std::size_t n, const remove_extent_t& v); ``` :: Remarks::: These overloads shall only participate in overload resolution when @@ -246,16 +245,14 @@ Examples::: * `auto p = make_shared(6, {1.0, 0.0});` * `auto p = make_shared[]>(4, {1, 2});` -[subs=+quotes] ``` template - shared_ptr make_shared(_see above_ v); + shared_ptr make_shared(const remove_extent_t& v); ``` :: -[subs=+quotes] ``` template - shared_ptr allocate_shared(const A& a, _see above_ v); + shared_ptr allocate_shared(const A& a, const remove_extent_t& v); ``` :: Remarks::: These overloads shall only participate in overload resolution when diff --git a/doc/smart_ptr/make_unique.adoc b/doc/smart_ptr/make_unique.adoc index 30b7137..b01da5a 100644 --- a/doc/smart_ptr/make_unique.adoc +++ b/doc/smart_ptr/make_unique.adoc @@ -46,7 +46,7 @@ namespace boost { `// only if T is not an array type` template - std::unique_ptr make_unique(_see below_ v); + std::unique_ptr make_unique(remove_reference_t&& v); `// only if T is an array type of the form U[]` template @@ -74,16 +74,14 @@ Remarks::: These overloads shall only participate in overload resolution when Returns::: `std::unique_ptr(new T(std::forward(args)$$...$$)`. Example::: `auto p = make_unique();` -[subs=+quotes] ``` template - std::unique_ptr make_unique(_see below_ v); + std::unique_ptr make_unique(remove_reference_t&& v); ``` :: Remarks::: * These overloads shall only participate in overload resolution when `T` is not an array type. -* The type of `v` is equivalent to `std::remove_reference_t&&`. Returns::: `std::unique_ptr(new T(std::move(v))`. Example::: `auto p = make_unique >({1, 2});` From 478a819cb5e63b4cf52fdfcebaa746e0079d9ea7 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 15 Jun 2017 01:36:59 -0400 Subject: [PATCH 21/26] Add generic pointer casts documentation --- doc/smart_ptr/make_shared.adoc | 18 ++- doc/smart_ptr/make_unique.adoc | 5 +- doc/smart_ptr/pointer_cast.adoc | 198 ++++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+), 13 deletions(-) diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc index 80afd39..3f69c72 100644 --- a/doc/smart_ptr/make_shared.adoc +++ b/doc/smart_ptr/make_shared.adoc @@ -74,11 +74,10 @@ namespace boost { shared_ptr allocate_shared(const A& a); `// only if T is an array type of the form U[]` - template - shared_ptr make_shared(std::size_t n, const remove_extent_t& v); - template - shared_ptr - allocate_shared(const A& a, std::size_t n, const remove_extent_t& v); + template shared_ptr + make_shared(std::size_t n, const remove_extent_t& v); + template shared_ptr + allocate_shared(const A& a, std::size_t n, const remove_extent_t& v); `// only if T is an array type of the form U[N]` template @@ -226,14 +225,13 @@ Examples::: * `auto p = make_shared();` ``` -template - shared_ptr make_shared(std::size_t n, const remove_extent_t& v); +template shared_ptr + make_shared(std::size_t n, const remove_extent_t& v); ``` :: ``` -template - shared_ptr - allocate_shared(const A& a, std::size_t n, const remove_extent_t& v); +template shared_ptr + allocate_shared(const A& a, std::size_t n, const remove_extent_t& v); ``` :: Remarks::: These overloads shall only participate in overload resolution when diff --git a/doc/smart_ptr/make_unique.adoc b/doc/smart_ptr/make_unique.adoc index b01da5a..f3c413c 100644 --- a/doc/smart_ptr/make_unique.adoc +++ b/doc/smart_ptr/make_unique.adoc @@ -79,9 +79,8 @@ template std::unique_ptr make_unique(remove_reference_t&& v); ``` :: -Remarks::: -* These overloads shall only participate in overload resolution when `T` is -not an array type. +Remarks::: These overloads shall only participate in overload resolution when +`T` is not an array type. Returns::: `std::unique_ptr(new T(std::move(v))`. Example::: `auto p = make_unique >({1, 2});` diff --git a/doc/smart_ptr/pointer_cast.adoc b/doc/smart_ptr/pointer_cast.adoc index cd65e4e..ccae283 100644 --- a/doc/smart_ptr/pointer_cast.adoc +++ b/doc/smart_ptr/pointer_cast.adoc @@ -13,3 +13,201 @@ http://www.boost.org/LICENSE_1_0.txt :toc-title: :idprefix: pointer_cast_ +## Description + +The pointer cast function templates (`static_pointer_cast`, +`dynamic_pointer_cast`, `const_pointer_cast`, and `reinterpret_pointer_cast`) +provide a way to write generic pointer castings for raw pointers, +`std::shared_ptr` and `std::unique_ptr`. + +There is test and example code in +link:../../test/pointer_cast_test.cpp[pointer_cast_test.cpp] + +## Rationale + +Boost smart pointers usually overload those functions to provide a mechanism +to emulate pointers casts. For example, `shared_ptr` implements a static +pointer cast this way: + +``` +template + shared_ptr static_pointer_cast(const shared_ptr& p); +``` + +Pointer cast functions templates are overloads of `static_pointer_cast`, +`dynamic_pointer_cast`, `const_pointer_cast`, and `reinterpret_pointer_cast` +for raw pointers, `std::shared_ptr` and `std::unique_ptr`. This way when +developing pointer type independent classes, for example, memory managers or +shared memory compatible classes, the same code can be used for raw and smart +pointers. + +## Synopsis + +The generic pointer casts are defined in ``. + +``` +namespace boost { + template T* static_pointer_cast(U* p) noexcept; + template T* dynamic_pointer_cast(U* p) noexcept; + template T* const_pointer_cast(U* p) noexcept; + template T* reinterpret_pointer_cast(U* p) noexcept; + + template std::shared_ptr + static_pointer_cast(const std::shared_ptr& p) noexcept; + template std::shared_ptr + dynamic_pointer_cast(const std::shared_ptr& p) noexcept; + template std::shared_ptr + const_pointer_cast(const std::shared_ptr& p) noexcept; + template std::shared_ptr + reinterpret_pointer_cast(const std::shared_ptr& p) noexcept; + + template std::unique_ptr + static_pointer_cast(std::unique_ptr&& p) noexcept; + template std::unique_ptr + dynamic_pointer_cast(std::unique_ptr&& p) noexcept; + template std::unique_ptr + const_pointer_cast(std::unique_ptr&& p) noexcept; + template std::unique_ptr + reinterpret_pointer_cast(std::unique_ptr&& p) noexcept; +} +``` + +## Free Functions + +### static_pointer_cast +``` +template T* static_pointer_cast(U* p) noexcept; +``` +:: +Returns::: `static_cast(p)` + +``` +template std::shared_ptr + static_pointer_cast(const std::shared_ptr& p) noexcept; +``` +:: +Returns::: `std::static_pointer_cast(p)` + +``` +template std::unique_ptr + static_pointer_cast(std::unique_ptr&& p) noexcept; +``` +:: +Requires::: The expression `static_cast((U*)0)` must be well-formed. +Returns::: `std::unique_ptr(static_cast::element_type*>(p.release()))`. + +CAUTION: The seemingly equivalent expression +`std::unique_ptr(static_cast(p.get()))` will eventually result in +undefined behavior, attempting to delete the same object twice. + +### dynamic_pointer_cast + +``` +template T* dynamic_pointer_cast(U* p) noexcept; +``` +:: +Returns::: `dynamic_cast(p)` + +``` +template std::shared_ptr + dynamic_pointer_cast(const std::shared_ptr& p) noexcept; +``` +:: +Returns::: `std::dynamic_pointer_cast(p)` + +``` +template std::unique_ptr + dynamic_pointer_cast(std::unique_ptr&& p) noexcept; +``` +:: +Requires::: +* The expression `static_cast((U*)0)` must be well-formed. +* `T` must have a virtual destructor. +Returns::: +* When `dynamic_cast::element_type*>(p.get())` +returns a non-zero value, `std::unique_ptr(dynamic_cast::element_type*>(p.release()));`. +* Otherwise, `std::unique_ptr()`. + +### const_pointer_cast + +``` +template T* const_pointer_cast(U* p) noexcept; +``` +:: +Returns::: `const_cast(p)` + +``` +template std::shared_ptr + const_pointer_cast(const std::shared_ptr& p) noexcept; +``` +:: +Returns::: `std::const_pointer_cast(p)` + +``` +template std::unique_ptr + const_pointer_cast(std::unique_ptr&& p) noexcept; +``` +:: +Requires::: The expression `const_cast((U*)0)` must be well-formed. +Returns::: `std::unique_ptr(const_cast::element_type*>(p.release()))`. + +### reinterpret_pointer_cast + +``` +template T* reinterpret_pointer_cast(U* p) noexcept; +``` +:: +Returns::: `reinterpret_cast(p)` + +``` +template std::shared_ptr + reinterpret_pointer_cast(const std::shared_ptr& p) noexcept; +``` +:: +Returns::: `std::reinterpret_pointer_cast(p)` + +``` +template std::unique_ptr + reinterpret_pointer_cast(std::unique_ptr&& p) noexcept; +``` +:: +Requires::: The expression `reinterpret_cast((U*)0)` must be well-formed. +Returns::: `std::unique_ptr(reinterpret_cast::element_type*>(p.release()))`. + +## Example + +The following example demonstrates how the generic pointer casts help us +create pointer independent code. + +``` +#include +#include + +class base { +public: + virtual ~base() { } +}; + +class derived : public base { }; + +template +void check_if_it_is_derived(const Ptr& ptr) +{ + assert(boost::dynamic_pointer_cast(ptr) != 0); +} + +int main() +{ + base* ptr = new derived; + boost::shared_ptr sptr(new derived); + + check_if_it_is_derived(ptr); + check_if_it_is_derived(sptr); + + delete ptr; +} +``` \ No newline at end of file From 7f760526abec965e38019485f42cf2520c530deb Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 15 Jun 2017 02:09:06 -0400 Subject: [PATCH 22/26] Add intrusive_ref_counter documentation --- doc/smart_ptr/intrusive_ref_counter.adoc | 96 ++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/doc/smart_ptr/intrusive_ref_counter.adoc b/doc/smart_ptr/intrusive_ref_counter.adoc index 61f9ed6..091f9cd 100644 --- a/doc/smart_ptr/intrusive_ref_counter.adoc +++ b/doc/smart_ptr/intrusive_ref_counter.adoc @@ -1,5 +1,6 @@ //// Copyright 2017 Peter Dimov +Copyright 2013 Andrey Semashev Distributed under the Boost Software License, Version 1.0. @@ -13,3 +14,98 @@ http://www.boost.org/LICENSE_1_0.txt :toc-title: :idprefix: intrusive_ref_counter_ +## Description + +The `intrusive_ref_counter` class template implements a reference counter for +a derived user's class that is intended to be used with `intrusive_ptr`. The +base class has associated `intrusive_ptr_add_ref` and `intrusive_ptr_release` +functions which modify the reference counter as needed and destroy the user's +object when the counter drops to zero. + +The class template is parameterized on `Derived` and `CounterPolicy` +parameters. The first parameter is the user's class that derives from +`intrusive_ref_counter`. This type is needed in order to destroy the object +correctly when there are no references to it left. + +The second parameter is a policy that defines the nature of the reference +counter. The library provides two such policies: `thread_unsafe_counter` and +`thread_safe_counter`. The former instructs the `intrusive_ref_counter` base +class to use a counter only suitable for a single-threaded use. Pointers to a +single object that uses this kind of reference counter must not be used in +different threads. The latter policy makes the reference counter thread-safe, +unless the target platform doesn't support threading. Since in modern systems +support for threading is common, the default counter policy is +`thread_safe_counter`. + +## Synopsis + +`intrusive_ref_counter` is defined in +``. + +``` +namespace boost { + struct thread_unsafe_counter; + struct thread_safe_counter; + + template + class intrusive_ref_counter { + public: + intrusive_ref_counter() noexcept; + intrusive_ref_counter(const intrusive_ref_counter& v) noexcept; + + intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept; + + unsigned int use_count() const noexcept; + + protected: + ~intrusive_ref_counter() = default; + }; +} +``` + +## Members + +### Constructors + +``` +intrusive_ref_counter() noexcept; +``` +:: +``` +intrusive_ref_counter(const intrusive_ref_counter&) noexcept; +``` +:: +Postconditions::: `use_count() == 0`. + +NOTE: The pointer to the constructed object is expected to be passed to +`intrusive_ptr` constructor, assignment operator or `reset` method, which +would increment the reference counter. + +### Destructor + +``` +~intrusive_ref_counter(); +``` +:: +Effects::: Destroys the counter object. + +NOTE: The destructor is protected so that the object can only be destroyed +through the `Derived` class. + +### Assignment + +``` +intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept; +``` +:: +Effects::: Does nothing, reference counter is not modified. + +### use_count + +``` +unsigned int use_count() const noexcept; +``` +:: +Returns::: The current value of the reference counter. + +NOTE: The returned value may not be actual in multi-threaded applications. From 61de342adc5b89b2c86d228b1cbb0adeb9fb6cdc Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 15 Jun 2017 08:16:50 -0400 Subject: [PATCH 23/26] Add deprecated shared_array documentation --- doc/smart_ptr/make_shared.adoc | 10 +- doc/smart_ptr/make_unique.adoc | 8 +- doc/smart_ptr/shared_array.adoc | 249 ++++++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+), 9 deletions(-) diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc index 3f69c72..5b4366c 100644 --- a/doc/smart_ptr/make_shared.adoc +++ b/doc/smart_ptr/make_shared.adoc @@ -133,16 +133,16 @@ of the object is initialized to the corresponding element from `v`. shall be interpreted to mean that each array element of the object is value-initialized. * When a (sub)object of non-array type `U` is specified to be initialized to -a value `v`, or constructed from `args$$...$$`, `make_shared` shall perform +a value `v`, or constructed from `args\...`, `make_shared` shall perform this initialization via the expression `::new(p) U(expr)` (where -`_expr_` is `v` or `std::forward(args)$$...$$)` respectively) and `p` +`_expr_` is `v` or `std::forward(args)\...)` respectively) and `p` has type `void*` and points to storage suitable to hold an object of type `U`. * When a (sub)object of non-array type `U` is specified to be initialized to -a value `v`, or constructed from `args$$...$$`, `allocate_shared` shall +a value `v`, or constructed from `args\...`, `allocate_shared` shall perform this initialization via the expression `std::allocator_traits::construct(a2, p, expr)` (where -`_expr_` is `v` or `std::forward(args)$$...$$)` respectively), `p` +`_expr_` is `v` or `std::forward(args)\...)` respectively), `p` points to storage suitable to hold an object of type `U`, and `a2` of type `A2` is a rebound copy `a` such that its `value_type` is `U`. * When a (sub)object of non-array type `U` is specified to be @@ -183,7 +183,7 @@ template Remarks::: These overloads shall only participate in overload resolution when `T` is not an array type. Returns::: A `shared_ptr` to an object of type `T`, constructed from -`args$$...$$`. +`args\...`. Examples::: * `auto p = make_shared();` * `auto p = make_shared >(16, 1);` diff --git a/doc/smart_ptr/make_unique.adoc b/doc/smart_ptr/make_unique.adoc index f3c413c..b4e94bf 100644 --- a/doc/smart_ptr/make_unique.adoc +++ b/doc/smart_ptr/make_unique.adoc @@ -21,16 +21,16 @@ create `std::unique_ptr` objects. ## Rationale -The C$$++$$11 standard introduced `std::unique_ptr` but did not provide any +The {cpp}11 standard introduced `std::unique_ptr` but did not provide any `make_unique` utility like `std::make_shared` that provided the same exception safety and facility to avoid writing `new` expressions. Before it -was implemented by some standard library vendors (and prior to the C$$++$$14 +was implemented by some standard library vendors (and prior to the {cpp}14 standard introducing `std::make_unique`), this library provided it due to requests from users. This library also provides additional overloads of `make_unique` for default-initialization, when users do not need or want to incur the expense -of value-initialization. The C$$++$$ standard does not yet provide this +of value-initialization. The {cpp} standard does not yet provide this feature with `std::make_unique`. ## Synopsis @@ -71,7 +71,7 @@ template :: Remarks::: These overloads shall only participate in overload resolution when `T` is not an array type. -Returns::: `std::unique_ptr(new T(std::forward(args)$$...$$)`. +Returns::: `std::unique_ptr(new T(std::forward(args)\...)`. Example::: `auto p = make_unique();` ``` diff --git a/doc/smart_ptr/shared_array.adoc b/doc/smart_ptr/shared_array.adoc index aa2933f..e1da95c 100644 --- a/doc/smart_ptr/shared_array.adoc +++ b/doc/smart_ptr/shared_array.adoc @@ -14,3 +14,252 @@ http://www.boost.org/LICENSE_1_0.txt :toc-title: :idprefix: shared_array_ +NOTE: This facility is deprecated because a `shared_ptr` to `T[]` or `T[N]` +is now available, and is superior in every regard. + +## Description + +The `shared_array` class template stores a pointer to a dynamically allocated +array. (Dynamically allocated array are allocated with the C++ `new[]` +expression.) The object pointed to is guaranteed to be deleted when the last +`shared_array` pointing to it is destroyed or reset. + +Every `shared_array` meets the _CopyConstructible_ and _Assignable_ +requirements of the {cpp} Standard Library, and so can be used in standard +library containers. Comparison operators are supplied so that shared_array +works with the standard library's associative containers. + +Normally, a `shared_array` cannot correctly hold a pointer to an object that +has been allocated with the non-array form of `new`. See `shared_ptr` for that +usage. + +Because the implementation uses reference counting, cycles of `shared_array` +instances will not be reclaimed. For example, if `main` holds a shared_array +to `A`, which directly or indirectly holds a shared_array back to `A`, the use +count of `A` will be 2. Destruction of the original `shared_array` will leave +`A` dangling with a use count of 1. + +A `shared_ptr` to a `std::vector` is an alternative to a `shared_array` that +is a bit heavier duty but far more flexible. + +The class template is parameterized on `T`, the type of the object pointed to. +`shared_array` 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. + +## Synopsis + +``` +namespace boost { + template class shared_array { + public: + typedef T element_type; + + explicit shared_array(T* p = 0); + template shared_array(T* p, D d); + shared_array(const shared_array& v) noexcept; + + ~shared_array() noexcept; + + shared_array& operator=(const shared_array& v) noexcept; + + void reset(T* p = 0); + template void reset(T* p, D d); + + T& operator[](std::ptrdiff_t n) const noexcept; + T* get() const noexcept; + + bool unique() const noexcept; + long use_count() const noexcept; + + explicit operator bool() const noexcept; + + void swap(shared_array& v) noexcept; + }; + + template bool + operator==(const shared_array& a, const shared_array& b) noexcept; + template bool + operator!=(const shared_array& a, const shared_array& b) noexcept; + template bool + operator<(const shared_array& a, const shared_array& b) noexcept; + + template + void swap(shared_array& a, shared_array& b) noexcept; +} +``` + +## Members + +### element_type + +``` +typedef T element_type; +``` +Type:: Provides the type of the stored pointer. + +### Constructors + +``` +explicit shared_array(T* p = 0); +``` +:: +Effects::: Constructs a `shared_array`, storing a copy of `p`, which must be a +pointer to an array that was allocated via a C++ `new[]` expression or be 0. +Afterwards, the use count is 1 (even if `p == 0`; see `~shared_array`). +Requires::: `T` is a complete type. +Throws::: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called. + +``` +template shared_array(T* p, D d); +``` +:: +Effects::: Constructs a `shared_array`, storing a copy of `p` and of `d`. +Afterwards, the use count is 1. When the the time comes to delete the array +pointed to by `p`, the object `d` is used in the statement `d(p)`. +Requires::: +* `T` is a complete type. +* The copy constructor and destructor of `D` must not throw. +* Invoking the object `d` with parameter `p` must not throw. +Throws::: `std::bad_alloc`. If an exception is thrown, `d(p)` is called. + +``` +shared_array(const shared_array& v) noexcept; +``` +:: +Effects::: Constructs a `shared_array`, as if by storing a copy of the pointer +stored in `v`. Afterwards, the use count for all copies is 1 more than the +initial use count. +Requires::: `T` is a complete type. + +### Destructor + +``` +~shared_array() noexcept; +``` +:: +Effects::: Decrements the use count. Then, if the use count is 0, deletes the +array pointed to by the stored pointer. Note that `delete[]` on a pointer with +a value of 0 is harmless. + +### Assignment + +``` +shared_array& operator=(const shared_array& v) noexcept; +``` +:: +Effects::: Constructs a new `shared_array` as described above, then replaces +this `shared_array` with the new one, destroying the replaced object. +Requires::: `T` is a complete type. +Returns::: `*this`. + +### reset + +``` +void reset(T* p = 0); +``` +:: +Effects::: Constructs a new `shared_array` as described above, then replaces +this `shared_array` with the new one, destroying the replaced object. +Requires::: `T` is a complete type. +Throws::: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called. + +``` +template void reset(T* p, D d); +``` +:: +Effects::: Constructs a new `shared_array` as described above, then replaces +this `shared_array` with the new one, destroying the replaced object. +Requires::: +* `T` is a complete type. +* The copy constructor of `D` must not throw. +Throws::: `std::bad_alloc`. If an exception is thrown, `d(p)` is called. + +### Indexing + +``` +T& operator[](std::ptrdiff_t n) const noexcept; +``` +Returns::: A reference to element `n` of the array pointed to by the stored +pointer. Behavior is undefined and almost certainly undesirable if the stored +pointer is 0, or if `n` is less than 0 or is greater than or equal to the +number of elements in the array. +Requires::: `T` is a complete type. + +### get + +``` +T* get() const noexcept; +``` +:: +Returns::: The stored pointer. + +### unique + +``` +bool unique() const noexcept; +``` +:: +Returns::: `true` if no other `shared_array` is sharing ownership of the +stored pointer, `false` otherwise. + +### use_count + +``` +long use_count() const noexcept; +``` +:: +Returns::: The number of `shared_array` objects sharing ownership of the +stored pointer. + +### Conversions + +``` +explicit operator bool() const noexcept; +``` +:: +Returns::: `get() != 0`. +Requires::: `T` is a complete type. + +### swap + +``` +void swap(shared_array& b) noexcept; +``` +:: +Effects::: Exchanges the contents of the two smart pointers. + +## Free Functions + +### Comparison + +``` +template bool + operator==(const shared_array& a, const shared_array& b) noexcept; +template bool + operator!=(const shared_array& a, const shared_array& b) noexcept; +template bool + operator<(const shared_array& a, const shared_array& b) noexcept; +``` +:: +Returns::: The result of comparing the stored pointers of the two smart +pointers. + +NOTE: The `operator<` overload is provided to define an ordering so that +`shared_array` objects can be used in associative containers such as +`std::map`. The implementation uses `std::less` to perform the comparison. +This ensures that the comparison is handled correctly, since the standard +mandates that relational operations on pointers are unspecified (5.9 +[expr.rel] paragraph 2) but `std::less` on pointers is well-defined (20.3.3 +[lib.comparisons] paragraph 8). + +### swap + +``` +template + void swap(shared_array& a, shared_array& b) noexcept; +``` +:: +Returns::: `a.swap(b)` +Requires::: `T` is a complete type. \ No newline at end of file From 6db55f7dfdf8dc671390dc57b19aa85775806c5b Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 15 Jun 2017 11:33:06 -0400 Subject: [PATCH 24/26] Add _add_ref and _release overload documentation --- doc/smart_ptr/intrusive_ref_counter.adoc | 33 +++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/doc/smart_ptr/intrusive_ref_counter.adoc b/doc/smart_ptr/intrusive_ref_counter.adoc index 091f9cd..1d33300 100644 --- a/doc/smart_ptr/intrusive_ref_counter.adoc +++ b/doc/smart_ptr/intrusive_ref_counter.adoc @@ -60,6 +60,14 @@ namespace boost { protected: ~intrusive_ref_counter() = default; }; + + template + void intrusive_ptr_add_ref( + const intrusive_ref_counter* p) noexcept; + + template + void intrusive_ptr_release( + const intrusive_ref_counter* p) noexcept; } ``` @@ -99,7 +107,7 @@ intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept; ``` :: Effects::: Does nothing, reference counter is not modified. - +y ### use_count ``` @@ -109,3 +117,26 @@ unsigned int use_count() const noexcept; Returns::: The current value of the reference counter. NOTE: The returned value may not be actual in multi-threaded applications. + +## Free Functions + +### intrusive_ptr_add_ref + +``` +template + void intrusive_ptr_add_ref( + const intrusive_ref_counter* p) noexcept; +``` +:: +Effects::: Increments the reference counter. + +### intrusive_ptr_release + +``` +template + void intrusive_ptr_release( + const intrusive_ref_counter* p) noexcept; +``` +:: +Effects::: Decrements the reference counter. If the reference counter reaches +0, calls `delete static_cast(p)`. From 5b817ba04da860f7724e5909d542b031fad5f386 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 15 Jun 2017 21:23:06 +0300 Subject: [PATCH 25/26] Fix synopses --- doc/smart_ptr.adoc | 1 - doc/smart_ptr/enable_shared_from_this.adoc | 15 ++-- doc/smart_ptr/intrusive_ptr.adoc | 96 +++++++++++----------- doc/smart_ptr/pointer_to_other.adoc | 48 ++++++----- doc/smart_ptr/scoped_array.adoc | 25 +++--- doc/smart_ptr/scoped_ptr.adoc | 25 +++--- doc/smart_ptr/shared_array.adoc | 9 +- doc/smart_ptr/shared_ptr.adoc | 71 ++++++++-------- doc/smart_ptr/weak_ptr.adoc | 19 ++--- 9 files changed, 148 insertions(+), 161 deletions(-) diff --git a/doc/smart_ptr.adoc b/doc/smart_ptr.adoc index 361b528..5b452c7 100644 --- a/doc/smart_ptr.adoc +++ b/doc/smart_ptr.adoc @@ -13,7 +13,6 @@ Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes :toclevels: 2 :idprefix: :listing-caption: Code Example -:table-caption: Illustration :docinfo: private-footer :leveloffset: +1 diff --git a/doc/smart_ptr/enable_shared_from_this.adoc b/doc/smart_ptr/enable_shared_from_this.adoc index 77037d3..26dc9fb 100644 --- a/doc/smart_ptr/enable_shared_from_this.adoc +++ b/doc/smart_ptr/enable_shared_from_this.adoc @@ -55,17 +55,15 @@ int main() `enable_shared_from_this` is defined in ``. ``` -namespace boost -{ +namespace boost { -template class enable_shared_from_this -{ -private: + template class enable_shared_from_this { + private: // exposition only weak_ptr weak_this_; -protected: + protected: enable_shared_from_this() = default; ~enable_shared_from_this() = default; @@ -73,16 +71,15 @@ protected: enable_shared_from_this(const enable_shared_from_this&) noexcept; enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; -public: + public: shared_ptr shared_from_this(); shared_ptr shared_from_this() const; weak_ptr weak_from_this() noexcept; weak_ptr weak_from_this() const noexcept; + } } - -} // namespace boost ``` ## Members diff --git a/doc/smart_ptr/intrusive_ptr.adoc b/doc/smart_ptr/intrusive_ptr.adoc index 392f1c3..1c729cd 100644 --- a/doc/smart_ptr/intrusive_ptr.adoc +++ b/doc/smart_ptr/intrusive_ptr.adoc @@ -41,12 +41,10 @@ As a general rule, if it isn't obvious whether `intrusive_ptr` better fits your `intrusive_ptr` is defined in ``. ``` -namespace boost -{ +namespace boost { -template class intrusive_ptr -{ -public: + template class intrusive_ptr { + public: typedef T element_type; @@ -71,50 +69,49 @@ public: T * get() const noexcept; T * detach() noexcept; - operator unspecified-bool-type() const noexcept; + explicit operator bool () const noexcept; void swap(intrusive_ptr & b) noexept; -}; + }; -template -bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; + template + bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; -template -bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; + template + bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; -template -bool operator==(intrusive_ptr const & a, U * b) noexcept; + template + bool operator==(intrusive_ptr const & a, U * b) noexcept; -template -bool operator!=(intrusive_ptr const & a, U * b) noexcept; + template + bool operator!=(intrusive_ptr const & a, U * b) noexcept; -template -bool operator==(T * a, intrusive_ptr const & b) noexcept; + template + bool operator==(T * a, intrusive_ptr const & b) noexcept; -template -bool operator!=(T * a, intrusive_ptr const & b) noexcept; + template + bool operator!=(T * a, intrusive_ptr const & b) noexcept; -template -bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; + template + bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; -template void swap(intrusive_ptr & a, intrusive_ptr & b) noexcept; + template void swap(intrusive_ptr & a, intrusive_ptr & b) noexcept; -template T * get_pointer(intrusive_ptr const & p) noexcept; + template T * get_pointer(intrusive_ptr const & p) noexcept; -template -intrusive_ptr static_pointer_cast(intrusive_ptr const & r) noexcept; + template + intrusive_ptr static_pointer_cast(intrusive_ptr const & r) noexcept; -template -intrusive_ptr const_pointer_cast(intrusive_ptr const & r) noexcept; + template + intrusive_ptr const_pointer_cast(intrusive_ptr const & r) noexcept; -template -intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & r) noexcept; + template + intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & r) noexcept; -template -std::basic_ostream & operator<< (std::basic_ostream & os, - intrusive_ptr const & p); - -} // namespace boost + template + std::basic_ostream & operator<< (std::basic_ostream & os, + intrusive_ptr const & p); +} ``` ## Members @@ -275,17 +272,18 @@ the implications are thoroughly understood. ### conversions ``` -operator unspecified-bool-type () const noexcept; +explicit operator bool () const noexcept; ``` [none] * {blank} + -Returns:: an unspecified value that, when used in boolean contexts, is equivalent to `get() != 0`. +Returns:: `get() != 0`. NOTE: This conversion operator allows `intrusive_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, -avoiding many of the implicit conversion pitfalls. +like `if (p && p\->valid()) {}`. + +NOTE: On C++03 compilers, the return value is of an unspecified type. ### swap @@ -304,7 +302,7 @@ Effects:: Exchanges the contents of the two smart pointers. ``` template -bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; + bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; ``` [none] @@ -314,7 +312,7 @@ Returns:: `a.get() == b.get()`. ``` template -bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; + bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; ``` [none] @@ -324,7 +322,7 @@ Returns:: `a.get() != b.get()`. ``` template -bool operator==(intrusive_ptr const & a, U * b) noexcept; + bool operator==(intrusive_ptr const & a, U * b) noexcept; ``` [none] @@ -334,7 +332,7 @@ Returns:: `a.get() == b`. ``` template -bool operator!=(intrusive_ptr const & a, U * b) noexcept; + bool operator!=(intrusive_ptr const & a, U * b) noexcept; ``` [none] @@ -344,7 +342,7 @@ Returns:: `a.get() != b`. ``` template -bool operator==(T * a, intrusive_ptr const & b) noexcept; + bool operator==(T * a, intrusive_ptr const & b) noexcept; ``` [none] @@ -354,7 +352,7 @@ Returns:: `a == b.get()`. ``` template -bool operator!=(T * a, intrusive_ptr const & b) noexcept; + bool operator!=(T * a, intrusive_ptr const & b) noexcept; ``` [none] @@ -364,7 +362,7 @@ Returns:: `a != b.get()`. ``` template -bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; + bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; ``` [none] @@ -402,7 +400,7 @@ NOTE: Provided as an aid to generic programming. Used by `mem_fn`. ``` template -intrusive_ptr static_pointer_cast(intrusive_ptr const & r) noexcept; + intrusive_ptr static_pointer_cast(intrusive_ptr const & r) noexcept; ``` [none] @@ -414,7 +412,7 @@ Returns:: `intrusive_ptr(static_cast(r.get()))`. ``` template -intrusive_ptr const_pointer_cast(intrusive_ptr const & r) noexcept; + intrusive_ptr const_pointer_cast(intrusive_ptr const & r) noexcept; ``` [none] @@ -426,7 +424,7 @@ Returns:: `intrusive_ptr(const_cast(r.get()))`. ``` template -intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & r) noexcept; + intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & r) noexcept; ``` [none] @@ -438,7 +436,7 @@ Returns:: `intrusive_ptr(dynamic_cast(r.get()))`. ``` template -std::basic_ostream & operator<< (std::basic_ostream & os, + std::basic_ostream & operator<< (std::basic_ostream & os, intrusive_ptr const & p); ``` diff --git a/doc/smart_ptr/pointer_to_other.adoc b/doc/smart_ptr/pointer_to_other.adoc index d8c5a52..d903cad 100644 --- a/doc/smart_ptr/pointer_to_other.adoc +++ b/doc/smart_ptr/pointer_to_other.adoc @@ -44,39 +44,37 @@ template class FloatPointerHolder `pointer_to_other` is defined in ``. ``` -namespace boost -{ +namespace boost { -template struct pointer_to_other; + template struct pointer_to_other; -template class Sp> - struct pointer_to_other< Sp, U > -{ - typedef Sp type; -}; + template class Sp> + struct pointer_to_other< Sp, U > + { + typedef Sp type; + }; -template class Sp> - struct pointer_to_other< Sp, U > -{ + template class Sp> + struct pointer_to_other< Sp, U > + { typedef Sp type; -}; + }; -template class Sp> - struct pointer_to_other< Sp, U > -{ + template class Sp> + struct pointer_to_other< Sp, U > + { typedef Sp type; -}; + }; -template - struct pointer_to_other< T*, U > -{ + template + struct pointer_to_other< T*, U > + { typedef U* type; -}; - -} // namespace boost + }; +} ``` If these definitions are not correct for a specific smart pointer, we can define a specialization of `pointer_to_other`. diff --git a/doc/smart_ptr/scoped_array.adoc b/doc/smart_ptr/scoped_array.adoc index 74aa96e..73d8a6c 100644 --- a/doc/smart_ptr/scoped_array.adoc +++ b/doc/smart_ptr/scoped_array.adoc @@ -46,12 +46,10 @@ The class template is parameterized on `T`, the type of the object pointed to. `scoped_array` is defined in ``. ``` -namespace boost -{ +namespace boost { -template class scoped_array -{ -private: + template class scoped_array { + private: scoped_array(scoped_array const &); scoped_array & operator=(scoped_array const &); @@ -59,7 +57,7 @@ private: void operator==( scoped_array const& ) const; void operator!=( scoped_array const& ) const; -public: + public: typedef T element_type; @@ -74,17 +72,16 @@ public: explicit operator bool () const noexcept; void swap(scoped_array & b) noexcept; -}; + }; -template void swap(scoped_array & a, scoped_array & b) noexcept; + template void swap(scoped_array & a, scoped_array & b) noexcept; -template bool operator==( scoped_array const & p, std::nullptr_t ) noexcept; -template bool operator==( std::nullptr_t, scoped_array const & p ) noexcept; + template bool operator==( scoped_array const & p, std::nullptr_t ) noexcept; + template bool operator==( std::nullptr_t, scoped_array const & p ) noexcept; -template bool operator!=( scoped_array const & p, std::nullptr_t ) noexcept; -template bool operator!=( std::nullptr_t, scoped_array const & p ) noexcept; - -} // namespace boost + template bool operator!=( scoped_array const & p, std::nullptr_t ) noexcept; + template bool operator!=( std::nullptr_t, scoped_array const & p ) noexcept; +} ``` ## Members diff --git a/doc/smart_ptr/scoped_ptr.adoc b/doc/smart_ptr/scoped_ptr.adoc index dcd616c..8c0bef9 100644 --- a/doc/smart_ptr/scoped_ptr.adoc +++ b/doc/smart_ptr/scoped_ptr.adoc @@ -42,12 +42,10 @@ and `T` must be complete at the point `scoped_ptr::~scoped_ptr` is instantiat `scoped_ptr` is defined in ``. ``` -namespace boost -{ +namespace boost { -template class scoped_ptr -{ -private: + template class scoped_ptr { + private: scoped_ptr(scoped_ptr const&); scoped_ptr& operator=(scoped_ptr const&); @@ -55,7 +53,7 @@ private: void operator==(scoped_ptr const&) const; void operator!=(scoped_ptr const&) const; -public: + public: typedef T element_type; @@ -71,17 +69,16 @@ public: explicit operator bool() const noexcept; void swap(scoped_ptr & b) noexcept; -}; + }; -template void swap(scoped_ptr & a, scoped_ptr & b) noexcept; + template void swap(scoped_ptr & a, scoped_ptr & b) noexcept; -template bool operator==( scoped_ptr const & p, std::nullptr_t ) noexcept; -template bool operator==( std::nullptr_t, scoped_ptr const & p ) noexcept; + template bool operator==( scoped_ptr const & p, std::nullptr_t ) noexcept; + template bool operator==( std::nullptr_t, scoped_ptr const & p ) noexcept; -template bool operator!=( scoped_ptr const & p, std::nullptr_t ) noexcept; -template bool operator!=( std::nullptr_t, scoped_ptr const & p ) noexcept; - -} // namespace boost + template bool operator!=( scoped_ptr const & p, std::nullptr_t ) noexcept; + template bool operator!=( std::nullptr_t, scoped_ptr const & p ) noexcept; +} ``` ## Members diff --git a/doc/smart_ptr/shared_array.adoc b/doc/smart_ptr/shared_array.adoc index e1da95c..5be074c 100644 --- a/doc/smart_ptr/shared_array.adoc +++ b/doc/smart_ptr/shared_array.adoc @@ -52,6 +52,7 @@ below. ``` namespace boost { + template class shared_array { public: typedef T element_type; @@ -237,8 +238,12 @@ Effects::: Exchanges the contents of the two smart pointers. ``` template bool operator==(const shared_array& a, const shared_array& b) noexcept; +``` +``` template bool operator!=(const shared_array& a, const shared_array& b) noexcept; +``` +``` template bool operator<(const shared_array& a, const shared_array& b) noexcept; ``` @@ -261,5 +266,5 @@ template void swap(shared_array& a, shared_array& b) noexcept; ``` :: -Returns::: `a.swap(b)` -Requires::: `T` is a complete type. \ No newline at end of file +Returns::: `a.swap(b)`. +Requires::: `T` is a complete type. diff --git a/doc/smart_ptr/shared_ptr.adoc b/doc/smart_ptr/shared_ptr.adoc index 52aa1be..594c740 100644 --- a/doc/smart_ptr/shared_ptr.adoc +++ b/doc/smart_ptr/shared_ptr.adoc @@ -103,16 +103,14 @@ functions defined in ``. These factory function `shared_ptr` is defined in ``. ``` -namespace boost -{ +namespace boost { -class bad_weak_ptr: public std::exception; + class bad_weak_ptr: public std::exception; -template class weak_ptr; + template class weak_ptr; -template class shared_ptr -{ -public: + template class shared_ptr { + public: typedef /*see below*/ element_type; @@ -182,48 +180,47 @@ public: template bool owner_before(shared_ptr const & rhs) const noexcept; template bool owner_before(weak_ptr const & rhs) const noexcept; -}; + }; -template + template bool operator==(shared_ptr const & a, shared_ptr const & b) noexcept; -template + template bool operator!=(shared_ptr const & a, shared_ptr const & b) noexcept; -template + template bool operator<(shared_ptr const & a, shared_ptr const & b) noexcept; -template bool operator==(shared_ptr const & p, std::nullptr_t) noexcept; -template bool operator==(std::nullptr_t, shared_ptr const & p) noexcept; + template bool operator==(shared_ptr const & p, std::nullptr_t) noexcept; + template bool operator==(std::nullptr_t, shared_ptr const & p) noexcept; -template bool operator!=(shared_ptr const & p, std::nullptr_t) noexcept; -template bool operator!=(std::nullptr_t, shared_ptr const & p) noexcept; + template bool operator!=(shared_ptr const & p, std::nullptr_t) noexcept; + template bool operator!=(std::nullptr_t, shared_ptr const & p) noexcept; -template void swap(shared_ptr & a, shared_ptr & b) noexcept; + template void swap(shared_ptr & a, shared_ptr & b) noexcept; -template + template typename shared_ptr::element_type * - get_pointer(shared_ptr const & p) noexcept; + get_pointer(shared_ptr const & p) noexcept; -template + template shared_ptr static_pointer_cast(shared_ptr const & r) noexcept; -template + template shared_ptr const_pointer_cast(shared_ptr const & r) noexcept; -template + template shared_ptr dynamic_pointer_cast(shared_ptr const & r) noexcept; -template + template shared_ptr reinterpret_pointer_cast(shared_ptr const & r) noexcept; -template + template std::basic_ostream & - operator<< (std::basic_ostream & os, shared_ptr const & p); + operator<< (std::basic_ostream & os, shared_ptr const & p); -template D * get_deleter(shared_ptr const & p) noexcept; - -} // namespace boost + template D * get_deleter(shared_ptr const & p) noexcept; +} ``` ## Members @@ -611,6 +608,8 @@ NOTE: This conversion operator allows `shared_ptr` objects to be used in boolean NOTE: The conversion to `bool` is not merely syntactic sugar. It allows `shared_ptr` variables to be declared in conditions when using `dynamic_pointer_cast` or `weak_ptr::lock`. +NOTE: On C++03 compilers, the return value is of an unspecified type. + ### swap ``` void swap(shared_ptr & b) noexcept; @@ -637,7 +636,7 @@ Effects:: See the description of `operator<`. ### comparison ``` template - bool operator==(shared_ptr const & a, shared_ptr const & b) noexcept; + bool operator==(shared_ptr const & a, shared_ptr const & b) noexcept; ``` [none] * {blank} @@ -646,7 +645,7 @@ Returns:: `a.get() == b.get()`. ``` template - bool operator!=(shared_ptr const & a, shared_ptr const & b) noexcept; + bool operator!=(shared_ptr const & a, shared_ptr const & b) noexcept; ``` [none] * {blank} @@ -677,7 +676,7 @@ Returns:: `p.get() != 0`. ``` template - bool operator<(shared_ptr const & a, shared_ptr const & b) noexcept; + bool operator<(shared_ptr const & a, shared_ptr const & b) noexcept; ``` [none] * {blank} @@ -703,7 +702,7 @@ Effects:: Equivalent to `a.swap(b)`. ### get_pointer ``` template - typename shared_ptr::element_type * + typename shared_ptr::element_type * get_pointer(shared_ptr const & p) noexcept; ``` [none] @@ -716,7 +715,7 @@ NOTE: Provided as an aid to generic programming. Used by `mem_fn`. ### static_pointer_cast ``` template - shared_ptr static_pointer_cast(shared_ptr const & r) noexcept; + shared_ptr static_pointer_cast(shared_ptr const & r) noexcept; ``` [none] * {blank} @@ -730,7 +729,7 @@ result in undefined behavior, attempting to delete the same object twice. ### const_pointer_cast ``` template - shared_ptr const_pointer_cast(shared_ptr const & r) noexcept; + shared_ptr const_pointer_cast(shared_ptr const & r) noexcept; ``` [none] * {blank} @@ -754,7 +753,7 @@ Returns:: ### reinterpret_pointer_cast ``` template - shared_ptr reinterpret_pointer_cast(shared_ptr const & r) noexcept; + shared_ptr reinterpret_pointer_cast(shared_ptr const & r) noexcept; ``` [none] * {blank} @@ -765,7 +764,7 @@ Returns:: `shared_ptr( r, reinterpret_cast::element_ty ### operator<< ``` template - std::basic_ostream & + std::basic_ostream & operator<< (std::basic_ostream & os, shared_ptr const & p); ``` [none] @@ -777,7 +776,7 @@ Returns:: `os`. ### get_deleter ``` template - D * get_deleter(shared_ptr const & p) noexcept; + D * get_deleter(shared_ptr const & p) noexcept; ``` [none] * {blank} diff --git a/doc/smart_ptr/weak_ptr.adoc b/doc/smart_ptr/weak_ptr.adoc index b605949..d51eaa1 100644 --- a/doc/smart_ptr/weak_ptr.adoc +++ b/doc/smart_ptr/weak_ptr.adoc @@ -73,12 +73,10 @@ Now `r` holds a reference to the object that was pointed by `q`. Even if `p.rese `weak_ptr` is defined in ``. ``` -namespace boost -{ +namespace boost { -template class weak_ptr -{ -public: + template class weak_ptr { + public: typedef /*see below*/ element_type; @@ -108,14 +106,13 @@ public: template bool owner_before( weak_ptr const & r ) const noexcept; template bool owner_before( shared_ptr const & r ) const noexcept; -}; + }; -template + template bool operator<(weak_ptr const & a, weak_ptr const & b) noexcept; -template void swap(weak_ptr & a, weak_ptr & b) noexcept; - -} // namespace boost + template void swap(weak_ptr & a, weak_ptr & b) noexcept; +} ``` ## Members @@ -250,7 +247,7 @@ Returns:: See the description of `operator<`. ### comparison ``` template - bool operator<(weak_ptr const & a, weak_ptr const & b) noexcept; + bool operator<(weak_ptr const & a, weak_ptr const & b) noexcept; ``` [none] * {blank} From 8812114601d26068aec36a5842bd4d51573ce7ee Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 15 Jun 2017 21:34:53 +0300 Subject: [PATCH 26/26] Fix line wrapping in pdf --- doc/smart_ptr/enable_shared_from_this.adoc | 8 ++++---- doc/smart_ptr/scoped_array.adoc | 24 ++++++++++++++-------- doc/smart_ptr/scoped_ptr.adoc | 12 +++++++---- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/doc/smart_ptr/enable_shared_from_this.adoc b/doc/smart_ptr/enable_shared_from_this.adoc index 26dc9fb..757c1d4 100644 --- a/doc/smart_ptr/enable_shared_from_this.adoc +++ b/doc/smart_ptr/enable_shared_from_this.adoc @@ -105,10 +105,10 @@ Returns:: `*this`. NOTE: `weak_this_` is unchanged. ``` -template shared_ptr enable_shared_from_this::shared_from_this(); +template shared_ptr shared_from_this(); ``` ``` -template shared_ptr enable_shared_from_this::shared_from_this() const; +template shared_ptr shared_from_this() const; ``` [none] * {blank} @@ -133,10 +133,10 @@ the construction of `p` will automatically initialize `p\->weak_this_` to `p`. ==== ``` -template weak_ptr enable_shared_from_this::weak_from_this() noexcept; +template weak_ptr weak_from_this() noexcept; ``` ``` -template weak_ptr enable_shared_from_this::weak_from_this() const noexcept; +template weak_ptr weak_from_this() const noexcept; ``` [none] * {blank} diff --git a/doc/smart_ptr/scoped_array.adoc b/doc/smart_ptr/scoped_array.adoc index 73d8a6c..9746a7c 100644 --- a/doc/smart_ptr/scoped_array.adoc +++ b/doc/smart_ptr/scoped_array.adoc @@ -76,11 +76,15 @@ namespace boost { template void swap(scoped_array & a, scoped_array & b) noexcept; - template bool operator==( scoped_array const & p, std::nullptr_t ) noexcept; - template bool operator==( std::nullptr_t, scoped_array const & p ) noexcept; + template + bool operator==( scoped_array const & p, std::nullptr_t ) noexcept; + template + bool operator==( std::nullptr_t, scoped_array const & p ) noexcept; - template bool operator!=( scoped_array const & p, std::nullptr_t ) noexcept; - template bool operator!=( std::nullptr_t, scoped_array const & p ) noexcept; + template + bool operator!=( scoped_array const & p, std::nullptr_t ) noexcept; + template + bool operator!=( std::nullptr_t, scoped_array const & p ) noexcept; } ``` @@ -154,14 +158,18 @@ Equivalent to `a.swap(b)`. ### comparisons - template bool operator==( scoped_array const & p, std::nullptr_t ) noexcept; + template + bool operator==( scoped_array const & p, std::nullptr_t ) noexcept; - template bool operator==( std::nullptr_t, scoped_array const & p ) noexcept; + template + bool operator==( std::nullptr_t, scoped_array const & p ) noexcept; Returns `p.get() == nullptr`. - template bool operator!=( scoped_array const & p, std::nullptr_t ) noexcept; + template + bool operator!=( scoped_array const & p, std::nullptr_t ) noexcept; - template bool operator!=( std::nullptr_t, scoped_array const & p ) noexcept; + template + bool operator!=( std::nullptr_t, scoped_array const & p ) noexcept; Returns `p.get() != nullptr`. diff --git a/doc/smart_ptr/scoped_ptr.adoc b/doc/smart_ptr/scoped_ptr.adoc index 8c0bef9..4f08811 100644 --- a/doc/smart_ptr/scoped_ptr.adoc +++ b/doc/smart_ptr/scoped_ptr.adoc @@ -73,11 +73,15 @@ namespace boost { template void swap(scoped_ptr & a, scoped_ptr & b) noexcept; - template bool operator==( scoped_ptr const & p, std::nullptr_t ) noexcept; - template bool operator==( std::nullptr_t, scoped_ptr const & p ) noexcept; + template + bool operator==( scoped_ptr const & p, std::nullptr_t ) noexcept; + template + bool operator==( std::nullptr_t, scoped_ptr const & p ) noexcept; - template bool operator!=( scoped_ptr const & p, std::nullptr_t ) noexcept; - template bool operator!=( std::nullptr_t, scoped_ptr const & p ) noexcept; + template + bool operator!=( scoped_ptr const & p, std::nullptr_t ) noexcept; + template + bool operator!=( std::nullptr_t, scoped_ptr const & p ) noexcept; } ```