Squashed 'third_party/boostorg/smart_ptr/' content from commit e37cd41

Change-Id: Ib1d9c588d60cbb7a3bad5a6f8b7e4761af21be72
git-subtree-dir: third_party/boostorg/smart_ptr
git-subtree-split: e37cd4154f492b3cd2ea8e87806614ffddf1163a
diff --git a/doc/smart_ptr/atomic_shared_ptr.adoc b/doc/smart_ptr/atomic_shared_ptr.adoc
new file mode 100644
index 0000000..43c0f85
--- /dev/null
+++ b/doc/smart_ptr/atomic_shared_ptr.adoc
@@ -0,0 +1,170 @@
+////
+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
+////
+
+[#atomic_shared_ptr]
+# atomic_shared_ptr
+:toc:
+:toc-title:
+:idprefix: atomic_shared_ptr_
+
+## Description
+
+The class template `atomic_shared_ptr<T>` implements the interface of `std::atomic`
+for a contained value of type `shared_ptr<T>`. Concurrent access to `atomic_shared_ptr`
+is not a data race.
+
+## Synopsis
+
+`atomic_shared_ptr` is defined in `<boost/smart_ptr/atomic_shared_ptr.hpp>`.
+
+```
+namespace boost {
+
+  template<class T> class atomic_shared_ptr {
+  private:
+
+    shared_ptr<T> p_; // exposition only
+
+    atomic_shared_ptr(const atomic_shared_ptr&) = delete;
+    atomic_shared_ptr& operator=(const atomic_shared_ptr&) = delete;
+
+  public:
+
+    constexpr atomic_shared_ptr() noexcept;
+    atomic_shared_ptr( shared_ptr<T> p ) noexcept;
+
+    atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept;
+
+    bool is_lock_free() const noexcept;
+
+    shared_ptr<T> load( int = 0 ) const noexcept;
+    operator shared_ptr<T>() const noexcept;
+
+    void store( shared_ptr<T> r, int = 0 ) noexcept;
+
+    shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) noexcept;
+
+    bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
+    bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
+    bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
+    bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
+
+    bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
+    bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
+    bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
+    bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
+  };
+}
+```
+
+## Members
+
+```
+constexpr atomic_shared_ptr() noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Default-initializes `p_`.
+
+```
+atomic_shared_ptr( shared_ptr<T> p ) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Initializes `p_` to `p`.
+
+```
+atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: `p_.swap(r)`.
+Returns:: `*this`.
+
+```
+bool is_lock_free() const noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `false`.
+
+NOTE: This implementation is not lock-free.
+
+```
+shared_ptr<T> load( int = 0 ) const noexcept;
+```
+```
+operator shared_ptr<T>() const noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `p_`.
+
+NOTE: The `int` argument is intended to be of type `memory_order`, but is ignored.
+  This implementation is lock-based and therefore always sequentially consistent.
+
+```
+void store( shared_ptr<T> r, int = 0 ) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: `p_.swap(r)`.
+
+```
+shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: `p_.swap(r)`.
+Returns:: The old value of `p_`.
+
+```
+bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
+```
+```
+bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
+```
+```
+bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
+```
+```
+bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: If `p_` is equivalent to `v`, assigns `w` to `p_`, otherwise assigns `p_` to `v`.
+Returns:: `true` if `p_` was equivalent to `v`, `false` otherwise.
+Remarks:: Two `shared_ptr` instances are equivalent if they store the same pointer value and _share ownership_.
+
+```
+bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
+```
+```
+bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
+```
+```
+bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
+```
+```
+bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: If `p_` is equivalent to `v`, assigns `std::move(w)` to `p_`, otherwise assigns `p_` to `v`.
+Returns:: `true` if `p_` was equivalent to `v`, `false` otherwise.
+Remarks:: The old value of `w` is not preserved in either case.
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..757c1d4
--- /dev/null
+++ b/doc/smart_ptr/enable_shared_from_this.adoc
@@ -0,0 +1,144 @@
+////
+Copyright 2002, 2003, 2015, 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: 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<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
+
+`enable_shared_from_this` is defined in `<boost/smart_ptr/enable_shared_from_this.hpp>`.
+
+```
+namespace boost {
+
+  template<class T> class enable_shared_from_this {
+  private:
+
+    // exposition only
+    weak_ptr<T> 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<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;
+  }
+}
+```
+
+## 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<class T> shared_ptr<T> shared_from_this();
+```
+```
+template<class T> shared_ptr<T const> shared_from_this() const;
+```
+[none]
+* {blank}
++
+Returns:: `shared_ptr<T>(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<Y> {};
+
+int main()
+{
+    boost::shared_ptr<Y> p(new Y);
+}
+```
+the construction of `p` will automatically initialize `p\->weak_this_` to `p`.
+====
+
+```
+template<class T> weak_ptr<T> weak_from_this() noexcept;
+```
+```
+template<class T> weak_ptr<T const> weak_from_this() const noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `weak_this_`.
diff --git a/doc/smart_ptr/history.adoc b/doc/smart_ptr/history.adoc
new file mode 100644
index 0000000..914928d
--- /dev/null
+++ b/doc/smart_ptr/history.adoc
@@ -0,0 +1,113 @@
+////
+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
+////
+
+[[history]]
+[appendix]
+# History and Acknowledgments
+:idprefix: history_
+
+## 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`.
+
+## 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.
+
+## 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<T[]>` and `shared_ptr<T[N]>`.
+
+## 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 `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.
+
+## June 2017
+
+Peter Dimov and Glen Fernandes rewrote the documentation in Asciidoc format.
+
+Peter Dimov added `atomic_shared_ptr` and `local_shared_ptr`.
diff --git a/doc/smart_ptr/introduction.adoc b/doc/smart_ptr/introduction.adoc
new file mode 100644
index 0000000..ff51823
--- /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
+: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
+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 six smart pointer class templates:
+
+* `<<scoped_ptr,scoped_ptr>>`, used to contain ownership of a dynamically allocated object to the current scope;
+* `<<scoped_array,scoped_array>>`, which provides scoped ownership for a dynamically allocated array;
+* `<<shared_ptr,shared_ptr>>`, a versatile tool for managing shared ownership of an object or array;
+* `<<weak_ptr,weak_ptr>>`, a non-owning observer to a shared_ptr-managed object that can be promoted temporarily to shared_ptr;
+* `<<intrusive_ptr,intrusive_ptr>>`, a pointer to objects with an embedded reference count;
+* `<<local_shared_ptr,local_shared_ptr>>`, providing shared ownership within a single thread.
+
+`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,make_shared>>`, a factory function for creating objects that returns a `shared_ptr`;
+* `<<make_unique,make_unique>>`, a factory function returning `std::unique_ptr`;
+* `<<enable_shared_from_this,enable_shared_from_this>>`, a helper base class that enables the acquisition of a `shared_ptr` pointing to `this`;
+* `<<pointer_to_other,pointer_to_other>>`, a helper trait for converting one smart pointer type to another;
+* `<<pointer_cast,static_pointer_cast>>` and companions, generic smart pointer casts;
+* `<<intrusive_ref_counter,intrusive_ref_counter>>`, a helper base class containing a reference count.
+* `<<atomic_shared_ptr,atomic_shared_ptr>>`, a helper class implementing the interface of `std::atomic` for a value of type `shared_ptr`.
+
+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..daf6794
--- /dev/null
+++ b/doc/smart_ptr/intrusive_ptr.adoc
@@ -0,0 +1,447 @@
+////
+Copyright 2003-2005, 2013, 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: Managing Objects with Embedded Counts
+:toc:
+:toc-title:
+:idprefix: intrusive_ptr_
+
+## 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
+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 `<<intrusive_ref_counter,intrusive_ref_counter>>` 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<T>` can be implicitly
+converted to `intrusive_ptr<U>` 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<T>` 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
+
+`intrusive_ptr` is defined in `<boost/smart_ptr/intrusive_ptr.hpp>`.
+
+```
+namespace boost {
+
+  template<class T> 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<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
+
+    ~intrusive_ptr();
+
+    intrusive_ptr & operator=(intrusive_ptr const & r);
+    template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> 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;
+
+    explicit operator bool () const noexcept;
+
+    void swap(intrusive_ptr & b) noexept;
+  };
+
+  template<class T, class U>
+    bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
+
+  template<class T, class U>
+    bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
+
+  template<class T, class U>
+    bool operator==(intrusive_ptr<T> const & a, U * b) noexcept;
+
+  template<class T, class U>
+    bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept;
+
+  template<class T, class U>
+    bool operator==(T * a, intrusive_ptr<U> const & b) noexcept;
+
+  template<class T, class U>
+    bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept;
+
+  template<class T, class U>
+    bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
+
+  template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept;
+
+  template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept;
+
+  template<class T, class U>
+    intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept;
+
+  template<class E, class T, class Y>
+    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os,
+      intrusive_ptr<Y> const & p);
+}
+```
+
+## 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<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
+```
+
+[none]
+* {blank}
++
+Effects:: `T * p = r.get(); if(p != 0) intrusive_ptr_add_ref(p);`.
+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<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> 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
+
+```
+explicit operator bool () const noexcept;
+```
+
+[none]
+* {blank}
++
+Returns:: `get() != 0`.
+
+NOTE: This conversion operator allows `intrusive_ptr` objects to be used in boolean contexts,
+like `if (p && p\->valid()) {}`.
+
+NOTE: On C++03 compilers, the return value is of an unspecified type.
+
+### swap
+
+```
+void swap(intrusive_ptr & b) noexcept;
+```
+
+[none]
+* {blank}
++
+Effects:: Exchanges the contents of the two smart pointers.
+
+## Free Functions
+
+### comparison
+
+```
+template<class T, class U>
+  bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
+```
+
+[none]
+* {blank}
++
+Returns:: `a.get() == b.get()`.
+
+```
+template<class T, class U>
+  bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
+```
+
+[none]
+* {blank}
++
+Returns:: `a.get() != b.get()`.
+
+```
+template<class T, class U>
+  bool operator==(intrusive_ptr<T> const & a, U * b) noexcept;
+```
+
+[none]
+* {blank}
++
+Returns:: `a.get() == b`.
+
+```
+template<class T, class U>
+  bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept;
+```
+
+[none]
+* {blank}
++
+Returns:: `a.get() != b`.
+
+```
+template<class T, class U>
+  bool operator==(T * a, intrusive_ptr<U> const & b) noexcept;
+```
+
+[none]
+* {blank}
++
+Returns:: `a == b.get()`.
+
+```
+template<class T, class U>
+  bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept;
+```
+
+[none]
+* {blank}
++
+Returns:: `a != b.get()`.
+
+```
+template<class T, class U>
+  bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
+```
+
+[none]
+* {blank}
++
+Returns:: `std::less<T *>()(a.get(), b.get())`.
+
+NOTE: Allows `intrusive_ptr` objects to be used as keys in associative containers.
+
+### swap
+
+```
+template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept;
+```
+
+[none]
+* {blank}
++
+Effects:: Equivalent to `a.swap(b)`.
+
+### get_pointer
+
+```
+template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept;
+```
+
+[none]
+* {blank}
++
+Returns:: `p.get()`.
+
+NOTE: Provided as an aid to generic programming. Used by `mem_fn`.
+
+### static_pointer_cast
+
+```
+template<class T, class U>
+  intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept;
+```
+
+[none]
+* {blank}
++
+Returns:: `intrusive_ptr<T>(static_cast<T*>(r.get()))`.
+
+### const_pointer_cast
+
+```
+template<class T, class U>
+  intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept;
+```
+
+[none]
+* {blank}
++
+Returns:: `intrusive_ptr<T>(const_cast<T*>(r.get()))`.
+
+### dynamic_pointer_cast
+
+```
+template<class T, class U>
+  intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept;
+```
+
+[none]
+* {blank}
++
+Returns:: `intrusive_ptr<T>(dynamic_cast<T*>(r.get()))`.
+
+### operator<<
+
+```
+template<class E, class T, class Y>
+  std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os,
+    intrusive_ptr<Y> const & p);
+```
+
+[none]
+* {blank}
++
+Effects:: `os << p.get();`.
+Returns:: `os`.
diff --git a/doc/smart_ptr/intrusive_ref_counter.adoc b/doc/smart_ptr/intrusive_ref_counter.adoc
new file mode 100644
index 0000000..32a28a6
--- /dev/null
+++ b/doc/smart_ptr/intrusive_ref_counter.adoc
@@ -0,0 +1,142 @@
+////
+Copyright 2017 Peter Dimov
+Copyright 2013 Andrey Semashev
+
+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: 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
+`<boost/smart_ptr/intrusive_ref_counter.hpp>`.
+
+```
+namespace boost {
+  struct thread_unsafe_counter;
+  struct thread_safe_counter;
+
+  template<class Derived, class CounterPolicy = thread_safe_counter>
+  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;
+  };
+
+  template<class Derived, class CounterPolicy>
+    void intrusive_ptr_add_ref(
+      const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
+
+  template<class Derived, class CounterPolicy>
+    void intrusive_ptr_release(
+      const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
+}
+```
+
+## 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.
+
+## Free Functions
+
+### intrusive_ptr_add_ref
+
+```
+template<class Derived, class CounterPolicy>
+  void intrusive_ptr_add_ref(
+    const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
+```
+::
+Effects::: Increments the reference counter.
+
+### intrusive_ptr_release
+
+```
+template<class Derived, class CounterPolicy>
+  void intrusive_ptr_release(
+    const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
+```
+::
+Effects::: Decrements the reference counter. If the reference counter reaches
+0, calls `delete static_cast<const Derived*>(p)`.
diff --git a/doc/smart_ptr/local_shared_ptr.adoc b/doc/smart_ptr/local_shared_ptr.adoc
new file mode 100644
index 0000000..d7d34dd
--- /dev/null
+++ b/doc/smart_ptr/local_shared_ptr.adoc
@@ -0,0 +1,719 @@
+////
+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
+////
+
+[#local_shared_ptr]
+# local_shared_ptr: Shared Ownership within a Single Thread
+:toc:
+:toc-title:
+:idprefix: local_shared_ptr_
+
+## Description
+
+`local_shared_ptr` is nearly identical to `shared_ptr`, with the only difference of note being that its reference count is
+updated with non-atomic operations. As such, a `local_shared_ptr` and all its copies must reside in (be local to) a single
+thread (hence the name.)
+
+`local_shared_ptr` can be converted to `shared_ptr` and vice versa. Creating a `local_shared_ptr` from a `shared_ptr` creates
+a new local reference count; this means that two `local_shared_ptr` instances, both created from the same `shared_ptr`, refer
+to the same object but don't share the same count, and as such, can safely be used by two different threads.
+
+.Two local_shared_ptr instances created from a shared_ptr
+```
+shared_ptr<X> p1( new X );
+
+local_shared_ptr<X> p2( p1 ); // p2.local_use_count() == 1
+local_shared_ptr<X> p3( p1 ); // p3.local_use_count() also 1
+```
+
+Creating the second `local_shared_ptr` from the first one, however, does lead to the two sharing the same count:
+
+.A local_shared_ptr created from another local_shared_ptr
+```
+shared_ptr<X> p1( new X );
+
+local_shared_ptr<X> p2( p1 ); // p2.local_use_count() == 1
+local_shared_ptr<X> p3( p2 ); // p3.local_use_count() == 2
+```
+
+Two `shared_ptr` instances created from the same `local_shared_ptr` do share ownership:
+
+.Two shared_ptr instances created from a local_shared_ptr
+```
+local_shared_ptr<X> p1( new X );
+
+shared_ptr<X> p2( p1 ); // p2.use_count() == 2
+shared_ptr<X> p3( p1 ); // p3.use_count() == 3
+```
+
+Here `p2.use_count()` is 2, because `p1` holds a reference, too.
+
+One can think of `local_shared_ptr<T>` as `shared_ptr<shared_ptr<T>>`, with the outer `shared_ptr` using non-atomic operations for
+its count. Converting from `local_shared_ptr` to `shared_ptr` gives you a copy of the inner `shared_ptr`; converting from `shared_ptr`
+wraps it into an outer `shared_ptr` with a non-atomic use count (conceptually speaking) and returns the result.
+
+## Synopsis
+
+`local_shared_ptr` is defined in `<boost/smart_ptr/local_shared_ptr.hpp>`.
+
+```
+namespace boost {
+
+  template<class T> class local_shared_ptr {
+  public:
+
+    typedef /*see below*/ element_type;
+
+    // constructors
+
+    constexpr local_shared_ptr() noexcept;
+    constexpr local_shared_ptr(std::nullptr_t) noexcept;
+
+    template<class Y> explicit local_shared_ptr(Y * p);
+
+    template<class Y, class D> local_shared_ptr(Y * p, D d);
+    template<class D> local_shared_ptr(std::nullptr_t p, D d);
+
+    template<class Y, class D, class A> local_shared_ptr(Y * p, D d, A a);
+    template<class D, class A> local_shared_ptr(std::nullptr_t p, D d, A a);
+
+    local_shared_ptr(local_shared_ptr const & r) noexcept;
+    template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r) noexcept;
+
+    local_shared_ptr(local_shared_ptr && r) noexcept;
+    template<class Y> local_shared_ptr(local_shared_ptr<Y> && r) noexcept;
+
+    template<class Y> local_shared_ptr( shared_ptr<Y> const & r );
+    template<class Y> local_shared_ptr( shared_ptr<Y> && r );
+
+    template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r, element_type * p) noexcept;
+    template<class Y> local_shared_ptr(local_shared_ptr<Y> && r, element_type * p) noexcept;
+
+    template<class Y, class D> local_shared_ptr(std::unique_ptr<Y, D> && r);
+    
+    // destructor
+
+    ~local_shared_ptr() noexcept;
+
+    // assignment
+
+    local_shared_ptr & operator=(local_shared_ptr const & r) noexcept;
+    template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const & r) noexcept;
+
+    local_shared_ptr & operator=(local_shared_ptr const && r) noexcept;
+    template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const && r) noexcept;
+
+    template<class Y, class D> local_shared_ptr & operator=(std::unique_ptr<Y, D> && r);
+
+    local_shared_ptr & operator=(std::nullptr_t) noexcept;
+
+    // reset
+	
+    void reset() noexcept;
+
+    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(local_shared_ptr<Y> const & r, element_type * p) noexcept;
+    template<class Y> void reset(local_shared_ptr<Y> && r, element_type * p) noexcept;
+
+    // accessors
+    
+    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;
+
+    long local_use_count() const noexcept;
+
+    // conversions
+
+    explicit operator bool() const noexcept;
+
+    template<class Y> operator shared_ptr<Y>() const noexcept;
+    template<class Y> operator weak_ptr<Y>() const noexcept;
+
+    // swap
+    
+    void swap(local_shared_ptr & b) noexcept;
+
+    // owner_before
+    
+    template<class Y> bool owner_before(local_shared_ptr<Y> const & rhs) const noexcept;
+  };
+
+  // comparisons
+  
+  template<class T, class U>
+    bool operator==(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+  template<class T, class U>
+    bool operator==(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+  template<class T, class U>
+    bool operator==(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+
+  template<class T, class U>
+    bool operator!=(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+  template<class T, class U>
+    bool operator!=(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+  template<class T, class U>
+    bool operator!=(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+
+  template<class T> bool operator==(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
+  template<class T> bool operator==(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
+
+  template<class T> bool operator!=(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
+  template<class T> bool operator!=(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
+
+  template<class T, class U>
+    bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+
+  // swap
+  
+  template<class T> void swap(local_shared_ptr<T> & a, local_shared_ptr<T> & b) noexcept;
+
+  // get_pointer
+  
+  template<class T>
+    typename local_shared_ptr<T>::element_type *
+      get_pointer(local_shared_ptr<T> const & p) noexcept;
+
+  // casts
+  
+  template<class T, class U>
+    local_shared_ptr<T> static_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    local_shared_ptr<T> const_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    local_shared_ptr<T> dynamic_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    local_shared_ptr<T> reinterpret_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+
+  // stream I/O
+
+  template<class E, class T, class Y>
+    std::basic_ostream<E, T> &
+      operator<< (std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p);
+
+  // get_deleter
+  
+  template<class D, class T> D * get_deleter(local_shared_ptr<T> const & p) noexcept;
+}
+```
+
+## 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
+```
+constexpr local_shared_ptr() noexcept;
+```
+```
+constexpr local_shared_ptr(std::nullptr_t) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Constructs an empty `local_shared_ptr`.
+Postconditions:: `local_use_count() == 0 && get() == 0`.
+
+### pointer constructor
+```
+template<class Y> explicit local_shared_ptr(Y * p);
+```
+[none]
+* {blank}
++
+Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p )`.
+
+Postconditions:: `local_use_count() == 1 && get() == p`.
+
+Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
+
+### constructors taking a deleter
+```
+template<class Y, class D> local_shared_ptr(Y * p, D d);
+```
+```
+template<class D> local_shared_ptr(std::nullptr_t p, D d);
+```
+[none]
+* {blank}
++
+Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p, d )`.
+
+Postconditions:: `local_use_count() == 1 && get() == p`.
+
+Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
+
+```
+template<class Y, class D, class A> local_shared_ptr(Y * p, D d, A a);
+```
+```
+template<class D, class A> local_shared_ptr(std::nullptr_t p, D d, A a);
+```
+[none]
+* {blank}
++
+Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p, d, a )`.
+
+Postconditions:: `local_use_count() == 1 && get() == p`.
+
+Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
+
+### copy and converting constructors
+```
+local_shared_ptr(local_shared_ptr const & r) noexcept;
+```
+```
+template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r) noexcept;
+```
+[none]
+* {blank}
++
+Requires:: `Y*` should be convertible to `T*`.
+
+Effects:: If `r` is empty, constructs an empty `local_shared_ptr`; otherwise, constructs a `local_shared_ptr` that shares ownership with `r`.
+
+Postconditions:: `get() == r.get() && local_use_count() == r.local_use_count()`.
+
+### move constructors
+```
+local_shared_ptr(local_shared_ptr && r) noexcept;
+```
+```
+template<class Y> local_shared_ptr(local_shared_ptr<Y> && r) noexcept;
+```
+[none]
+* {blank}
++
+Requires:: `Y*` should be convertible to `T*`.
+
+Effects:: Move-constructs a `local_shared_ptr` from `r`.
+
+Postconditions:: `*this` contains the old value of `r`. `r` is empty and `r.get() == 0`.
+
+### shared_ptr constructor
+```
+template<class Y> local_shared_ptr( shared_ptr<Y> const & r );
+```
+```
+template<class Y> local_shared_ptr( shared_ptr<Y> && r );
+```
+[none]
+* {blank}
++
+Effects:: Constructs a `local_shared_ptr` that owns `r`.
+
+Postconditions:: `local_use_count() == 1`. `get()` returns the old value of `r.get()`.
+
+Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
+
+### aliasing constructor
+```
+template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r, element_type * p) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: constructs a `local_shared_ptr` that shares ownership with `r` and stores `p`.
+
+Postconditions:: `get() == p && local_use_count() == r.local_use_count()`.
+
+### aliasing move constructor
+```
+template<class Y> local_shared_ptr(local_shared_ptr<Y> && r, element_type * p) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Move-constructs a `local_shared_ptr` from `r`, while storing `p` instead.
+
+Postconditions:: `get() == p` and `local_use_count()` equals the old count of `r`. `r` is empty and `r.get() == 0`.
+
+### unique_ptr constructor
+```
+template<class Y, class D> local_shared_ptr(std::unique_ptr<Y, D> && r);
+```
+[none]
+* {blank}
++
+Requires:: `Y*` should be convertible to `T*`.
+
+Effects::
+- When `r.get() == 0`, equivalent to `local_shared_ptr()`;
+- Otherwise, constructs a `local_shared_ptr` that owns `shared_ptr<T>( std::move(r) )`.
+
+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
+```
+~local_shared_ptr() noexcept;
+```
+[none]
+* {blank}
++
+Effects::
+- If `*this` is empty, or shares ownership with another `local_shared_ptr` instance (`local_use_count() > 1`), there are no side effects.
+- Otherwise, destroys the owned `shared_ptr`.
+
+### assignment
+```
+local_shared_ptr & operator=(local_shared_ptr const & r) noexcept;
+```
+```
+template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const & r) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `local_shared_ptr(r).swap(*this)`.
+Returns:: `*this`.
+
+```
+local_shared_ptr & operator=(local_shared_ptr && r) noexcept;
+```
+```
+template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> && r) noexcept;
+```
+```
+template<class Y, class D> local_shared_ptr & operator=(std::unique_ptr<Y, D> && r);
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `local_shared_ptr(std::move(r)).swap(*this)`.
+Returns:: `*this`.
+
+```
+local_shared_ptr & operator=(std::nullptr_t) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `local_shared_ptr().swap(*this)`.
+Returns:: `*this`.
+
+### reset
+```
+void reset() noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `local_shared_ptr().swap(*this)`.
+
+```
+template<class Y> void reset(Y * p);
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `local_shared_ptr(p).swap(*this)`.
+
+```
+template<class Y, class D> void reset(Y * p, D d);
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `local_shared_ptr(p, d).swap(*this)`.
+
+```
+template<class Y, class D, class A> void reset(Y * p, D d, A a);
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `local_shared_ptr(p, d, a).swap(*this)`.
+
+```
+template<class Y> void reset(local_shared_ptr<Y> const & r, element_type * p) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `local_shared_ptr(r, p).swap(*this)`.
+
+```
+template<class Y> void reset(local_shared_ptr<Y> && r, element_type * p) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `local_shared_ptr(std::move(r), p).swap(*this)`.
+
+### indirection
+```
+T & operator*() const noexcept;
+```
+[none]
+* {blank}
++
+Requires:: `T` should not be an array type.
+Returns:: `*get()`.
+
+```
+T * operator->() const noexcept;
+```
+[none]
+* {blank}
++
+Requires:: `T` should not be an array type.
+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.
+
+### local_use_count
+```
+long local_use_count() const noexcept;
+```
+[none]
+* {blank}
++
+Returns:: The number of `local_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: On C++03 compilers, the return value is of an unspecified type.
+
+```
+template<class Y> operator shared_ptr<Y>() const noexcept;
+```
+```
+template<class Y> operator weak_ptr<Y>() const noexcept;
+```
+[none]
+* {blank}
++
+Requires:: `T*` should be convertible to `Y*`.
+Returns:: a copy of the owned `shared_ptr`.
+
+### swap
+```
+void swap(local_shared_ptr & b) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Exchanges the contents of the two smart pointers.
+
+### owner_before
+```
+template<class Y> bool owner_before(local_shared_ptr<Y> const & rhs) const noexcept;
+```
+[none]
+* {blank}
++
+Effects:: See the description of `operator<`.
+
+## Free Functions
+
+### comparison
+```
+template<class T, class U>
+  bool operator==(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+```
+```
+template<class T, class U>
+  bool operator==(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+```
+```
+template<class T, class U>
+  bool operator==(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `a.get() == b.get()`.
+
+```
+template<class T, class U>
+  bool operator!=(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+```
+```
+template<class T, class U>
+  bool operator!=(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+```
+```
+template<class T, class U>
+  bool operator!=(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `a.get() != b.get()`.
+
+```
+template<class T> bool operator==(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
+```
+```
+template<class T> bool operator==(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `p.get() == 0`.
+
+```
+template<class T> bool operator!=(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
+```
+```
+template<class T> bool operator!=(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `p.get() != 0`.
+
+```
+template<class T, class U>
+  bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> 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 `local_shared_ptr` instances
+    are equivalent if and only if they share ownership or are both empty.
+
+NOTE: Allows `local_shared_ptr` objects to be used as keys in associative containers.
+
+NOTE: The rest of the comparison operators are omitted by design.
+
+### swap
+```
+template<class T> void swap(local_shared_ptr<T> & a, local_shared_ptr<T> & b) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `a.swap(b)`.
+
+### get_pointer
+```
+template<class T>
+  typename local_shared_ptr<T>::element_type *
+    get_pointer(local_shared_ptr<T> const & p) noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `p.get()`.
+
+NOTE: Provided as an aid to generic programming. Used by `mem_fn`.
+
+### static_pointer_cast
+```
+template<class T, class U>
+  local_shared_ptr<T> static_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+```
+[none]
+* {blank}
++
+Requires:: The expression `static_cast<T*>( (U*)0 )` must be well-formed.
+Returns:: `local_shared_ptr<T>( r, static_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`.
+
+CAUTION: The seemingly equivalent expression `local_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>
+  local_shared_ptr<T> const_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+```
+[none]
+* {blank}
++
+Requires:: The expression `const_cast<T*>( (U*)0 )` must be well-formed.
+Returns:: `local_shared_ptr<T>( r, const_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`.
+
+### dynamic_pointer_cast
+```
+template<class T, class U>
+    local_shared_ptr<T> dynamic_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+```
+[none]
+* {blank}
++
+Requires:: The expression `dynamic_cast<T*>( (U*)0 )` must be well-formed.
+Returns::
+  - When `dynamic_cast<typename local_shared_ptr<T>::element_type*>(r.get())` returns a nonzero value `p`, `local_shared_ptr<T>(r, p)`;
+  - Otherwise, `local_shared_ptr<T>()`.
+
+### reinterpret_pointer_cast
+```
+template<class T, class U>
+  local_shared_ptr<T> reinterpret_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+```
+[none]
+* {blank}
++
+Requires:: The expression `reinterpret_cast<T*>( (U*)0 )` must be well-formed.
+Returns:: `local_shared_ptr<T>( r, reinterpret_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`.
+
+### operator<<
+```
+template<class E, class T, class Y>
+  std::basic_ostream<E, T> &
+    operator<< (std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p);
+```
+[none]
+* {blank}
++
+Effects:: `os << p.get();`.
+Returns:: `os`.
+
+### get_deleter
+```
+template<class D, class T>
+  D * get_deleter(local_shared_ptr<T> const & p) noexcept;
+```
+[none]
+* {blank}
++
+Returns:: If `*this` owns a `shared_ptr` instance `p`, `get_deleter<D>( p )`, otherwise 0.
+
diff --git a/doc/smart_ptr/make_local_shared.adoc b/doc/smart_ptr/make_local_shared.adoc
new file mode 100644
index 0000000..3d586f7
--- /dev/null
+++ b/doc/smart_ptr/make_local_shared.adoc
@@ -0,0 +1,81 @@
+////
+Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com)
+
+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_local_shared]
+# make_local_shared: Creating local_shared_ptr
+:toc:
+:toc-title:
+:idprefix: make_local_shared_
+
+## Description
+
+The function templates `make_local_shared` and `allocate_local_shared` provide
+convenient, safe and efficient ways to create `local_shared_ptr` objects. They
+are analogous to `make_shared` and `allocate_shared` for `shared_ptr`.
+
+## Synopsis
+
+`make_local_shared` and `allocate_local_shared` are defined in
+`<boost/smart_ptr/make_local_shared.hpp>`.
+
+[subs=+quotes]
+```
+namespace boost {
+  `// only if T is not an array type`
+  template<class T, class... Args>
+    local_shared_ptr<T> make_local_shared(Args&&... args);
+  template<class T, class A, class... Args>
+    local_shared_ptr<T> allocate_local_shared(const A& a, Args&&... args);
+
+  `// only if T is an array type of the form U[]`
+  template<class T>
+    local_shared_ptr<T> make_local_shared(std::size_t n);
+  template<class T, class A>
+    local_shared_ptr<T> allocate_local_shared(const A& a, std::size_t n);
+
+  `// only if T is an array type of the form U[N]`
+  template<class T>
+    local_shared_ptr<T> make_local_shared();
+  template<class T, class A>
+    local_shared_ptr<T> allocate_local_shared(const A& a);
+
+  `// only if T is an array type of the form U[]`
+  template<class T>
+    local_shared_ptr<T> make_local_shared(std::size_t n,
+      const remove_extent_t<T>& v);
+  template<class T, class A>
+    local_shared_ptr<T> allocate_local_shared(const A& a, std::size_t n,
+      const remove_extent_t<T>& v);
+
+  `// only if T is an array type of the form U[N]`
+  template<class T>
+    local_shared_ptr<T> make_local_shared(const remove_extent_t<T>& v);
+  template<class T, class A>
+    local_shared_ptr<T> allocate_local_shared(const A& a,
+      const remove_extent_t<T>& v);
+
+  `// only if T is not an array type of the form U[]`
+  template<class T>
+    local_shared_ptr<T> make_local_shared_noinit();
+  template<class T, class A>
+    local_shared_ptr<T> allocate_local_shared_noinit(const A& a);
+
+  `// only if T is an array type of the form U[N]`
+  template<class T>
+    local_shared_ptr<T> make_local_shared_noinit(std::size_t n);
+  template<class T, class A>
+    local_shared_ptr<T> allocate_local_shared_noinit(const A& a,
+      std::size_t n);
+}
+```
+
+## Description
+
+The requirements and effects of these functions are the same as `make_shared`
+and `allocate_shared`, except that a `local_shared_ptr` is returned.
diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc
new file mode 100644
index 0000000..5b4366c
--- /dev/null
+++ b/doc/smart_ptr/make_shared.adoc
@@ -0,0 +1,295 @@
+////
+Copyright 2017 Peter Dimov
+Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com)
+
+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: Creating shared_ptr
+:toc:
+: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<Widget>()` 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
+`<boost/smart_ptr/make_shared.hpp>`.
+
+[subs=+quotes]
+```
+namespace boost {
+  `// only if T is not an array type`
+  template<class T, class... Args>
+    shared_ptr<T> make_shared(Args&&... args);
+  template<class T, class A, class... Args>
+    shared_ptr<T> allocate_shared(const A& a, Args&&... args);
+
+  `// only if T is an array type of the form U[]`
+  template<class T>
+    shared_ptr<T> make_shared(std::size_t n);
+  template<class T, class A>
+    shared_ptr<T> allocate_shared(const A& a, std::size_t n);
+
+  `// only if T is an array type of the form U[N]`
+  template<class T>
+    shared_ptr<T> make_shared();
+  template<class T, class A>
+    shared_ptr<T> allocate_shared(const A& a);
+
+  `// only if T is an array type of the form U[]`
+  template<class T> shared_ptr<T>
+    make_shared(std::size_t n, const remove_extent_t<T>& v);
+  template<class T, class A> shared_ptr<T>
+    allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
+
+  `// only if T is an array type of the form U[N]`
+  template<class T>
+    shared_ptr<T> make_shared(const remove_extent_t<T>& v);
+  template<class T, class A>
+    shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v);
+
+  `// only if T is not an array type of the form U[]`
+  template<class T>
+    shared_ptr<T> make_shared_noinit();
+  template<class T, class A>
+    shared_ptr<T> allocate_shared_noinit(const A& a);
+
+  `// only if T is an array type of the form U[N]`
+  template<class T>
+    shared_ptr<T> make_shared_noinit(std::size_t n);
+  template<class T, class A>
+    shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n);
+}
+```
+
+## Common Requirements
+
+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:: `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.
+* 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>(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>(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.
+
+## Free Functions
+
+```
+template<class T, class... Args>
+  shared_ptr<T> make_shared(Args&&... args);
+```
+::
+```
+template<class T, class A, class... Args>
+  shared_ptr<T> 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\...`.
+Examples:::
+* `auto p = make_shared<int>();`
+* `auto p = make_shared<std::vector<int> >(16, 1);`
+
+```
+template<class T>
+  shared_ptr<T> make_shared(std::size_t n);
+```
+::
+```
+template<class T, class A>
+  shared_ptr<T> 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`.
+Examples:::
+* `auto p = make_shared<double[]>(1024);`
+* `auto p = make_shared<double[][2][2]>(6);`
+
+```
+template<class T>
+  shared_ptr<T> make_shared();
+```
+::
+```
+template<class T, class A>
+  shared_ptr<T> 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`.
+Examples:::
+* `auto p = make_shared<double[1024]>();`
+* `auto p = make_shared<double[6][2][2]>();`
+
+```
+template<class T> shared_ptr<T>
+  make_shared(std::size_t n, const remove_extent_t<T>& v);
+```
+::
+```
+template<class T, class A> shared_ptr<T>
+  allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& 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`.
+Examples:::
+* `auto p = make_shared<double[]>(1024, 1.0);`
+* `auto p = make_shared<double[][2]>(6, {1.0, 0.0});`
+* `auto p = make_shared<std::vector<int>[]>(4, {1, 2});`
+
+```
+template<class T>
+  shared_ptr<T> make_shared(const remove_extent_t<T>& v);
+```
+::
+```
+template<class T, class A>
+  shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& 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`.
+Examples:::
+* `auto p = make_shared<double[1024]>(1.0);`
+* `auto p = make_shared<double[6][2]>({1.0, 0.0});`
+* `auto p = make_shared<std::vector<int>[4]>({1, 2});`
+
+```
+template<class T>
+  shared_ptr<T> make_shared_noinit();
+```
+::
+```
+template<class T, class A>
+  shared_ptr<T> 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.
+Example::: `auto p = make_shared_noinit<double[1024]>();`
+
+```
+template<class T>
+  shared_ptr<T> make_shared_noinit(std::size_t n);
+```
+::
+```
+template<class T, class A>
+  shared_ptr<T> 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`.
+Example::: `auto p = make_shared_noinit<double[]>(1024);`
diff --git a/doc/smart_ptr/make_unique.adoc b/doc/smart_ptr/make_unique.adoc
new file mode 100644
index 0000000..ae3b325
--- /dev/null
+++ b/doc/smart_ptr/make_unique.adoc
@@ -0,0 +1,115 @@
+////
+Copyright 2017 Peter Dimov
+Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com)
+
+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: Creating unique_ptr
+:toc:
+:toc-title:
+:idprefix: make_unique_
+
+## Description
+
+The `make_unique` function templates provide convenient and safe ways to
+create `std::unique_ptr` objects.
+
+## Rationale
+
+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 {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 {cpp} standard does not yet provide this
+feature with `std::make_unique`.
+
+## Synopsis
+
+`make_unique` is defined in `<boost/smart_ptr/make_unique.hpp>`.
+
+[subs=+quotes]
+```
+namespace boost {
+  `// only if T is not an array type`
+  template<class T, class... Args>
+    std::unique_ptr<T> make_unique(Args&&... args);
+
+  `// only if T is not an array type`
+  template<class T>
+    std::unique_ptr<T> make_unique(remove_reference_t<T>&& v);
+
+  `// only if T is an array type of the form U[]`
+  template<class T>
+    std::unique_ptr<T> make_unique(std::size_t n);
+
+  `// only if T is not an array type`
+  template<class T>
+    std::unique_ptr<T> make_unique_noinit();
+
+  `// only if T is an array type of the form U[]`
+  template<class T>
+    std::unique_ptr<T> make_unique_noinit(std::size_t n);
+}
+```
+
+## Free Functions
+
+```
+template<class T, class... Args>
+  std::unique_ptr<T> make_unique(Args&&... args);
+```
+::
+Remarks::: These overloads shall only participate in overload resolution when
+`T` is not an array type.
+Returns::: `std::unique_ptr<T>(new T(std::forward<Args>(args)\...)`.
+Example::: `auto p = make_unique<int>();`
+
+```
+template<class T>
+  std::unique_ptr<T> make_unique(remove_reference_t<T>&& v);
+```
+::
+Remarks::: These overloads shall only participate in overload resolution when
+`T` is not an array type.
+Returns::: `std::unique_ptr<T>(new T(std::move(v))`.
+Example::: `auto p = make_unique<std::vector<int> >({1, 2});`
+
+```
+template<class T>
+  std::unique_ptr<T> 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<double[]>(1024);`
+
+```
+template<class T>
+  std::unique_ptr<T> make_unique_noinit();
+```
+::
+Remarks::: These overloads shall only participate in overload resolution when
+`T` is not an array type.
+Returns::: `std::unique_ptr<T>(new T)`.
+Example::: `auto p = make_unique_noinit<double[1024]>();`
+
+```
+template<class T>
+  std::unique_ptr<T> 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<double[]>(1024);`
diff --git a/doc/smart_ptr/pointer_cast.adoc b/doc/smart_ptr/pointer_cast.adoc
new file mode 100644
index 0000000..ccae283
--- /dev/null
+++ b/doc/smart_ptr/pointer_cast.adoc
@@ -0,0 +1,213 @@
+////
+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: 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<T>` implements a static
+pointer cast this way:
+
+```
+template<class T, class U>
+  shared_ptr<T> static_pointer_cast(const shared_ptr<U>& 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 `<boost/pointer_cast.hpp>`.
+
+```
+namespace boost {
+  template<class T, class U> T* static_pointer_cast(U* p) noexcept;
+  template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
+  template<class T, class U> T* const_pointer_cast(U* p) noexcept;
+  template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
+
+  template<class T, class U> std::shared_ptr<T>
+    static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+  template<class T, class U> std::shared_ptr<T>
+    dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+  template<class T, class U> std::shared_ptr<T>
+    const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+  template<class T, class U> std::shared_ptr<T>
+    reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+
+  template<class T, class U> std::unique_ptr<T>
+    static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+  template<class T, class U> std::unique_ptr<T>
+    dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+  template<class T, class U> std::unique_ptr<T>
+    const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+  template<class T, class U> std::unique_ptr<T>
+    reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+}
+```
+
+## Free Functions
+
+### static_pointer_cast
+```
+template<class T, class U> T* static_pointer_cast(U* p) noexcept;
+```
+::
+Returns::: `static_cast<T*>(p)`
+
+```
+template<class T, class U> std::shared_ptr<T>
+  static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+```
+::
+Returns::: `std::static_pointer_cast<T>(p)`
+
+```
+template<class T, class U> std::unique_ptr<T>
+  static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+```
+::
+Requires::: The expression `static_cast<T*>((U*)0)` must be well-formed.
+Returns::: `std::unique_ptr<T>(static_cast<typename
+std::unique_ptr<T>::element_type*>(p.release()))`.
+
+CAUTION: The seemingly equivalent expression
+`std::unique_ptr<T>(static_cast<T*>(p.get()))` will eventually result in
+undefined behavior, attempting to delete the same object twice.
+
+### dynamic_pointer_cast
+
+```
+template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
+```
+::
+Returns::: `dynamic_cast<T*>(p)`
+
+```
+template<class T, class U> std::shared_ptr<T>
+  dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+```
+::
+Returns::: `std::dynamic_pointer_cast<T>(p)`
+
+```
+template<class T, class U> std::unique_ptr<T>
+  dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+```
+::
+Requires:::
+* The expression `static_cast<T*>((U*)0)` must be well-formed.
+* `T` must have a virtual destructor.
+Returns:::
+* When `dynamic_cast<typename std::unique_ptr<T>::element_type*>(p.get())`
+returns a non-zero value, `std::unique_ptr<T>(dynamic_cast<typename
+std::unique_ptr<T>::element_type*>(p.release()));`.
+* Otherwise, `std::unique_ptr<T>()`.
+
+### const_pointer_cast
+
+```
+template<class T, class U> T* const_pointer_cast(U* p) noexcept;
+```
+::
+Returns::: `const_cast<T*>(p)`
+
+```
+template<class T, class U> std::shared_ptr<T>
+  const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+```
+::
+Returns::: `std::const_pointer_cast<T>(p)`
+
+```
+template<class T, class U> std::unique_ptr<T>
+  const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+```
+::
+Requires::: The expression `const_cast<T*>((U*)0)` must be well-formed.
+Returns::: `std::unique_ptr<T>(const_cast<typename
+std::unique_ptr<T>::element_type*>(p.release()))`.
+
+### reinterpret_pointer_cast
+
+```
+template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
+```
+::
+Returns::: `reinterpret_cast<T*>(p)`
+
+```
+template<class T, class U> std::shared_ptr<T>
+  reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+```
+::
+Returns::: `std::reinterpret_pointer_cast<T>(p)`
+
+```
+template<class T, class U> std::unique_ptr<T>
+  reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+```
+::
+Requires::: The expression `reinterpret_cast<T*>((U*)0)` must be well-formed.
+Returns::: `std::unique_ptr<T>(reinterpret_cast<typename
+std::unique_ptr<T>::element_type*>(p.release()))`.
+
+## Example
+
+The following example demonstrates how the generic pointer casts help us
+create pointer independent code.
+
+```
+#include <boost/pointer_cast.hpp>
+#include <boost/shared_ptr.hpp>
+
+class base {
+public:
+  virtual ~base() { }
+};
+
+class derived : public base { };
+
+template<class Ptr>
+void check_if_it_is_derived(const Ptr& ptr)
+{
+  assert(boost::dynamic_pointer_cast<derived>(ptr) != 0);
+}
+
+int main()
+{
+  base* ptr = new derived;
+  boost::shared_ptr<base> sptr(new derived);
+
+  check_if_it_is_derived(ptr);
+  check_if_it_is_derived(sptr);
+
+  delete ptr;
+}
+```
\ No newline at end of file
diff --git a/doc/smart_ptr/pointer_to_other.adoc b/doc/smart_ptr/pointer_to_other.adoc
new file mode 100644
index 0000000..d903cad
--- /dev/null
+++ b/doc/smart_ptr/pointer_to_other.adoc
@@ -0,0 +1,114 @@
+////
+Copyright 2005, 2006 Ion Gaztañaga
+Copyright 2005, 2006, 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: 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 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
+
+`pointer_to_other` is defined in `<boost/smart_ptr/pointer_to_other.hpp>`.
+
+```
+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;
+  };
+}
+```
+
+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.
diff --git a/doc/smart_ptr/scoped_array.adoc b/doc/smart_ptr/scoped_array.adoc
new file mode 100644
index 0000000..9746a7c
--- /dev/null
+++ b/doc/smart_ptr/scoped_array.adoc
@@ -0,0 +1,175 @@
+////
+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.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#scoped_array]
+# scoped_array: Scoped Array Ownership
+:toc:
+: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<T[]>` 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<T[]>` 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
+
+`scoped_array` is defined in `<boost/smart_ptr/scoped_array.hpp>`.
+
+```
+namespace boost {
+
+  template<class T> 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<class T> void swap(scoped_array<T> & a, scoped_array<T> & b) noexcept;
+
+  template<class T>
+    bool operator==( scoped_array<T> const & p, std::nullptr_t ) noexcept;
+  template<class T>
+    bool operator==( std::nullptr_t, scoped_array<T> const & p ) noexcept;
+
+  template<class T>
+    bool operator!=( scoped_array<T> const & p, std::nullptr_t ) noexcept;
+  template<class T>
+    bool operator!=( std::nullptr_t, scoped_array<T> const & p ) noexcept;
+}
+```
+
+## 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<class T> void swap(scoped_array<T> & a, scoped_array<T> & b) noexcept;
+
+Equivalent to `a.swap(b)`.
+
+### comparisons
+
+    template<class T>
+      bool operator==( scoped_array<T> const & p, std::nullptr_t ) noexcept;
+
+    template<class T>
+      bool operator==( std::nullptr_t, scoped_array<T> const & p ) noexcept;
+
+Returns `p.get() == nullptr`.
+
+    template<class T>
+      bool operator!=( scoped_array<T> const & p, std::nullptr_t ) noexcept;
+
+    template<class T>
+      bool operator!=( std::nullptr_t, scoped_array<T> const & p ) noexcept;
+
+Returns `p.get() != nullptr`.
diff --git a/doc/smart_ptr/scoped_ptr.adoc b/doc/smart_ptr/scoped_ptr.adoc
new file mode 100644
index 0000000..4f08811
--- /dev/null
+++ b/doc/smart_ptr/scoped_ptr.adoc
@@ -0,0 +1,234 @@
+////
+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: Scoped Object Ownership
+:toc:
+:toc-title:
+: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_example,example>>.
+
+`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<T>::~scoped_ptr` is instantiated.
+
+## Synopsis
+
+`scoped_ptr` is defined in `<boost/smart_ptr/scoped_ptr.hpp>`.
+
+```
+namespace boost {
+
+  template<class T> 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<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) noexcept;
+
+  template<class T>
+    bool operator==( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
+  template<class T>
+    bool operator==( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
+
+  template<class T>
+    bool operator!=( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
+  template<class T>
+    bool operator!=( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
+}
+```
+
+## 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`.
+
+NOTE: On C++03 compilers, the return value is of an unspecified type.
+
+### 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<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) noexcept;
+
+Equivalent to `a.swap(b)`.
+
+### comparisons
+
+    template<class T> bool operator==( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
+
+    template<class T> bool operator==( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
+
+Returns `p.get() == nullptr`.
+
+    template<class T> bool operator!=( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
+
+    template<class T> bool operator!=( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
+
+Returns `p.get() != nullptr`.
+
+## 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 `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<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 `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
new file mode 100644
index 0000000..5be074c
--- /dev/null
+++ b/doc/smart_ptr/shared_array.adoc
@@ -0,0 +1,270 @@
+////
+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_array]]
+[appendix]
+# shared_array (deprecated)
+:toc:
+: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 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(const shared_array& v) noexcept;
+
+    ~shared_array() noexcept;
+
+    shared_array& operator=(const shared_array& v) noexcept;
+
+    void reset(T* p = 0);
+    template<class D> 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<T>& v) noexcept;
+  };
+
+  template<class T> bool
+    operator==(const shared_array<T>& a, const shared_array<T>& b) noexcept;
+  template<class T> bool
+    operator!=(const shared_array<T>& a, const shared_array<T>& b) noexcept;
+  template<class T> bool
+    operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept;
+
+  template<class T>
+    void swap(shared_array<T>& a, shared_array<T>& 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<class D> 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<class D> 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<T>& b) noexcept;
+```
+::
+Effects::: Exchanges the contents of the two smart pointers.
+
+## Free Functions
+
+### Comparison
+
+```
+template<class T> bool
+  operator==(const shared_array<T>& a, const shared_array<T>& b) noexcept;
+```
+```
+template<class T> bool
+  operator!=(const shared_array<T>& a, const shared_array<T>& b) noexcept;
+```
+```
+template<class T> bool
+  operator<(const shared_array<T>& a, const shared_array<T>& 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<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) noexcept;
+```
+::
+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
new file mode 100644
index 0000000..64761dd
--- /dev/null
+++ b/doc/smart_ptr/shared_ptr.adoc
@@ -0,0 +1,1035 @@
+////
+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.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#shared_ptr]
+# shared_ptr: Shared Ownership
+:toc:
+: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<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
+{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 `<<weak_ptr,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.
+
+.Using shared_ptr with arrays
+```
+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 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);
+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_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 `<<make_shared,make_shared>>` or `allocate_shared` factory
+functions defined in `<boost/smart_ptr/make_shared.hpp>`. These factory functions also provide an efficiency benefit by consolidating allocations.
+
+## Synopsis
+
+`shared_ptr` is defined in `<boost/smart_ptr/shared_ptr.hpp>`.
+
+```
+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;
+
+    constexpr shared_ptr() noexcept;
+    constexpr shared_ptr(std::nullptr_t) noexcept;
+
+    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() noexcept;
+
+    shared_ptr(shared_ptr const & r) noexcept;
+    template<class Y> shared_ptr(shared_ptr<Y> const & r) noexcept;
+
+    shared_ptr(shared_ptr && r) noexcept;
+    template<class Y> shared_ptr(shared_ptr<Y> && r) noexcept;
+
+    template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
+
+    template<class Y> shared_ptr(shared_ptr<Y> && r, element_type * p) noexcept;
+
+    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) noexcept;
+    template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r) noexcept;
+
+    shared_ptr & operator=(shared_ptr const && r) noexcept;
+    template<class Y> shared_ptr & operator=(shared_ptr<Y> const && r) noexcept;
+
+    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) noexcept;
+
+    void reset() noexcept;
+
+    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) noexcept;
+    template<class Y> void reset(shared_ptr<Y> && 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<class Y> bool owner_before(shared_ptr<Y> const & rhs) const noexcept;
+    template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const noexcept;
+  };
+
+  template<class T, class U>
+    bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+
+  template<class T, class U>
+    bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+
+  template<class T, class U>
+    bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+
+  template<class T> bool operator==(shared_ptr<T> const & p, std::nullptr_t) noexcept;
+  template<class T> bool operator==(std::nullptr_t, shared_ptr<T> const & p) noexcept;
+
+  template<class T> bool operator!=(shared_ptr<T> const & p, std::nullptr_t) noexcept;
+  template<class T> bool operator!=(std::nullptr_t, shared_ptr<T> const & p) noexcept;
+
+  template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b) noexcept;
+
+  template<class T>
+    typename shared_ptr<T>::element_type *
+      get_pointer(shared_ptr<T> const & p) noexcept;
+
+  template<class T, class U>
+    shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r) noexcept;
+
+  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) noexcept;
+
+  template<class T> bool atomic_is_lock_free( shared_ptr<T> const * p ) noexcept;
+
+  template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) noexcept;
+  template<class T>
+    shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, int ) noexcept;
+
+  template<class T>
+    void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) noexcept;
+  template<class T>
+    void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept;
+
+  template<class T>
+    shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) noexcept;
+  template<class T>
+    shared_ptr<T> atomic_exchange_explicit(
+      shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept;
+
+  template<class T>
+    bool atomic_compare_exchange(
+      shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) noexcept;
+  template<class T>
+    bool atomic_compare_exchange_explicit(
+      shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, int, int ) noexcept;
+}
+```
+
+## 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
+```
+constexpr shared_ptr() noexcept;
+```
+```
+constexpr shared_ptr(std::nullptr_t) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Constructs an empty `shared_ptr`.
+Postconditions:: `use_count() == 0 && get() == 0`.
+
+### pointer constructor
+```
+template<class Y> 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<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.
+
+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<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);
+```
+[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<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.
+
+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<class Y> shared_ptr(shared_ptr<Y> 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<class Y> shared_ptr(shared_ptr<Y> && 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<class Y> shared_ptr(shared_ptr<Y> 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<class Y> shared_ptr(shared_ptr<Y> && 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<class Y> explicit shared_ptr(weak_ptr<Y> 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<class Y> shared_ptr(std::auto_ptr<Y> & r);
+```
+```
+template<class Y> shared_ptr(std::auto_ptr<Y> && 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<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
+```
+[none]
+* {blank}
++
+Requires:: `Y*` should be convertible to `T*`.
+
+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.
+
+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<class Y> shared_ptr & operator=(shared_ptr<Y> const & r) noexcept;
+```
+```
+template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & 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<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) noexcept;
+```
+```
+template<class Y> shared_ptr & operator=(shared_ptr<Y> && r) noexcept;
+```
+```
+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);
+```
+[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<class Y> void reset(Y * p);
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `shared_ptr(p).swap(*this)`.
+
+```
+template<class Y, class D> void reset(Y * p, D d);
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `shared_ptr(p, d).swap(*this)`.
+
+```
+template<class Y, class D, class A> void reset(Y * p, D d, A a);
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `shared_ptr(p, d, a).swap(*this)`.
+
+```
+template<class Y> void reset(shared_ptr<Y> const & r, element_type * p) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `shared_ptr(r, p).swap(*this)`.
+
+```
+template<class Y> void reset(shared_ptr<Y> && 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`.
+
+NOTE: On C++03 compilers, the return value is of an unspecified type.
+
+### swap
+```
+void swap(shared_ptr & b) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Exchanges the contents of the two smart pointers.
+
+### owner_before
+```
+template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const noexcept;
+```
+```
+template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const noexcept;
+```
+[none]
+* {blank}
++
+Effects:: See the description of `operator<`.
+
+## Free Functions
+
+### comparison
+```
+template<class T, class U>
+  bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `a.get() == b.get()`.
+
+```
+template<class T, class U>
+  bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `a.get() != b.get()`.
+
+```
+template<class T> bool operator==(shared_ptr<T> const & p, std::nullptr_t) noexcept;
+```
+```
+template<class T> bool operator==(std::nullptr_t, shared_ptr<T> const & p) noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `p.get() == 0`.
+
+```
+template<class T> bool operator!=(shared_ptr<T> const & p, std::nullptr_t) noexcept;
+```
+```
+template<class T> bool operator!=(std::nullptr_t, shared_ptr<T> const & p) noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `p.get() != 0`.
+
+```
+template<class T, class U>
+  bool operator<(shared_ptr<T> const & a, shared_ptr<U> 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<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: Equivalent to `a.swap(b)`.
+
+### get_pointer
+```
+template<class T>
+  typename shared_ptr<T>::element_type *
+    get_pointer(shared_ptr<T> const & p) noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `p.get()`.
+
+NOTE: 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) noexcept;
+```
+[none]
+* {blank}
++
+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()) )`.
+
+CAUTION: 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) noexcept;
+```
+[none]
+* {blank}
++
+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()) )`.
+
+### dynamic_pointer_cast
+```
+template<class T, class U>
+    shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) noexcept;
+```
+[none]
+* {blank}
++
+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>()`.
+
+### reinterpret_pointer_cast
+```
+template<class T, class U>
+  shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r) noexcept;
+```
+[none]
+* {blank}
++
+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()) )`.
+
+### 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);
+```
+[none]
+* {blank}
++
+Effects:: `os << p.get();`.
+Returns:: `os`.
+
+### get_deleter
+```
+template<class D, class T>
+  D * get_deleter(shared_ptr<T> const & p) noexcept;
+```
+[none]
+* {blank}
++
+Returns:: If `*this` owns a deleter `d` of type (cv-unqualified) `D`, returns `&d`; otherwise returns 0.
+
+### Atomic Access
+
+NOTE: The function in this section are atomic with respect to the first `shared_ptr` argument,
+  identified by `*p`. Concurrent access to the same `shared_ptr` instance is not a data race, if
+  done exclusively by the functions in this section.
+
+```
+template<class T> bool atomic_is_lock_free( shared_ptr<T> const * p ) noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `false`.
+
+NOTE: This implementation is not lock-free.
+
+```
+template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) noexcept;
+```
+```
+template<class T> shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, int ) noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `*p`.
+
+NOTE: The `int` argument is the `memory_order`, but this implementation does not use it, as it's lock-based
+  and therefore always sequentially consistent.
+
+```
+template<class T>
+  void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) noexcept;
+```
+```
+template<class T>
+  void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: `p\->swap(r)`.
+
+```
+template<class T>
+  shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) noexcept;
+```
+```
+template<class T>
+  shared_ptr<T> atomic_exchange_explicit(
+    shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: `p\->swap(r)`.
+Returns:: The old value of `*p`.
+
+```
+template<class T>
+  bool atomic_compare_exchange(
+    shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) noexcept;
+```
+```
+template<class T>
+  bool atomic_compare_exchange_explicit(
+    shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, int, int ) noexcept;
+```
+[none]
+* {blank}
++
+Effects:: If `*p` is equivalent to `*v`, assigns `w` to `*p`, otherwise assigns `*p` to `*v`.
+Returns:: `true` if `*p` was equivalent to `*v`, `false` otherwise.
+Remarks:: Two `shared_ptr` instances are equivalent if they store the same pointer value and _share ownership_.
+
+
+## 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<int> p(new int(42));
+```
+
+.Reading a `shared_ptr` from two threads
+```
+// thread A
+shared_ptr<int> p2(p); // reads p
+
+// thread B
+shared_ptr<int> 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<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, 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".
diff --git a/doc/smart_ptr/techniques.adoc b/doc/smart_ptr/techniques.adoc
new file mode 100644
index 0000000..36155d4
--- /dev/null
+++ b/doc/smart_ptr/techniques.adoc
@@ -0,0 +1,768 @@
+////
+Copyright 2003, 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
+////
+
+[[techniques]]
+[appendix]
+# Smart Pointer Programming Techniques
+:toc:
+: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<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`&#8217;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 {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<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;
+    }
+};
+```
+
+## 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<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.
+
+[#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<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 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,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`&#8217;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 `<<shared_ptr_get_deleter,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
+    }
+}
+```
+
+[#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<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 `<<techniques_intrusive,make_shared_from_intrusive>>` described above. Or, if it's known that the `shared_ptr` created in `f` will never outlive the object, use <<techniques_static,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 <<techniques_static,here>> and <<techniques_weak_without_shared,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 <<techniques_from_raw,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,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 <<techniques_incomplete,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));
+```
+
+## 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 `<<shared_ptr_static_pointer_cast,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>`&#8217;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(...)
+        {
+        }
+    }
+};
+```
+
+[#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<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.
diff --git a/doc/smart_ptr/weak_ptr.adoc b/doc/smart_ptr/weak_ptr.adoc
new file mode 100644
index 0000000..d51eaa1
--- /dev/null
+++ b/doc/smart_ptr/weak_ptr.adoc
@@ -0,0 +1,298 @@
+////
+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.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+[#weak_ptr]
+# weak_ptr: Non-owning Observer
+:toc:
+: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<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
+
+`weak_ptr` is defined in `<boost/smart_ptr/weak_ptr.hpp>`.
+
+```
+namespace boost {
+
+  template<class T> class weak_ptr {
+  public:
+
+    typedef /*see below*/ element_type;
+
+    weak_ptr() noexcept;
+
+    template<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept;
+    weak_ptr(weak_ptr const & r) noexcept;
+    template<class Y> weak_ptr(weak_ptr<Y> 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<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept;
+    template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept;
+
+    long use_count() const noexcept;
+    bool expired() const noexcept;
+
+    shared_ptr<T> lock() const noexcept;
+
+    void reset() noexcept;
+
+    void swap(weak_ptr<T> & b) noexcept;
+
+    template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept;
+    template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept;
+  };
+
+  template<class T, class U>
+    bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept;
+
+  template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept;
+}
+```
+
+## 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<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept;
+```
+```
+weak_ptr(weak_ptr const & r) noexcept;
+```
+```
+template<class Y> weak_ptr(weak_ptr<Y> 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<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept;
+```
+```
+template<class Y> weak_ptr & operator=(shared_ptr<Y> 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<T> lock() const noexcept;
+```
+[none]
+* {blank}
++
+Returns:: `expired()? shared_ptr<T>(): shared_ptr<T>(*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<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept;
+```
+```
+template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept;
+```
+[none]
+* {blank}
++
+Returns:: See the description of `operator<`.
+
+## Free Functions
+
+### comparison
+```
+template<class T, class U>
+  bool operator<(weak_ptr<T> const & a, weak_ptr<U> 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<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & 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<X> create()
+    {
+        shared_ptr<X> px(new X);
+        // create weak pointers from px here
+        return px;
+    }
+};
+```