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/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..3e84d7c
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,96 @@
+* text=auto !eol svneol=native#text/plain
+*.gitattributes text svneol=native#text/plain
+
+# Scriptish formats
+*.bat text svneol=native#text/plain
+*.bsh text svneol=native#text/x-beanshell
+*.cgi text svneol=native#text/plain
+*.cmd text svneol=native#text/plain
+*.js text svneol=native#text/javascript
+*.php text svneol=native#text/x-php
+*.pl text svneol=native#text/x-perl
+*.pm text svneol=native#text/x-perl
+*.py text svneol=native#text/x-python
+*.sh eol=lf svneol=LF#text/x-sh
+configure eol=lf svneol=LF#text/x-sh
+
+# Image formats
+*.bmp binary svneol=unset#image/bmp
+*.gif binary svneol=unset#image/gif
+*.ico binary svneol=unset#image/ico
+*.jpeg binary svneol=unset#image/jpeg
+*.jpg binary svneol=unset#image/jpeg
+*.png binary svneol=unset#image/png
+*.tif binary svneol=unset#image/tiff
+*.tiff binary svneol=unset#image/tiff
+*.svg text svneol=native#image/svg%2Bxml
+
+# Data formats
+*.pdf binary svneol=unset#application/pdf
+*.avi binary svneol=unset#video/avi
+*.doc binary svneol=unset#application/msword
+*.dsp text svneol=crlf#text/plain
+*.dsw text svneol=crlf#text/plain
+*.eps binary svneol=unset#application/postscript
+*.gz binary svneol=unset#application/gzip
+*.mov binary svneol=unset#video/quicktime
+*.mp3 binary svneol=unset#audio/mpeg
+*.ppt binary svneol=unset#application/vnd.ms-powerpoint
+*.ps binary svneol=unset#application/postscript
+*.psd binary svneol=unset#application/photoshop
+*.rdf binary svneol=unset#text/rdf
+*.rss text svneol=unset#text/xml
+*.rtf binary svneol=unset#text/rtf
+*.sln text svneol=native#text/plain
+*.swf binary svneol=unset#application/x-shockwave-flash
+*.tgz binary svneol=unset#application/gzip
+*.vcproj text svneol=native#text/xml
+*.vcxproj text svneol=native#text/xml
+*.vsprops text svneol=native#text/xml
+*.wav binary svneol=unset#audio/wav
+*.xls binary svneol=unset#application/vnd.ms-excel
+*.zip binary svneol=unset#application/zip
+
+# Text formats
+.htaccess text svneol=native#text/plain
+*.bbk text svneol=native#text/xml
+*.cmake text svneol=native#text/plain
+*.css text svneol=native#text/css
+*.dtd text svneol=native#text/xml
+*.htm text svneol=native#text/html
+*.html text svneol=native#text/html
+*.ini text svneol=native#text/plain
+*.log text svneol=native#text/plain
+*.mak text svneol=native#text/plain
+*.qbk text svneol=native#text/plain
+*.rst text svneol=native#text/plain
+*.sql text svneol=native#text/x-sql
+*.txt text svneol=native#text/plain
+*.xhtml text svneol=native#text/xhtml%2Bxml
+*.xml text svneol=native#text/xml
+*.xsd text svneol=native#text/xml
+*.xsl text svneol=native#text/xml
+*.xslt text svneol=native#text/xml
+*.xul text svneol=native#text/xul
+*.yml text svneol=native#text/plain
+boost-no-inspect text svneol=native#text/plain
+CHANGES text svneol=native#text/plain
+COPYING text svneol=native#text/plain
+INSTALL text svneol=native#text/plain
+Jamfile text svneol=native#text/plain
+Jamroot text svneol=native#text/plain
+Jamfile.v2 text svneol=native#text/plain
+Jamrules text svneol=native#text/plain
+Makefile* text svneol=native#text/plain
+README text svneol=native#text/plain
+TODO text svneol=native#text/plain
+
+# Code formats
+*.c text svneol=native#text/plain
+*.cpp text svneol=native#text/plain
+*.h text svneol=native#text/plain
+*.hpp text svneol=native#text/plain
+*.ipp text svneol=native#text/plain
+*.tpp text svneol=native#text/plain
+*.jam text svneol=native#text/plain
+*.java text svneol=native#text/plain
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..3cdb7c4
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,280 @@
+# Copyright 2016, 2017, 2018 Peter Dimov
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
+
+language: cpp
+
+sudo: false
+
+branches:
+ only:
+ - master
+ - develop
+ - /feature\/.*/
+
+env:
+ matrix:
+ - BOGUS_JOB=true
+
+matrix:
+
+ exclude:
+ - env: BOGUS_JOB=true
+
+ include:
+ - os: linux
+ compiler: g++
+ env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11 VARIANT=debug,release
+
+ - os: linux
+ compiler: g++-4.4
+ env: TOOLSET=gcc COMPILER=g++-4.4 CXXSTD=98,0x
+ addons:
+ apt:
+ packages:
+ - g++-4.4
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - os: linux
+ compiler: g++-4.6
+ env: TOOLSET=gcc COMPILER=g++-4.6 CXXSTD=03,0x
+ addons:
+ apt:
+ packages:
+ - g++-4.6
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - os: linux
+ compiler: g++-4.7
+ env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=03,11
+ addons:
+ apt:
+ packages:
+ - g++-4.7
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - os: linux
+ compiler: g++-4.8
+ env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=03,11
+ addons:
+ apt:
+ packages:
+ - g++-4.8
+ sources:
+ - ubuntu-toolchain-r-test
+ - os: linux
+ compiler: g++-4.9
+ env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=03,11
+ addons:
+ apt:
+ packages:
+ - g++-4.9
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - os: linux
+ compiler: g++-5
+ env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=03,11,14,1z
+ addons:
+ apt:
+ packages:
+ - g++-5
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - os: linux
+ compiler: g++-6
+ env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=03,11,14,1z
+ addons:
+ apt:
+ packages:
+ - g++-6
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - os: linux
+ compiler: g++-7
+ env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 VARIANT=release
+ addons:
+ apt:
+ packages:
+ - g++-7
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - os: linux
+ compiler: g++-7
+ env: UBSAN=1 TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold
+ addons:
+ apt:
+ packages:
+ - g++-7
+ sources:
+ - ubuntu-toolchain-r-test
+
+ - os: linux
+ compiler: clang++
+ env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11 VARIANT=debug,release
+
+ - os: linux
+ compiler: /usr/bin/clang++
+ env: TOOLSET=clang COMPILER=/usr/bin/clang++ CXXSTD=03,11
+ addons:
+ apt:
+ packages:
+ - clang-3.3
+
+ - os: linux
+ compiler: /usr/bin/clang++
+ env: TOOLSET=clang COMPILER=/usr/bin/clang++ CXXSTD=03,11
+ addons:
+ apt:
+ packages:
+ - clang-3.4
+
+ - os: linux
+ compiler: clang++-3.5
+ env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=03,11,14,1z
+ addons:
+ apt:
+ packages:
+ - clang-3.5
+ - libstdc++-4.9-dev
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-precise-3.5
+
+ - os: linux
+ compiler: clang++-3.6
+ env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=03,11,14,1z
+ addons:
+ apt:
+ packages:
+ - clang-3.6
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-precise-3.6
+
+ - os: linux
+ compiler: clang++-3.7
+ env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=03,11,14,1z
+ addons:
+ apt:
+ packages:
+ - clang-3.7
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-precise-3.7
+
+ - os: linux
+ compiler: clang++-3.8
+ env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=03,11,14,1z
+ addons:
+ apt:
+ packages:
+ - clang-3.8
+ - libstdc++-4.9-dev
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-precise-3.8
+
+ - os: linux
+ compiler: clang++-3.9
+ env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=03,11,14,1z
+ addons:
+ apt:
+ packages:
+ - clang-3.9
+ - libstdc++-4.9-dev
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-precise-3.9
+
+ - os: linux
+ compiler: clang++-4.0
+ env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=03,11,14,1z
+ addons:
+ apt:
+ packages:
+ - clang-4.0
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-trusty-4.0
+
+ - os: linux
+ compiler: clang++-5.0
+ env: TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z VARIANT=release
+ addons:
+ apt:
+ packages:
+ - clang-5.0
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-trusty-5.0
+
+ - os: linux
+ compiler: clang++-5.0
+ env: UBSAN=1 TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1
+ addons:
+ apt:
+ packages:
+ - clang-5.0
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-trusty-5.0
+
+ - os: linux
+ compiler: clang++-libc++
+ env: TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,1z VARIANT=release
+ addons:
+ apt:
+ packages:
+ - libc++-dev
+
+ - os: linux
+ compiler: clang++-libc++
+ env: UBSAN=1 TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1
+ addons:
+ apt:
+ packages:
+ - libc++-dev
+
+ - os: osx
+ compiler: clang++
+ env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z
+
+install:
+ - BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
+ - cd ..
+ - git clone -b $BOOST_BRANCH https://github.com/boostorg/boost.git boost-root
+ - cd boost-root
+ - git submodule init libs/align
+ - git submodule init libs/assert
+ - git submodule init libs/atomic
+ - git submodule init libs/config
+ - git submodule init libs/container_hash
+ - git submodule init libs/core
+ - git submodule init libs/move
+ - git submodule init libs/predef
+ - git submodule init libs/static_assert
+ - git submodule init libs/throw_exception
+ - git submodule init libs/type_traits
+ - git submodule init libs/detail
+ - git submodule init libs/integer
+ - git submodule init tools/build
+ - git submodule update
+ - cp -r $TRAVIS_BUILD_DIR/* libs/smart_ptr
+ - ./bootstrap.sh
+ - ./b2 headers
+
+script:
+ - |-
+ echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
+ - ./b2 -j3 libs/smart_ptr/test toolset=$TOOLSET cxxstd=$CXXSTD ${VARIANT:+variant=$VARIANT} ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}
+
+notifications:
+ email:
+ on_success: always
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1301e79
--- /dev/null
+++ b/README.md
@@ -0,0 +1,6 @@
+# Boost.SmartPtr
+
+Branch | Travis | Appveyor
+---------|--------|---------
+Develop | [](https://travis-ci.org/boostorg/smart_ptr) | [](https://ci.appveyor.com/project/pdimov/smart-ptr)
+Master | [](https://travis-ci.org/boostorg/smart_ptr) | [](https://ci.appveyor.com/project/pdimov/smart-ptr)
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..8b7288c
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,74 @@
+# Copyright 2016-2018 Peter Dimov
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
+
+version: 1.0.{build}-{branch}
+
+shallow_clone: true
+
+branches:
+ only:
+ - master
+ - develop
+ - /feature\/.*/
+
+environment:
+ matrix:
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
+ TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0,msvc-12.0
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
+ TOOLSET: msvc-14.0
+ ADDRMD: 32,64
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+ TOOLSET: msvc-14.1
+ CXXSTD: 14,17
+ ADDRMD: 32,64
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
+ ADDPATH: C:\cygwin\bin;
+ TOOLSET: gcc
+ CXXSTD: 03,11,14,1z
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
+ ADDPATH: C:\cygwin64\bin;
+ TOOLSET: gcc
+ CXXSTD: 03,11,14,1z
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
+ ADDPATH: C:\mingw\bin;
+ TOOLSET: gcc
+ CXXSTD: 03,11,14,1z
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
+ ADDPATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;
+ TOOLSET: gcc
+ CXXSTD: 03,11,14,1z
+
+install:
+ - set BOOST_BRANCH=develop
+ - if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master
+ - cd ..
+ - git clone -b %BOOST_BRANCH% https://github.com/boostorg/boost.git boost-root
+ - cd boost-root
+ - git submodule init libs/align
+ - git submodule init libs/assert
+ - git submodule init libs/atomic
+ - git submodule init libs/config
+ - git submodule init libs/container_hash
+ - git submodule init libs/core
+ - git submodule init libs/move
+ - git submodule init libs/predef
+ - git submodule init libs/static_assert
+ - git submodule init libs/throw_exception
+ - git submodule init libs/type_traits
+ - git submodule init libs/detail
+ - git submodule init libs/integer
+ - git submodule init tools/build
+ - git submodule update
+ - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\smart_ptr
+ - cmd /c bootstrap
+ - b2 -d0 headers
+
+build: off
+
+test_script:
+ - PATH=%ADDPATH%%PATH%
+ - if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
+ - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
+ - b2 -j3 libs/smart_ptr/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release
diff --git a/doc/.gitignore b/doc/.gitignore
new file mode 100644
index 0000000..0972e2d
--- /dev/null
+++ b/doc/.gitignore
@@ -0,0 +1,2 @@
+/html/
+/pdf/
diff --git a/doc/Jamfile b/doc/Jamfile
new file mode 100644
index 0000000..b6d2c35
--- /dev/null
+++ b/doc/Jamfile
@@ -0,0 +1,26 @@
+# Copyright 2017 Peter Dimov
+#
+# Distributed under the Boost Software License, Version 1.0.
+#
+# See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt
+
+project doc/smart_ptr ;
+
+import asciidoctor ;
+
+html smart_ptr.html : smart_ptr.adoc ;
+
+install html_ : smart_ptr.html : <location>html ;
+
+pdf smart_ptr.pdf : smart_ptr.adoc ;
+explicit smart_ptr.pdf ;
+
+install pdf_ : smart_ptr.pdf : <location>pdf ;
+explicit pdf_ ;
+
+###############################################################################
+alias boostdoc ;
+explicit boostdoc ;
+alias boostrelease : html_ ;
+explicit boostrelease ;
diff --git a/doc/smart_ptr-docinfo-footer.html b/doc/smart_ptr-docinfo-footer.html
new file mode 100644
index 0000000..e81781d
--- /dev/null
+++ b/doc/smart_ptr-docinfo-footer.html
@@ -0,0 +1,6 @@
+<style>
+
+*:not(pre)>code { background: none; color: #600000; }
+table tr.even, table tr.alt, table tr:nth-of-type(even) { background: none; }
+
+</style>
diff --git a/doc/smart_ptr.adoc b/doc/smart_ptr.adoc
new file mode 100644
index 0000000..2c1a7cc
--- /dev/null
+++ b/doc/smart_ptr.adoc
@@ -0,0 +1,76 @@
+////
+Copyright 2017 Peter Dimov
+
+Distributed under the Boost Software License, Version 1.0.
+
+See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt
+////
+
+# Boost.SmartPtr: The Smart Pointer Library
+Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes
+:toc: left
+:toclevels: 2
+:idprefix:
+:listing-caption: Code Example
+:docinfo: private-footer
+
+:leveloffset: +1
+
+include::smart_ptr/introduction.adoc[]
+
+include::smart_ptr/scoped_ptr.adoc[]
+
+include::smart_ptr/scoped_array.adoc[]
+
+include::smart_ptr/shared_ptr.adoc[]
+
+include::smart_ptr/weak_ptr.adoc[]
+
+include::smart_ptr/make_shared.adoc[]
+
+include::smart_ptr/enable_shared_from_this.adoc[]
+
+include::smart_ptr/make_unique.adoc[]
+
+include::smart_ptr/intrusive_ptr.adoc[]
+
+include::smart_ptr/intrusive_ref_counter.adoc[]
+
+include::smart_ptr/local_shared_ptr.adoc[]
+
+include::smart_ptr/make_local_shared.adoc[]
+
+include::smart_ptr/pointer_cast.adoc[]
+
+include::smart_ptr/pointer_to_other.adoc[]
+
+include::smart_ptr/atomic_shared_ptr.adoc[]
+
+// appendix
+include::smart_ptr/techniques.adoc[]
+
+// appendix
+include::smart_ptr/history.adoc[]
+
+// appendix, deprecated
+include::smart_ptr/shared_array.adoc[]
+
+:leveloffset: -1
+
+[[copyright]]
+[appendix]
+## Copyright and License
+
+This documentation is
+
+* Copyright 1999 Greg Colvin
+* Copyright 1999 Beman Dawes
+* Copyright 2002 Darin Adler
+* Copyright 2003-2017 Peter Dimov
+* Copyright 2005, 2006 Ion Gaztañaga
+* Copyright 2008 Frank Mori Hess
+* Copyright 2012-2017 Glen Fernandes
+* Copyright 2013 Andrey Semashev
+
+and is distributed under the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0].
diff --git a/doc/smart_ptr/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`’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`’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>`’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;
+ }
+};
+```
diff --git a/example/scoped_ptr_example.cpp b/example/scoped_ptr_example.cpp
new file mode 100644
index 0000000..3dcfbb1
--- /dev/null
+++ b/example/scoped_ptr_example.cpp
@@ -0,0 +1,23 @@
+// Boost scoped_ptr_example implementation file -----------------------------//
+
+// Copyright Beman Dawes 2001. 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)
+
+
+// See http://www.boost.org/libs/smart_ptr for documentation.
+
+#include "scoped_ptr_example.hpp"
+#include <iostream>
+
+class example::implementation
+{
+ public:
+ ~implementation() { std::cout << "destroying implementation\n"; }
+};
+
+example::example() : _imp( new implementation ) {}
+
+void example::do_something() { std::cout << "did something\n"; }
+
+example::~example() {}
diff --git a/example/scoped_ptr_example.hpp b/example/scoped_ptr_example.hpp
new file mode 100644
index 0000000..0d9c603
--- /dev/null
+++ b/example/scoped_ptr_example.hpp
@@ -0,0 +1,29 @@
+// Boost scoped_ptr_example header file ------------------------------------//
+
+// Copyright Beman Dawes 2001. 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)
+
+
+// See http://www.boost.org/libs/smart_ptr for documentation.
+
+#include <boost/utility.hpp>
+#include <boost/scoped_ptr.hpp>
+
+// The point of this example is to prove that even though
+// example::implementation is an incomplete type in translation units using
+// this header, scoped_ptr< implementation > is still valid because the type
+// is complete where it counts - in the inplementation translation unit where
+// destruction is actually instantiated.
+
+class example : private boost::noncopyable
+{
+ public:
+ example();
+ ~example();
+ void do_something();
+ private:
+ class implementation;
+ boost::scoped_ptr< implementation > _imp; // hide implementation details
+};
+
diff --git a/example/scoped_ptr_example_test.cpp b/example/scoped_ptr_example_test.cpp
new file mode 100644
index 0000000..26b3a18
--- /dev/null
+++ b/example/scoped_ptr_example_test.cpp
@@ -0,0 +1,17 @@
+// Boost scoped_ptr_example_test main program -------------------------------//
+
+// Copyright Beman Dawes 2001. 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)
+
+
+// See http://www.boost.org/libs/smart_ptr for documentation.
+
+#include "scoped_ptr_example.hpp"
+
+int main()
+{
+ example my_example;
+ my_example.do_something();
+ return 0;
+}
diff --git a/example/shared_ptr_example.cpp b/example/shared_ptr_example.cpp
new file mode 100644
index 0000000..c3b1f3b
--- /dev/null
+++ b/example/shared_ptr_example.cpp
@@ -0,0 +1,95 @@
+// Boost shared_ptr_example.cpp --------------------------------------------//
+
+// Copyright Beman Dawes 2001. 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)
+
+
+// See http://www.boost.org/libs/smart_ptr for documentation.
+
+// Revision History
+// 21 May 01 Initial complete version (Beman Dawes)
+
+// The original code for this example appeared in the shared_ptr documentation.
+// Ray Gallimore pointed out that foo_set was missing a Compare template
+// argument, so would not work as intended. At that point the code was
+// turned into an actual .cpp file so it could be compiled and tested.
+
+#include <vector>
+#include <set>
+#include <iostream>
+#include <algorithm>
+#include <boost/shared_ptr.hpp>
+
+// The application will produce a series of
+// objects of type Foo which later must be
+// accessed both by occurrence (std::vector)
+// and by ordering relationship (std::set).
+
+struct Foo
+{
+ Foo( int _x ) : x(_x) {}
+ ~Foo() { std::cout << "Destructing a Foo with x=" << x << "\n"; }
+ int x;
+ /* ... */
+};
+
+typedef boost::shared_ptr<Foo> FooPtr;
+
+struct FooPtrOps
+{
+ bool operator()( const FooPtr & a, const FooPtr & b )
+ { return a->x > b->x; }
+ void operator()( const FooPtr & a )
+ { std::cout << a->x << "\n"; }
+};
+
+int main()
+{
+ std::vector<FooPtr> foo_vector;
+ std::set<FooPtr,FooPtrOps> foo_set; // NOT multiset!
+
+ FooPtr foo_ptr( new Foo( 2 ) );
+ foo_vector.push_back( foo_ptr );
+ foo_set.insert( foo_ptr );
+
+ foo_ptr.reset( new Foo( 1 ) );
+ foo_vector.push_back( foo_ptr );
+ foo_set.insert( foo_ptr );
+
+ foo_ptr.reset( new Foo( 3 ) );
+ foo_vector.push_back( foo_ptr );
+ foo_set.insert( foo_ptr );
+
+ foo_ptr.reset ( new Foo( 2 ) );
+ foo_vector.push_back( foo_ptr );
+ foo_set.insert( foo_ptr );
+
+ std::cout << "foo_vector:\n";
+ std::for_each( foo_vector.begin(), foo_vector.end(), FooPtrOps() );
+
+ std::cout << "\nfoo_set:\n";
+ std::for_each( foo_set.begin(), foo_set.end(), FooPtrOps() );
+ std::cout << "\n";
+
+// Expected output:
+//
+// foo_vector:
+// 2
+// 1
+// 3
+// 2
+//
+// foo_set:
+// 3
+// 2
+// 1
+//
+// Destructing a Foo with x=2
+// Destructing a Foo with x=1
+// Destructing a Foo with x=3
+// Destructing a Foo with x=2
+
+ return 0;
+}
+
diff --git a/example/shared_ptr_example2.cpp b/example/shared_ptr_example2.cpp
new file mode 100644
index 0000000..fdefc8d
--- /dev/null
+++ b/example/shared_ptr_example2.cpp
@@ -0,0 +1,22 @@
+// Boost shared_ptr_example2 implementation file -----------------------------//
+
+// Copyright Beman Dawes 2001. 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)
+
+
+// See http://www.boost.org/libs/smart_ptr for documentation.
+
+#include "shared_ptr_example2.hpp"
+#include <iostream>
+
+class example::implementation
+{
+ public:
+ ~implementation() { std::cout << "destroying implementation\n"; }
+};
+
+example::example() : _imp( new implementation ) {}
+
+void example::do_something()
+ { std::cout << "use_count() is " << _imp.use_count() << "\n"; }
diff --git a/example/shared_ptr_example2.hpp b/example/shared_ptr_example2.hpp
new file mode 100644
index 0000000..5ca7a07
--- /dev/null
+++ b/example/shared_ptr_example2.hpp
@@ -0,0 +1,31 @@
+// Boost shared_ptr_example2 header file -----------------------------------//
+
+// Copyright Beman Dawes 2001. 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)
+
+
+// See http://www.boost.org/libs/smart_ptr for documentation.
+
+#include <boost/shared_ptr.hpp>
+
+// This example demonstrates the handle/body idiom (also called pimpl and
+// several other names). It separates the interface (in this header file)
+// from the implementation (in shared_ptr_example2.cpp).
+
+// Note that even though example::implementation is an incomplete type in
+// some translation units using this header, shared_ptr< implementation >
+// is still valid because the type is complete where it counts - in the
+// shared_ptr_example2.cpp translation unit where functions requiring a
+// complete type are actually instantiated.
+
+class example
+{
+public:
+ example();
+ void do_something();
+private:
+ class implementation;
+ boost::shared_ptr< implementation > _imp; // hide implementation details
+};
+
diff --git a/example/shared_ptr_example2_test.cpp b/example/shared_ptr_example2_test.cpp
new file mode 100644
index 0000000..2702cb8
--- /dev/null
+++ b/example/shared_ptr_example2_test.cpp
@@ -0,0 +1,22 @@
+// Boost shared_ptr_example2_test main program ------------------------------//
+
+// Copyright Beman Dawes 2001. 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)
+
+
+// See http://www.boost.org/libs/smart_ptr for documentation.
+
+#include "shared_ptr_example2.hpp"
+
+int main()
+{
+ example a;
+ a.do_something();
+ example b(a);
+ b.do_something();
+ example c;
+ c = a;
+ c.do_something();
+ return 0;
+}
diff --git a/extras/src/sp_collector.cpp b/extras/src/sp_collector.cpp
new file mode 100644
index 0000000..bb69ae8
--- /dev/null
+++ b/extras/src/sp_collector.cpp
@@ -0,0 +1,270 @@
+//
+// sp_collector.cpp
+//
+// Copyright (c) 2002, 2003 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+
+#include <boost/assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_mutex.hpp>
+#include <cstdlib>
+#include <map>
+#include <deque>
+#include <iostream>
+
+typedef std::map< void const *, std::pair<void *, size_t> > map_type;
+
+static map_type & get_map()
+{
+ static map_type m;
+ return m;
+}
+
+typedef boost::detail::lightweight_mutex mutex_type;
+
+static mutex_type & get_mutex()
+{
+ static mutex_type m;
+ return m;
+}
+
+static void * init_mutex_before_main = &get_mutex();
+
+namespace
+{
+ class X;
+
+ struct count_layout
+ {
+ boost::detail::sp_counted_base * pi;
+ int id;
+ };
+
+ struct shared_ptr_layout
+ {
+ X * px;
+ count_layout pn;
+ };
+}
+
+// assume 4 byte alignment for pointers when scanning
+size_t const pointer_align = 4;
+
+typedef std::map<void const *, long> map2_type;
+
+static void scan_and_count(void const * area, size_t size, map_type const & m, map2_type & m2)
+{
+ unsigned char const * p = static_cast<unsigned char const *>(area);
+
+ for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)
+ {
+ shared_ptr_layout const * q = reinterpret_cast<shared_ptr_layout const *>(p);
+
+ if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m.count(q->pn.pi) != 0)
+ {
+ ++m2[q->pn.pi];
+ }
+ }
+}
+
+typedef std::deque<void const *> open_type;
+
+static void scan_and_mark(void const * area, size_t size, map2_type & m2, open_type & open)
+{
+ unsigned char const * p = static_cast<unsigned char const *>(area);
+
+ for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)
+ {
+ shared_ptr_layout const * q = reinterpret_cast<shared_ptr_layout const *>(p);
+
+ if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0)
+ {
+ open.push_back(q->pn.pi);
+ m2.erase(q->pn.pi);
+ }
+ }
+}
+
+static void find_unreachable_objects_impl(map_type const & m, map2_type & m2)
+{
+ // scan objects for shared_ptr members, compute internal counts
+
+ {
+ std::cout << "... " << m.size() << " objects in m.\n";
+
+ for(map_type::const_iterator i = m.begin(); i != m.end(); ++i)
+ {
+ boost::detail::sp_counted_base const * p = static_cast<boost::detail::sp_counted_base const *>(i->first);
+
+ BOOST_ASSERT(p->use_count() != 0); // there should be no inactive counts in the map
+
+ m2[ i->first ];
+
+ scan_and_count(i->second.first, i->second.second, m, m2);
+ }
+
+ std::cout << "... " << m2.size() << " objects in m2.\n";
+ }
+
+ // mark reachable objects
+
+ {
+ open_type open;
+
+ for(map2_type::iterator i = m2.begin(); i != m2.end(); ++i)
+ {
+ boost::detail::sp_counted_base const * p = static_cast<boost::detail::sp_counted_base const *>(i->first);
+ if(p->use_count() != i->second) open.push_back(p);
+ }
+
+ std::cout << "... " << open.size() << " objects in open.\n";
+
+ for(open_type::iterator j = open.begin(); j != open.end(); ++j)
+ {
+ m2.erase(*j);
+ }
+
+ while(!open.empty())
+ {
+ void const * p = open.front();
+ open.pop_front();
+
+ map_type::const_iterator i = m.find(p);
+ BOOST_ASSERT(i != m.end());
+
+ scan_and_mark(i->second.first, i->second.second, m2, open);
+ }
+ }
+
+ // m2 now contains the unreachable objects
+}
+
+std::size_t find_unreachable_objects(bool report)
+{
+ map2_type m2;
+
+#ifdef BOOST_HAS_THREADS
+
+ // This will work without the #ifdef, but some compilers warn
+ // that lock is not referenced
+
+ mutex_type::scoped_lock lock(get_mutex());
+
+#endif
+
+ map_type const & m = get_map();
+
+ find_unreachable_objects_impl(m, m2);
+
+ if(report)
+ {
+ for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j)
+ {
+ map_type::const_iterator i = m.find(j->first);
+ BOOST_ASSERT(i != m.end());
+ std::cout << "Unreachable object at " << i->second.first << ", " << i->second.second << " bytes long.\n";
+ }
+ }
+
+ return m2.size();
+}
+
+typedef std::deque< boost::shared_ptr<X> > free_list_type;
+
+static void scan_and_free(void * area, size_t size, map2_type const & m2, free_list_type & free)
+{
+ unsigned char * p = static_cast<unsigned char *>(area);
+
+ for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)
+ {
+ shared_ptr_layout * q = reinterpret_cast<shared_ptr_layout *>(p);
+
+ if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0 && q->px != 0)
+ {
+ boost::shared_ptr<X> * ppx = reinterpret_cast< boost::shared_ptr<X> * >(p);
+ free.push_back(*ppx);
+ ppx->reset();
+ }
+ }
+}
+
+void free_unreachable_objects()
+{
+ free_list_type free;
+
+ {
+ map2_type m2;
+
+#ifdef BOOST_HAS_THREADS
+
+ mutex_type::scoped_lock lock(get_mutex());
+
+#endif
+
+ map_type const & m = get_map();
+
+ find_unreachable_objects_impl(m, m2);
+
+ for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j)
+ {
+ map_type::const_iterator i = m.find(j->first);
+ BOOST_ASSERT(i != m.end());
+ scan_and_free(i->second.first, i->second.second, m2, free);
+ }
+ }
+
+ std::cout << "... about to free " << free.size() << " objects.\n";
+}
+
+// debug hooks
+
+namespace boost
+{
+
+void sp_scalar_constructor_hook(void *)
+{
+}
+
+void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn)
+{
+#ifdef BOOST_HAS_THREADS
+
+ mutex_type::scoped_lock lock(get_mutex());
+
+#endif
+
+ get_map()[pn] = std::make_pair(px, size);
+}
+
+void sp_scalar_destructor_hook(void *)
+{
+}
+
+void sp_scalar_destructor_hook(void *, std::size_t, void * pn)
+{
+#ifdef BOOST_HAS_THREADS
+
+ mutex_type::scoped_lock lock(get_mutex());
+
+#endif
+
+ get_map().erase(pn);
+}
+
+void sp_array_constructor_hook(void *)
+{
+}
+
+void sp_array_destructor_hook(void *)
+{
+}
+
+} // namespace boost
+
+#endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
diff --git a/extras/src/sp_debug_hooks.cpp b/extras/src/sp_debug_hooks.cpp
new file mode 100644
index 0000000..3193936
--- /dev/null
+++ b/extras/src/sp_debug_hooks.cpp
@@ -0,0 +1,243 @@
+//
+// sp_debug_hooks.cpp
+//
+// Copyright (c) 2002, 2003 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+
+#include <boost/assert.hpp>
+#include <new>
+#include <cstdlib>
+
+int const m = 2; // m * sizeof(int) must be aligned appropriately
+
+// magic values to mark heap blocks with
+
+int const allocated_scalar = 0x1234560C;
+int const allocated_array = 0x1234560A;
+int const adopted_scalar = 0x0567890C;
+int const adopted_array = 0x0567890A;
+int const deleted = 0x498769DE;
+
+using namespace std; // for compilers where things aren't in std
+
+// operator new
+
+static new_handler get_new_handler()
+{
+ new_handler p = set_new_handler(0);
+ set_new_handler(p);
+ return p;
+}
+
+static void * allocate(size_t n, int mark)
+{
+ int * pm;
+
+ for(;;)
+ {
+ pm = static_cast<int*>(malloc(n + m * sizeof(int)));
+
+ if(pm != 0) break;
+
+ if(new_handler pnh = get_new_handler())
+ {
+ pnh();
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ *pm = mark;
+
+ return pm + m;
+}
+
+void * operator new(size_t n) throw(bad_alloc)
+{
+ void * p = allocate(n, allocated_scalar);
+
+#if !defined(BOOST_NO_EXCEPTIONS)
+
+ if(p == 0) throw bad_alloc();
+
+#endif
+
+ return p;
+}
+
+#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
+
+void * operator new(size_t n, nothrow_t const &) throw()
+{
+ return allocate(n, allocated_scalar);
+}
+
+#endif
+
+void * operator new[](size_t n) throw(bad_alloc)
+{
+ void * p = allocate(n, allocated_array);
+
+#if !defined(BOOST_NO_EXCEPTIONS)
+
+ if(p == 0) throw bad_alloc();
+
+#endif
+
+ return p;
+}
+
+#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
+
+void * operator new[](size_t n, nothrow_t const &) throw()
+{
+ return allocate(n, allocated_array);
+}
+
+#endif
+
+// debug hooks
+
+namespace boost
+{
+
+void sp_scalar_constructor_hook(void * p)
+{
+ if(p == 0) return;
+
+ int * pm = static_cast<int*>(p);
+ pm -= m;
+
+ BOOST_ASSERT(*pm != adopted_scalar); // second smart pointer to the same address
+ BOOST_ASSERT(*pm != allocated_array); // allocated with new[]
+ BOOST_ASSERT(*pm == allocated_scalar); // not allocated with new
+
+ *pm = adopted_scalar;
+}
+
+void sp_scalar_constructor_hook(void * px, std::size_t, void *)
+{
+ sp_scalar_constructor_hook(px);
+}
+
+void sp_scalar_destructor_hook(void * p)
+{
+ if(p == 0) return;
+
+ int * pm = static_cast<int*>(p);
+ pm -= m;
+
+ BOOST_ASSERT(*pm == adopted_scalar); // attempt to destroy nonmanaged block
+
+ *pm = allocated_scalar;
+}
+
+void sp_scalar_destructor_hook(void * px, std::size_t, void *)
+{
+ sp_scalar_destructor_hook(px);
+}
+
+// It is not possible to handle the array hooks in a portable manner.
+// The implementation typically reserves a bit of storage for the number
+// of objects in the array, and the argument of the array hook isn't
+// equal to the return value of operator new[].
+
+void sp_array_constructor_hook(void * /* p */)
+{
+/*
+ if(p == 0) return;
+
+ // adjust p depending on the implementation
+
+ int * pm = static_cast<int*>(p);
+ pm -= m;
+
+ BOOST_ASSERT(*pm != adopted_array); // second smart array pointer to the same address
+ BOOST_ASSERT(*pm != allocated_scalar); // allocated with new
+ BOOST_ASSERT(*pm == allocated_array); // not allocated with new[]
+
+ *pm = adopted_array;
+*/
+}
+
+void sp_array_destructor_hook(void * /* p */)
+{
+/*
+ if(p == 0) return;
+
+ // adjust p depending on the implementation
+
+ int * pm = static_cast<int*>(p);
+ pm -= m;
+
+ BOOST_ASSERT(*pm == adopted_array); // attempt to destroy nonmanaged block
+
+ *pm = allocated_array;
+*/
+}
+
+} // namespace boost
+
+// operator delete
+
+void operator delete(void * p) throw()
+{
+ if(p == 0) return;
+
+ int * pm = static_cast<int*>(p);
+ pm -= m;
+
+ BOOST_ASSERT(*pm != deleted); // double delete
+ BOOST_ASSERT(*pm != adopted_scalar); // delete p.get();
+ BOOST_ASSERT(*pm != allocated_array); // allocated with new[]
+ BOOST_ASSERT(*pm == allocated_scalar); // not allocated with new
+
+ *pm = deleted;
+
+ free(pm);
+}
+
+#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
+
+void operator delete(void * p, nothrow_t const &) throw()
+{
+ ::operator delete(p);
+}
+
+#endif
+
+void operator delete[](void * p) throw()
+{
+ if(p == 0) return;
+
+ int * pm = static_cast<int*>(p);
+ pm -= m;
+
+ BOOST_ASSERT(*pm != deleted); // double delete
+ BOOST_ASSERT(*pm != adopted_scalar); // delete p.get();
+ BOOST_ASSERT(*pm != allocated_scalar); // allocated with new
+ BOOST_ASSERT(*pm == allocated_array); // not allocated with new[]
+
+ *pm = deleted;
+
+ free(pm);
+}
+
+#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
+
+void operator delete[](void * p, nothrow_t const &) throw()
+{
+ ::operator delete[](p);
+}
+
+#endif
+
+#endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
diff --git a/extras/test/shared_ptr_mt_test.cpp b/extras/test/shared_ptr_mt_test.cpp
new file mode 100644
index 0000000..8a50425
--- /dev/null
+++ b/extras/test/shared_ptr_mt_test.cpp
@@ -0,0 +1,82 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#endif
+
+// shared_ptr_mt_test.cpp - tests shared_ptr with multiple threads
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+// Copyright (c) 2008 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
+
+#include <boost/shared_ptr.hpp>
+#include <boost/bind.hpp>
+
+#include <vector>
+
+#include <cstdio>
+#include <ctime>
+
+#include <boost/detail/lightweight_thread.hpp>
+
+//
+
+int const n = 1024 * 1024;
+
+void test( boost::shared_ptr<int> const & pi )
+{
+ std::vector< boost::shared_ptr<int> > v;
+
+ for( int i = 0; i < n; ++i )
+ {
+ v.push_back( pi );
+ }
+}
+
+int const m = 16; // threads
+
+#if defined( BOOST_HAS_PTHREADS )
+
+char const * thmodel = "POSIX";
+
+#else
+
+char const * thmodel = "Windows";
+
+#endif
+
+int main()
+{
+ using namespace std; // printf, clock_t, clock
+
+ printf( "Using %s threads: %d threads, %d iterations: ", thmodel, m, n );
+
+ boost::shared_ptr<int> pi( new int(42) );
+
+ clock_t t = clock();
+
+ boost::detail::lw_thread_t a[ m ];
+
+ for( int i = 0; i < m; ++i )
+ {
+ boost::detail::lw_thread_create( a[ i ], boost::bind( test, pi ) );
+ }
+
+ for( int j = 0; j < m; ++j )
+ {
+ boost::detail::lw_thread_join( a[j] );
+ }
+
+ t = clock() - t;
+
+ printf( "\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC );
+
+ return 0;
+}
diff --git a/extras/test/shared_ptr_timing_test.cpp b/extras/test/shared_ptr_timing_test.cpp
new file mode 100644
index 0000000..79e62ff
--- /dev/null
+++ b/extras/test/shared_ptr_timing_test.cpp
@@ -0,0 +1,46 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#endif
+
+//
+// shared_ptr_timing_test.cpp - use to evaluate the impact of thread safety
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+//
+// 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)
+//
+
+#include <boost/shared_ptr.hpp>
+#include <iostream>
+#include <vector>
+#include <ctime>
+
+int const n = 8 * 1024 * 1024;
+
+int main()
+{
+ using namespace std;
+
+ std::vector< boost::shared_ptr<int> > v;
+ boost::shared_ptr<int> pi(new int);
+
+ clock_t t = clock();
+
+ for(int i = 0; i < n; ++i)
+ {
+ v.push_back(pi);
+ }
+
+ t = clock() - t;
+
+ std::cout << static_cast<double>(t) / CLOCKS_PER_SEC << '\n';
+
+ return 0;
+}
diff --git a/extras/test/sp_atomic_mt2_test.cpp b/extras/test/sp_atomic_mt2_test.cpp
new file mode 100644
index 0000000..750b0b2
--- /dev/null
+++ b/extras/test/sp_atomic_mt2_test.cpp
@@ -0,0 +1,247 @@
+
+// Copyright (c) 2008 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
+
+#include <boost/config.hpp>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/bind.hpp>
+
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/locks.hpp>
+
+#include <boost/detail/lightweight_mutex.hpp>
+#include <boost/detail/lightweight_thread.hpp>
+
+#include <vector>
+#include <numeric>
+#include <cstdio>
+#include <cstdlib>
+#include <cstddef>
+#include <ctime>
+
+//
+
+static void next_value( unsigned & v )
+{
+ v = v % 2? 3 * v + 1: v / 2;
+}
+
+struct X
+{
+ std::vector<unsigned> v_;
+
+ explicit X( std::size_t n ): v_( n )
+ {
+ for( std::size_t i = 0; i < n; ++i )
+ {
+ v_[ i ] = i;
+ }
+ }
+
+ unsigned get() const
+ {
+ return std::accumulate( v_.begin(), v_.end(), 0 );
+ }
+
+ void set()
+ {
+ std::for_each( v_.begin(), v_.end(), next_value );
+ }
+};
+
+static boost::shared_ptr<X> ps;
+
+static boost::detail::lightweight_mutex lm;
+static boost::shared_mutex rw;
+
+enum prim_type
+{
+ pt_mutex,
+ pt_rwlock,
+ pt_atomics
+};
+
+int read_access( prim_type pt )
+{
+ switch( pt )
+ {
+ case pt_mutex:
+ {
+ boost::detail::lightweight_mutex::scoped_lock lock( lm );
+ return ps->get();
+ }
+
+ case pt_rwlock:
+ {
+ boost::shared_lock<boost::shared_mutex> lock( rw );
+ return ps->get();
+ }
+
+ case pt_atomics:
+ {
+ boost::shared_ptr<X> p2 = boost::atomic_load( &ps );
+ return p2->get();
+ }
+ }
+}
+
+void write_access( prim_type pt )
+{
+ switch( pt )
+ {
+ case pt_mutex:
+ {
+ boost::detail::lightweight_mutex::scoped_lock lock( lm );
+ ps->set();
+ }
+ break;
+
+ case pt_rwlock:
+ {
+ boost::unique_lock<boost::shared_mutex> lock( rw );
+ ps->set();
+ }
+ break;
+
+ case pt_atomics:
+ {
+ boost::shared_ptr<X> p1 = boost::atomic_load( &ps );
+
+ for( ;; )
+ {
+ boost::shared_ptr<X> p2( new X( *p1 ) );
+ p2->set();
+
+ if( boost::atomic_compare_exchange( &ps, &p1, p2 ) ) break;
+ }
+ }
+ break;
+ }
+}
+
+void worker( int k, prim_type pt, int n, int r )
+{
+ ++r;
+
+ unsigned s = 0, nr = 0, nw = 0;
+
+ for( int i = 0; i < n; ++i )
+ {
+ if( i % r )
+ {
+ s += read_access( pt );
+ ++nr;
+ }
+ else
+ {
+ write_access( pt );
+ ++s;
+ ++nw;
+ }
+ }
+
+ printf( "Worker %2d: %u:%u, %10u\n", k, nr, nw, s );
+}
+
+#if defined( BOOST_HAS_PTHREADS )
+ char const * thmodel = "POSIX";
+#else
+ char const * thmodel = "Windows";
+#endif
+
+char const * pt_to_string( prim_type pt )
+{
+ switch( pt )
+ {
+ case pt_mutex:
+
+ return "mutex";
+
+ case pt_rwlock:
+
+ return "rwlock";
+
+ case pt_atomics:
+
+ return "atomics";
+ }
+}
+
+static void handle_pt_option( std::string const & opt, prim_type & pt, prim_type pt2 )
+{
+ if( opt == pt_to_string( pt2 ) )
+ {
+ pt = pt2;
+ }
+}
+
+static void handle_int_option( std::string const & opt, std::string const & prefix, int & k, int kmin, int kmax )
+{
+ if( opt.substr( 0, prefix.size() ) == prefix )
+ {
+ int v = atoi( opt.substr( prefix.size() ).c_str() );
+
+ if( v >= kmin && v <= kmax )
+ {
+ k = v;
+ }
+ }
+}
+
+int main( int ac, char const * av[] )
+{
+ using namespace std; // printf, clock_t, clock
+
+ int m = 4; // threads
+ int n = 10000; // vector size
+ int k = 1000000; // iterations
+ int r = 100; // read/write ratio, r:1
+
+ prim_type pt = pt_atomics;
+
+ for( int i = 1; i < ac; ++i )
+ {
+ handle_pt_option( av[i], pt, pt_mutex );
+ handle_pt_option( av[i], pt, pt_rwlock );
+ handle_pt_option( av[i], pt, pt_atomics );
+
+ handle_int_option( av[i], "n=", n, 1, INT_MAX );
+ handle_int_option( av[i], "size=", n, 1, INT_MAX );
+
+ handle_int_option( av[i], "k=", k, 1, INT_MAX );
+ handle_int_option( av[i], "iterations=", k, 1, INT_MAX );
+
+ handle_int_option( av[i], "m=", m, 1, INT_MAX );
+ handle_int_option( av[i], "threads=", m, 1, INT_MAX );
+
+ handle_int_option( av[i], "r=", r, 1, INT_MAX );
+ handle_int_option( av[i], "ratio=", r, 1, INT_MAX );
+ }
+
+ printf( "%s: threads=%d size=%d iterations=%d ratio=%d %s\n\n", thmodel, m, n, k, r, pt_to_string( pt ) );
+
+ ps.reset( new X( n ) );
+
+ clock_t t = clock();
+
+ std::vector<boost::detail::lw_thread_t> a( m );
+
+ for( int i = 0; i < m; ++i )
+ {
+ boost::detail::lw_thread_create( a[ i ], boost::bind( worker, i, pt, k, r ) );
+ }
+
+ for( int j = 0; j < m; ++j )
+ {
+ boost::detail::lw_thread_join( a[ j ] );
+ }
+
+ t = clock() - t;
+
+ double ts = static_cast<double>( t ) / CLOCKS_PER_SEC;
+ printf( "%.3f seconds, %.3f accesses per microsecond.\n", ts, m * k / ts / 1e+6 );
+}
diff --git a/extras/test/sp_atomic_mt_test.cpp b/extras/test/sp_atomic_mt_test.cpp
new file mode 100644
index 0000000..32c76c5
--- /dev/null
+++ b/extras/test/sp_atomic_mt_test.cpp
@@ -0,0 +1,191 @@
+
+// Copyright (c) 2008 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
+
+//#define USE_MUTEX
+//#define USE_RWLOCK
+
+#include <boost/config.hpp>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/bind.hpp>
+
+#if defined( USE_RWLOCK )
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/locks.hpp>
+#endif
+
+#include <boost/detail/lightweight_mutex.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/detail/lightweight_thread.hpp>
+
+#include <cstdio>
+#include <ctime>
+
+//
+
+int const n = 1024 * 1024;
+
+struct X
+{
+ int v_; // version
+
+ unsigned a_;
+ unsigned b_;
+
+ X(): v_( 0 ), a_( 1 ), b_( 1 )
+ {
+ }
+
+ int get() const
+ {
+ return a_ * 7 + b_ * 11;
+ }
+
+ void set()
+ {
+ int tmp = get();
+
+ b_ = a_;
+ a_ = tmp;
+
+ ++v_;
+ }
+};
+
+static boost::shared_ptr<X> ps( new X );
+
+static boost::detail::lightweight_mutex lm;
+
+#if defined( USE_RWLOCK )
+static boost::shared_mutex rw;
+#endif
+
+static int tr = 0;
+
+void reader( int r )
+{
+ int k = 0;
+ unsigned s = 0;
+
+ for( int i = 0; i < n; ++k )
+ {
+#if defined( USE_MUTEX )
+
+ boost::detail::lightweight_mutex::scoped_lock lock( lm );
+
+ s += ps->get();
+
+ BOOST_TEST( ps->v_ >= i );
+ i = ps->v_;
+
+#elif defined( USE_RWLOCK )
+
+ boost::shared_lock<boost::shared_mutex> lock( rw );
+
+ s += ps->get();
+
+ BOOST_TEST( ps->v_ >= i );
+ i = ps->v_;
+
+#else
+
+ boost::shared_ptr<X> p2 = boost::atomic_load( &ps );
+
+ s += p2->get();
+
+ BOOST_TEST( p2->v_ >= i );
+ i = p2->v_;
+
+#endif
+ }
+
+ printf( "Reader %d: %9d iterations (%6.3fx), %u\n", r, k, (double)k / n, s );
+
+ boost::detail::lightweight_mutex::scoped_lock lock( lm );
+ tr += k;
+}
+
+void writer()
+{
+ for( int i = 0; i < n; ++i )
+ {
+#if defined( USE_MUTEX )
+
+ boost::detail::lightweight_mutex::scoped_lock lock( lm );
+
+ BOOST_TEST( ps->v_ == i );
+ ps->set();
+
+#elif defined( USE_RWLOCK )
+
+ boost::unique_lock<boost::shared_mutex> lock( rw );
+
+ BOOST_TEST( ps->v_ == i );
+ ps->set();
+
+#else
+
+ boost::shared_ptr<X> p2( new X( *ps ) );
+
+ BOOST_TEST( p2->v_ == i );
+ p2->set();
+
+ boost::atomic_store( &ps, p2 );
+
+#endif
+ }
+}
+
+#if defined( BOOST_HAS_PTHREADS )
+ char const * thmodel = "POSIX";
+#else
+ char const * thmodel = "Windows";
+#endif
+
+int const mr = 8; // reader threads
+int const mw = 1; // writer thread
+
+#if defined( USE_MUTEX )
+ char const * prim = "mutex";
+#elif defined( USE_RWLOCK )
+ char const * prim = "rwlock";
+#else
+ char const * prim = "atomics";
+#endif
+
+int main()
+{
+ using namespace std; // printf, clock_t, clock
+
+ printf( "Using %s threads: %dR + %dW threads, %d iterations, %s\n\n", thmodel, mr, mw, n, prim );
+
+ clock_t t = clock();
+
+ boost::detail::lw_thread_t a[ mr+mw ];
+
+ for( int i = 0; i < mr; ++i )
+ {
+ boost::detail::lw_thread_create( a[ i ], boost::bind( reader, i ) );
+ }
+
+ for( int i = mr; i < mr+mw; ++i )
+ {
+ boost::detail::lw_thread_create( a[ i ], writer );
+ }
+
+ for( int j = 0; j < mr+mw; ++j )
+ {
+ boost::detail::lw_thread_join( a[ j ] );
+ }
+
+ t = clock() - t;
+
+ double ts = static_cast<double>( t ) / CLOCKS_PER_SEC;
+ printf( "%.3f seconds, %.3f reads per microsecond.\n", ts, tr / ts / 1e+6 );
+
+ return boost::report_errors();
+}
diff --git a/extras/test/weak_ptr_mt_test.cpp b/extras/test/weak_ptr_mt_test.cpp
new file mode 100644
index 0000000..5b11ff9
--- /dev/null
+++ b/extras/test/weak_ptr_mt_test.cpp
@@ -0,0 +1,122 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#endif
+
+// weak_ptr_mt_test.cpp
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+// Copyright 2005, 2008 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
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/bind.hpp>
+
+#include <vector>
+
+#include <cstdio>
+#include <ctime>
+#include <cstdlib>
+
+#include <boost/detail/lightweight_thread.hpp>
+
+//
+
+int const n = 16384;
+int const k = 512; // vector size
+int const m = 16; // threads
+
+void test( std::vector< boost::shared_ptr<int> > & v )
+{
+ using namespace std; // printf, rand
+
+ std::vector< boost::weak_ptr<int> > w( v.begin(), v.end() );
+
+ int s = 0, f = 0, r = 0;
+
+ for( int i = 0; i < n; ++i )
+ {
+ // randomly kill a pointer
+
+ v[ rand() % k ].reset();
+ ++s;
+
+ for( int j = 0; j < k; ++j )
+ {
+ if( boost::shared_ptr<int> px = w[ j ].lock() )
+ {
+ ++s;
+
+ if( rand() & 4 )
+ {
+ continue;
+ }
+
+ // rebind anyway with prob. 50% for add_ref_lock() against weak_release() contention
+ ++f;
+ }
+ else
+ {
+ ++r;
+ }
+
+ w[ j ] = v[ rand() % k ];
+ }
+ }
+
+ printf( "\n%d locks, %d forced rebinds, %d normal rebinds.", s, f, r );
+}
+
+#if defined( BOOST_HAS_PTHREADS )
+
+char const * thmodel = "POSIX";
+
+#else
+
+char const * thmodel = "Windows";
+
+#endif
+
+int main()
+{
+ using namespace std; // printf, clock_t, clock
+
+ printf("Using %s threads: %d threads, %d * %d iterations: ", thmodel, m, n, k );
+
+ std::vector< boost::shared_ptr<int> > v( k );
+
+ for( int i = 0; i < k; ++i )
+ {
+ v[ i ].reset( new int( 0 ) );
+ }
+
+ clock_t t = clock();
+
+ boost::detail::lw_thread_t a[ m ];
+
+ for( int i = 0; i < m; ++i )
+ {
+ boost::detail::lw_thread_create( a[ i ], boost::bind( test, v ) );
+ }
+
+ v.resize( 0 ); // kill original copies
+
+ for( int j = 0; j < m; ++j )
+ {
+ boost::detail::lw_thread_join( a[j] );
+ }
+
+ t = clock() - t;
+
+ printf("\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC);
+
+ return 0;
+}
diff --git a/extras/test/weak_ptr_timing_test.cpp b/extras/test/weak_ptr_timing_test.cpp
new file mode 100644
index 0000000..1c24b0a
--- /dev/null
+++ b/extras/test/weak_ptr_timing_test.cpp
@@ -0,0 +1,85 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#endif
+
+//
+// weak_ptr_timing_test.cpp
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+// Copyright 2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+#include <vector>
+#include <cstdio>
+#include <ctime>
+#include <cstdlib>
+
+//
+
+int const n = 29000;
+int const k = 2048;
+
+void test( std::vector< boost::shared_ptr<int> > & v )
+{
+ using namespace std; // printf, rand
+
+ std::vector< boost::weak_ptr<int> > w( v.begin(), v.end() );
+
+ int s = 0, r = 0;
+
+ for( int i = 0; i < n; ++i )
+ {
+ // randomly kill a pointer
+
+ v[ rand() % k ].reset();
+
+ for( int j = 0; j < k; ++j )
+ {
+ if( boost::shared_ptr<int> px = w[ j ].lock() )
+ {
+ ++s;
+ }
+ else
+ {
+ ++r;
+ w[ j ] = v[ rand() % k ];
+ }
+ }
+ }
+
+ printf( "\n%d locks, %d rebinds.", s, r );
+}
+
+int main()
+{
+ using namespace std; // printf, clock_t, clock
+
+ std::vector< boost::shared_ptr<int> > v( k );
+
+ for( int i = 0; i < k; ++i )
+ {
+ v[ i ].reset( new int( 0 ) );
+ }
+
+ clock_t t = clock();
+
+ test( v );
+
+ t = clock() - t;
+
+ printf( "\n\n%.3f seconds.\n", static_cast<double>( t ) / CLOCKS_PER_SEC );
+
+ return 0;
+}
diff --git a/include/boost/detail/atomic_count.hpp b/include/boost/detail/atomic_count.hpp
new file mode 100644
index 0000000..5411c7a
--- /dev/null
+++ b/include/boost/detail/atomic_count.hpp
@@ -0,0 +1,21 @@
+#ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
+#define BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/detail/atomic_count.hpp - thread/SMP safe reference counter
+//
+// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
+//
+// 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
+
+#include <boost/smart_ptr/detail/atomic_count.hpp>
+
+#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
diff --git a/include/boost/detail/lightweight_mutex.hpp b/include/boost/detail/lightweight_mutex.hpp
new file mode 100644
index 0000000..b7a7f6d
--- /dev/null
+++ b/include/boost/detail/lightweight_mutex.hpp
@@ -0,0 +1,22 @@
+#ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
+#define BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/detail/lightweight_mutex.hpp - lightweight mutex
+//
+// Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd.
+//
+// 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
+//
+
+#include <boost/smart_ptr/detail/lightweight_mutex.hpp>
+
+#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
diff --git a/include/boost/detail/lightweight_thread.hpp b/include/boost/detail/lightweight_thread.hpp
new file mode 100644
index 0000000..c2930d5
--- /dev/null
+++ b/include/boost/detail/lightweight_thread.hpp
@@ -0,0 +1,188 @@
+#ifndef BOOST_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED
+#define BOOST_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// boost/detail/lightweight_thread.hpp
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+// Copyright (c) 2008, 2018 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
+//
+//
+// typedef /*...*/ lw_thread_t; // as pthread_t
+// template<class F> int lw_thread_create( lw_thread_t & th, F f );
+// void lw_thread_join( lw_thread_t th );
+
+
+#include <boost/config.hpp>
+#include <memory>
+#include <cerrno>
+
+#if defined( BOOST_HAS_PTHREADS )
+
+#include <pthread.h>
+
+namespace boost
+{
+namespace detail
+{
+
+typedef ::pthread_t lw_thread_t;
+
+inline int lw_thread_create_( lw_thread_t* thread, const pthread_attr_t* attr, void* (*start_routine)( void* ), void* arg )
+{
+ return ::pthread_create( thread, attr, start_routine, arg );
+}
+
+inline void lw_thread_join( lw_thread_t th )
+{
+ ::pthread_join( th, 0 );
+}
+
+} // namespace detail
+} // namespace boost
+
+#else // defined( BOOST_HAS_PTHREADS )
+
+#include <windows.h>
+#include <process.h>
+
+namespace boost
+{
+namespace detail
+{
+
+typedef HANDLE lw_thread_t;
+
+inline int lw_thread_create_( lw_thread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg )
+{
+ HANDLE h = (HANDLE)_beginthreadex( 0, 0, start_routine, arg, 0, 0 );
+
+ if( h != 0 )
+ {
+ *thread = h;
+ return 0;
+ }
+ else
+ {
+ return EAGAIN;
+ }
+}
+
+inline void lw_thread_join( lw_thread_t thread )
+{
+ ::WaitForSingleObject( thread, INFINITE );
+ ::CloseHandle( thread );
+}
+
+} // namespace detail
+} // namespace boost
+
+#endif // defined( BOOST_HAS_PTHREADS )
+
+
+namespace boost
+{
+namespace detail
+{
+
+class lw_abstract_thread
+{
+public:
+
+ virtual ~lw_abstract_thread() {}
+ virtual void run() = 0;
+};
+
+#if defined( BOOST_HAS_PTHREADS )
+
+extern "C" void * lw_thread_routine( void * pv )
+{
+#if defined(BOOST_NO_CXX11_SMART_PTR)
+
+ std::auto_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
+
+#else
+
+ std::unique_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
+
+#endif
+
+ pt->run();
+
+ return 0;
+}
+
+#else
+
+unsigned __stdcall lw_thread_routine( void * pv )
+{
+#if defined(BOOST_NO_CXX11_SMART_PTR)
+
+ std::auto_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
+
+#else
+
+ std::unique_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
+
+#endif
+
+ pt->run();
+
+ return 0;
+}
+
+#endif
+
+template<class F> class lw_thread_impl: public lw_abstract_thread
+{
+public:
+
+ explicit lw_thread_impl( F f ): f_( f )
+ {
+ }
+
+ void run()
+ {
+ f_();
+ }
+
+private:
+
+ F f_;
+};
+
+template<class F> int lw_thread_create( lw_thread_t & th, F f )
+{
+#if defined(BOOST_NO_CXX11_SMART_PTR)
+
+ std::auto_ptr<lw_abstract_thread> p( new lw_thread_impl<F>( f ) );
+
+#else
+
+ std::unique_ptr<lw_abstract_thread> p( new lw_thread_impl<F>( f ) );
+
+#endif
+
+ int r = lw_thread_create_( &th, 0, lw_thread_routine, p.get() );
+
+ if( r == 0 )
+ {
+ p.release();
+ }
+
+ return r;
+}
+
+} // namespace detail
+} // namespace boost
+
+#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED
diff --git a/include/boost/detail/quick_allocator.hpp b/include/boost/detail/quick_allocator.hpp
new file mode 100644
index 0000000..d54b3a7
--- /dev/null
+++ b/include/boost/detail/quick_allocator.hpp
@@ -0,0 +1,23 @@
+#ifndef BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
+#define BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/quick_allocator.hpp
+//
+// Copyright (c) 2003 David Abrahams
+// Copyright (c) 2003 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+
+#include <boost/smart_ptr/detail/quick_allocator.hpp>
+
+#endif // #ifndef BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp
new file mode 100644
index 0000000..18b938d
--- /dev/null
+++ b/include/boost/enable_shared_from_this.hpp
@@ -0,0 +1,18 @@
+#ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
+#define BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
+
+//
+// enable_shared_from_this.hpp
+//
+// Copyright (c) 2002 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
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+#include <boost/smart_ptr/enable_shared_from_this.hpp>
+
+#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
diff --git a/include/boost/intrusive_ptr.hpp b/include/boost/intrusive_ptr.hpp
new file mode 100644
index 0000000..c43adbd
--- /dev/null
+++ b/include/boost/intrusive_ptr.hpp
@@ -0,0 +1,18 @@
+#ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED
+#define BOOST_INTRUSIVE_PTR_HPP_INCLUDED
+
+//
+// intrusive_ptr.hpp
+//
+// Copyright (c) 2001, 2002 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
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+#include <boost/smart_ptr/intrusive_ptr.hpp>
+
+#endif // #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED
diff --git a/include/boost/make_shared.hpp b/include/boost/make_shared.hpp
new file mode 100644
index 0000000..588fbfd
--- /dev/null
+++ b/include/boost/make_shared.hpp
@@ -0,0 +1,16 @@
+#ifndef BOOST_MAKE_SHARED_HPP_INCLUDED
+#define BOOST_MAKE_SHARED_HPP_INCLUDED
+
+// make_shared.hpp
+//
+// Copyright (c) 2007, 2008 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
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/make_shared.hpp>
+
+#endif // #ifndef BOOST_MAKE_SHARED_HPP_INCLUDED
diff --git a/include/boost/make_unique.hpp b/include/boost/make_unique.hpp
new file mode 100644
index 0000000..7189d6e
--- /dev/null
+++ b/include/boost/make_unique.hpp
@@ -0,0 +1,13 @@
+/*
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_MAKE_UNIQUE_HPP_INCLUDED
+#define BOOST_MAKE_UNIQUE_HPP_INCLUDED
+
+#include <boost/smart_ptr/make_unique.hpp>
+
+#endif
diff --git a/include/boost/pointer_cast.hpp b/include/boost/pointer_cast.hpp
new file mode 100644
index 0000000..d47327b
--- /dev/null
+++ b/include/boost/pointer_cast.hpp
@@ -0,0 +1,122 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005.
+// 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)
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_POINTER_CAST_HPP
+#define BOOST_POINTER_CAST_HPP
+
+#include <boost/config.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
+
+namespace boost {
+
+//static_pointer_cast overload for raw pointers
+template<class T, class U>
+inline T* static_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
+{
+ return static_cast<T*>(ptr);
+}
+
+//dynamic_pointer_cast overload for raw pointers
+template<class T, class U>
+inline T* dynamic_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
+{
+ return dynamic_cast<T*>(ptr);
+}
+
+//const_pointer_cast overload for raw pointers
+template<class T, class U>
+inline T* const_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
+{
+ return const_cast<T*>(ptr);
+}
+
+//reinterpret_pointer_cast overload for raw pointers
+template<class T, class U>
+inline T* reinterpret_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
+{
+ return reinterpret_cast<T*>(ptr);
+}
+
+} // namespace boost
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR )
+
+#include <boost/type_traits/has_virtual_destructor.hpp>
+#include <boost/static_assert.hpp>
+#include <memory>
+
+namespace boost {
+
+//static_pointer_cast overload for std::shared_ptr
+using std::static_pointer_cast;
+
+//dynamic_pointer_cast overload for std::shared_ptr
+using std::dynamic_pointer_cast;
+
+//const_pointer_cast overload for std::shared_ptr
+using std::const_pointer_cast;
+
+//reinterpret_pointer_cast overload for std::shared_ptr
+template<class T, class U> std::shared_ptr<T> reinterpret_pointer_cast(const std::shared_ptr<U> & r ) BOOST_SP_NOEXCEPT
+{
+ (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename std::shared_ptr<T>::element_type E;
+
+ E * p = reinterpret_cast< E* >( r.get() );
+ return std::shared_ptr<T>( r, p );
+}
+
+//static_pointer_cast overload for std::unique_ptr
+template<class T, class U> std::unique_ptr<T> static_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) static_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename std::unique_ptr<T>::element_type E;
+
+ return std::unique_ptr<T>( static_cast<E*>( r.release() ) );
+}
+
+//dynamic_pointer_cast overload for std::unique_ptr
+template<class T, class U> std::unique_ptr<T> dynamic_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
+
+ BOOST_STATIC_ASSERT_MSG( boost::has_virtual_destructor<T>::value, "The target of dynamic_pointer_cast must have a virtual destructor." );
+
+ T * p = dynamic_cast<T*>( r.get() );
+ if( p ) r.release();
+ return std::unique_ptr<T>( p );
+}
+
+//const_pointer_cast overload for std::unique_ptr
+template<class T, class U> std::unique_ptr<T> const_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) const_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename std::unique_ptr<T>::element_type E;
+
+ return std::unique_ptr<T>( const_cast<E*>( r.release() ) );
+}
+
+//reinterpret_pointer_cast overload for std::unique_ptr
+template<class T, class U> std::unique_ptr<T> reinterpret_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename std::unique_ptr<T>::element_type E;
+
+ return std::unique_ptr<T>( reinterpret_cast<E*>( r.release() ) );
+}
+
+} // namespace boost
+
+#endif // #if !defined( BOOST_NO_CXX11_SMART_PTR )
+
+#endif //BOOST_POINTER_CAST_HPP
diff --git a/include/boost/pointer_to_other.hpp b/include/boost/pointer_to_other.hpp
new file mode 100644
index 0000000..d7d455d
--- /dev/null
+++ b/include/boost/pointer_to_other.hpp
@@ -0,0 +1,55 @@
+#ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED
+#define BOOST_POINTER_TO_OTHER_HPP_INCLUDED
+
+//
+// pointer_to_other.hpp
+//
+// (C) Copyright Ion Gaztanaga 2005.
+// Copyright (c) 2005 Peter Dimov.
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+namespace boost
+{
+
+// Defines the same pointer type (raw or smart) to another pointee type
+
+template<class T, class U>
+struct pointer_to_other;
+
+template<class T, class U,
+ template<class> class Sp>
+struct pointer_to_other< Sp<T>, U >
+{
+ typedef Sp<U> type;
+};
+
+template<class T, class T2, class U,
+ template<class, class> class Sp>
+struct pointer_to_other< Sp<T, T2>, U >
+{
+ typedef Sp<U, T2> type;
+};
+
+template<class T, class T2, class T3, class U,
+ template<class, class, class> class Sp>
+struct pointer_to_other< Sp<T, T2, T3>, U >
+{
+ typedef Sp<U, T2, T3> type;
+};
+
+template<class T, class U>
+struct pointer_to_other< T*, U >
+{
+ typedef U* type;
+};
+
+} // namespace boost
+
+#endif // #ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED
diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp
new file mode 100644
index 0000000..d91889b
--- /dev/null
+++ b/include/boost/scoped_array.hpp
@@ -0,0 +1,15 @@
+#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
+#define BOOST_SCOPED_ARRAY_HPP_INCLUDED
+
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001, 2002 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/scoped_array.hpp>
+
+#endif // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
diff --git a/include/boost/scoped_ptr.hpp b/include/boost/scoped_ptr.hpp
new file mode 100644
index 0000000..334a22e
--- /dev/null
+++ b/include/boost/scoped_ptr.hpp
@@ -0,0 +1,15 @@
+#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
+#define BOOST_SCOPED_PTR_HPP_INCLUDED
+
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001, 2002 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/scoped_ptr.hpp>
+
+#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
diff --git a/include/boost/shared_array.hpp b/include/boost/shared_array.hpp
new file mode 100644
index 0000000..6804224
--- /dev/null
+++ b/include/boost/shared_array.hpp
@@ -0,0 +1,19 @@
+#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED
+#define BOOST_SHARED_ARRAY_HPP_INCLUDED
+
+//
+// shared_array.hpp
+//
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001, 2002 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+#include <boost/smart_ptr/shared_array.hpp>
+
+#endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED
diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp
new file mode 100644
index 0000000..cb01b26
--- /dev/null
+++ b/include/boost/shared_ptr.hpp
@@ -0,0 +1,19 @@
+#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
+#define BOOST_SHARED_PTR_HPP_INCLUDED
+
+//
+// shared_ptr.hpp
+//
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001-2008 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+
+#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
diff --git a/include/boost/smart_ptr.hpp b/include/boost/smart_ptr.hpp
new file mode 100644
index 0000000..6fabfc5
--- /dev/null
+++ b/include/boost/smart_ptr.hpp
@@ -0,0 +1,26 @@
+#ifndef BOOST_SMART_PTR_HPP_INCLUDED
+#define BOOST_SMART_PTR_HPP_INCLUDED
+
+//
+// smart_ptr.hpp
+//
+// For convenience, this header includes the rest of the smart
+// pointer library headers.
+//
+// Copyright (c) 2003 Peter Dimov Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/scoped_array.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/make_shared.hpp>
+
+#endif // #ifndef BOOST_SMART_PTR_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/allocate_local_shared_array.hpp b/include/boost/smart_ptr/allocate_local_shared_array.hpp
new file mode 100644
index 0000000..f46f110
--- /dev/null
+++ b/include/boost/smart_ptr/allocate_local_shared_array.hpp
@@ -0,0 +1,228 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
+#define BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
+
+#include <boost/smart_ptr/allocate_shared_array.hpp>
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+
+namespace boost {
+namespace detail {
+
+template<class>
+struct lsp_if_array { };
+
+template<class T>
+struct lsp_if_array<T[]> {
+ typedef boost::local_shared_ptr<T[]> type;
+};
+
+template<class>
+struct lsp_if_size_array { };
+
+template<class T, std::size_t N>
+struct lsp_if_size_array<T[N]> {
+ typedef boost::local_shared_ptr<T[N]> type;
+};
+
+class lsp_array_base
+ : public local_counted_base {
+public:
+ void set(sp_counted_base* base) BOOST_SP_NOEXCEPT {
+ count_ = shared_count(base);
+ }
+
+ virtual void local_cb_destroy() BOOST_SP_NOEXCEPT {
+ shared_count().swap(count_);
+ }
+
+ virtual shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT {
+ return count_;
+ }
+
+private:
+ shared_count count_;
+};
+
+template<class A>
+class lsp_array_state
+ : public sp_array_state<A> {
+public:
+ template<class U>
+ lsp_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
+ : sp_array_state<A>(other, size) { }
+
+ lsp_array_base& base() BOOST_SP_NOEXCEPT {
+ return base_;
+ }
+
+private:
+ lsp_array_base base_;
+};
+
+template<class A, std::size_t N>
+class lsp_size_array_state
+ : public sp_size_array_state<A, N> {
+public:
+ template<class U>
+ lsp_size_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
+ : sp_size_array_state<A, N>(other, size) { }
+
+ lsp_array_base& base() BOOST_SP_NOEXCEPT {
+ return base_;
+ }
+
+private:
+ lsp_array_base base_;
+};
+
+} /* detail */
+
+template<class T, class A>
+inline typename detail::lsp_if_array<T>::type
+allocate_local_shared(const A& allocator, std::size_t count)
+{
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::lsp_array_state<other> state;
+ typedef detail::sp_array_base<state> base;
+ std::size_t size = count * detail::sp_array_count<type>::value;
+ detail::sp_array_result<other, base> result(allocator, size);
+ base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size, start);
+ detail::lsp_array_base& local = node->state().base();
+ local.set(node);
+ result.release();
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), &local);
+}
+
+template<class T, class A>
+inline typename detail::lsp_if_size_array<T>::type
+allocate_local_shared(const A& allocator)
+{
+ enum {
+ size = detail::sp_array_count<T>::value
+ };
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::lsp_size_array_state<other, size> state;
+ typedef detail::sp_array_base<state> base;
+ detail::sp_array_result<other, base> result(allocator, size);
+ base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size, start);
+ detail::lsp_array_base& local = node->state().base();
+ local.set(node);
+ result.release();
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), &local);
+}
+
+template<class T, class A>
+inline typename detail::lsp_if_array<T>::type
+allocate_local_shared(const A& allocator, std::size_t count,
+ const typename detail::sp_array_element<T>::type& value)
+{
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::lsp_array_state<other> state;
+ typedef detail::sp_array_base<state> base;
+ std::size_t size = count * detail::sp_array_count<type>::value;
+ detail::sp_array_result<other, base> result(allocator, size);
+ base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size,
+ reinterpret_cast<const scalar*>(&value),
+ detail::sp_array_count<type>::value, start);
+ detail::lsp_array_base& local = node->state().base();
+ local.set(node);
+ result.release();
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), &local);
+}
+
+template<class T, class A>
+inline typename detail::lsp_if_size_array<T>::type
+allocate_local_shared(const A& allocator,
+ const typename detail::sp_array_element<T>::type& value)
+{
+ enum {
+ size = detail::sp_array_count<T>::value
+ };
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::lsp_size_array_state<other, size> state;
+ typedef detail::sp_array_base<state> base;
+ detail::sp_array_result<other, base> result(allocator, size);
+ base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size,
+ reinterpret_cast<const scalar*>(&value),
+ detail::sp_array_count<type>::value, start);
+ detail::lsp_array_base& local = node->state().base();
+ local.set(node);
+ result.release();
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), &local);
+}
+
+template<class T, class A>
+inline typename detail::lsp_if_array<T>::type
+allocate_local_shared_noinit(const A& allocator, std::size_t count)
+{
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::lsp_array_state<other> state;
+ typedef detail::sp_array_base<state, false> base;
+ std::size_t size = count * detail::sp_array_count<type>::value;
+ detail::sp_array_result<other, base> result(allocator, size);
+ base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
+ size, start);
+ detail::lsp_array_base& local = node->state().base();
+ local.set(node);
+ result.release();
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), &local);
+}
+
+template<class T, class A>
+inline typename detail::lsp_if_size_array<T>::type
+allocate_local_shared_noinit(const A& allocator)
+{
+ enum {
+ size = detail::sp_array_count<T>::value
+ };
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::lsp_size_array_state<other, size> state;
+ typedef detail::sp_array_base<state, false> base;
+ detail::sp_array_result<other, base> result(allocator, size);
+ base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
+ size, start);
+ detail::lsp_array_base& local = node->state().base();
+ local.set(node);
+ result.release();
+ return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), &local);
+}
+
+} /* boost */
+
+#endif
diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp
new file mode 100644
index 0000000..3406881
--- /dev/null
+++ b/include/boost/smart_ptr/allocate_shared_array.hpp
@@ -0,0 +1,703 @@
+/*
+Copyright 2012-2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
+#define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/has_trivial_assign.hpp>
+#include <boost/type_traits/has_trivial_constructor.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
+
+namespace boost {
+namespace detail {
+
+template<class>
+struct sp_if_array { };
+
+template<class T>
+struct sp_if_array<T[]> {
+ typedef boost::shared_ptr<T[]> type;
+};
+
+template<class>
+struct sp_if_size_array { };
+
+template<class T, std::size_t N>
+struct sp_if_size_array<T[N]> {
+ typedef boost::shared_ptr<T[N]> type;
+};
+
+template<class>
+struct sp_array_element { };
+
+template<class T>
+struct sp_array_element<T[]> {
+ typedef T type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_element<T[N]> {
+ typedef T type;
+};
+
+template<class T>
+struct sp_array_scalar {
+ typedef T type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_scalar<T[N]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_scalar<const T[N]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_scalar<volatile T[N]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_scalar<const volatile T[N]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_scalar<T[]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_scalar<const T[]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_scalar<volatile T[]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_scalar<const volatile T[]> {
+ typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_count {
+ enum {
+ value = 1
+ };
+};
+
+template<class T, std::size_t N>
+struct sp_array_count<T[N]> {
+ enum {
+ value = N * sp_array_count<T>::value
+ };
+};
+
+template<std::size_t N, std::size_t M>
+struct sp_max_size {
+ enum {
+ value = N < M ? M : N
+ };
+};
+
+template<std::size_t N, std::size_t M>
+struct sp_align_up {
+ enum {
+ value = (N + M - 1) & ~(M - 1)
+ };
+};
+
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+template<class A, class T>
+struct sp_bind_allocator {
+ typedef typename std::allocator_traits<A>::template rebind_alloc<T> type;
+};
+#else
+template<class A, class T>
+struct sp_bind_allocator {
+ typedef typename A::template rebind<T>::other type;
+};
+#endif
+
+template<class T>
+BOOST_CONSTEXPR inline std::size_t
+sp_objects(std::size_t size) BOOST_SP_NOEXCEPT
+{
+ return (size + sizeof(T) - 1) / sizeof(T);
+}
+
+template<bool, class = void>
+struct sp_enable { };
+
+template<class T>
+struct sp_enable<true, T> {
+ typedef T type;
+};
+
+template<bool E, class A, class T>
+inline typename sp_enable<!E && boost::has_trivial_destructor<T>::value>::type
+sp_array_destroy(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { }
+
+template<bool E, class A, class T>
+inline typename sp_enable<!E &&
+ !boost::has_trivial_destructor<T>::value>::type
+sp_array_destroy(A&, T* start, std::size_t size)
+{
+ while (size > 0) {
+ start[--size].~T();
+ }
+}
+
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+template<bool E, class A, class T>
+inline typename sp_enable<E>::type
+sp_array_destroy(A& allocator, T* start, std::size_t size)
+{
+ while (size > 0) {
+ std::allocator_traits<A>::destroy(allocator, start + --size);
+ }
+}
+#endif
+
+template<bool E, class A, class T>
+inline typename sp_enable<!E &&
+ boost::has_trivial_constructor<T>::value &&
+ boost::has_trivial_assign<T>::value &&
+ boost::has_trivial_destructor<T>::value>::type
+sp_array_construct(A&, T* start, std::size_t size)
+{
+ for (std::size_t i = 0; i < size; ++i) {
+ start[i] = T();
+ }
+}
+
+template<bool E, class A, class T>
+inline typename sp_enable<!E &&
+ boost::has_trivial_constructor<T>::value &&
+ boost::has_trivial_assign<T>::value &&
+ boost::has_trivial_destructor<T>::value>::type
+sp_array_construct(A&, T* start, std::size_t size, const T* list,
+ std::size_t count)
+{
+ for (std::size_t i = 0; i < size; ++i) {
+ start[i] = list[i % count];
+ }
+}
+
+#if !defined(BOOST_NO_EXCEPTIONS)
+template<bool E, class A, class T>
+inline typename sp_enable<!E &&
+ !(boost::has_trivial_constructor<T>::value &&
+ boost::has_trivial_assign<T>::value &&
+ boost::has_trivial_destructor<T>::value)>::type
+sp_array_construct(A& none, T* start, std::size_t size)
+{
+ std::size_t i = 0;
+ try {
+ for (; i < size; ++i) {
+ ::new(static_cast<void*>(start + i)) T();
+ }
+ } catch (...) {
+ sp_array_destroy<E>(none, start, i);
+ throw;
+ }
+}
+
+template<bool E, class A, class T>
+inline typename sp_enable<!E &&
+ !(boost::has_trivial_constructor<T>::value &&
+ boost::has_trivial_assign<T>::value &&
+ boost::has_trivial_destructor<T>::value)>::type
+sp_array_construct(A& none, T* start, std::size_t size, const T* list,
+ std::size_t count)
+{
+ std::size_t i = 0;
+ try {
+ for (; i < size; ++i) {
+ ::new(static_cast<void*>(start + i)) T(list[i % count]);
+ }
+ } catch (...) {
+ sp_array_destroy<E>(none, start, i);
+ throw;
+ }
+}
+#else
+template<bool E, class A, class T>
+inline typename sp_enable<!E &&
+ !(boost::has_trivial_constructor<T>::value &&
+ boost::has_trivial_assign<T>::value &&
+ boost::has_trivial_destructor<T>::value)>::type
+sp_array_construct(A&, T* start, std::size_t size)
+{
+ for (std::size_t i = 0; i < size; ++i) {
+ ::new(static_cast<void*>(start + i)) T();
+ }
+}
+
+template<bool E, class A, class T>
+inline typename sp_enable<!E &&
+ !(boost::has_trivial_constructor<T>::value &&
+ boost::has_trivial_assign<T>::value &&
+ boost::has_trivial_destructor<T>::value)>::type
+sp_array_construct(A&, T* start, std::size_t size, const T* list,
+ std::size_t count)
+{
+ for (std::size_t i = 0; i < size; ++i) {
+ ::new(static_cast<void*>(start + i)) T(list[i % count]);
+ }
+}
+#endif
+
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+#if !defined(BOOST_NO_EXCEPTIONS)
+template<bool E, class A, class T>
+inline typename sp_enable<E>::type
+sp_array_construct(A& allocator, T* start, std::size_t size)
+{
+ std::size_t i = 0;
+ try {
+ for (i = 0; i < size; ++i) {
+ std::allocator_traits<A>::construct(allocator, start + i);
+ }
+ } catch (...) {
+ sp_array_destroy<E>(allocator, start, i);
+ throw;
+ }
+}
+
+template<bool E, class A, class T>
+inline typename sp_enable<E>::type
+sp_array_construct(A& allocator, T* start, std::size_t size, const T* list,
+ std::size_t count)
+{
+ std::size_t i = 0;
+ try {
+ for (i = 0; i < size; ++i) {
+ std::allocator_traits<A>::construct(allocator, start + i,
+ list[i % count]);
+ }
+ } catch (...) {
+ sp_array_destroy<E>(allocator, start, i);
+ throw;
+ }
+}
+#else
+template<bool E, class A, class T>
+inline typename sp_enable<E>::type
+sp_array_construct(A& allocator, T* start, std::size_t size)
+{
+ for (std::size_t i = 0; i < size; ++i) {
+ std::allocator_traits<A>::construct(allocator, start + i);
+ }
+}
+
+template<bool E, class A, class T>
+inline typename sp_enable<E>::type
+sp_array_construct(A& allocator, T* start, std::size_t size, const T* list,
+ std::size_t count)
+{
+ for (std::size_t i = 0; i < size; ++i) {
+ std::allocator_traits<A>::construct(allocator, start + i,
+ list[i % count]);
+ }
+}
+#endif
+#endif
+
+template<class A, class T>
+inline typename sp_enable<boost::has_trivial_constructor<T>::value>::type
+sp_array_default(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { }
+
+#if !defined(BOOST_NO_EXCEPTIONS)
+template<class A, class T>
+inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type
+sp_array_default(A& none, T* start, std::size_t size)
+{
+ std::size_t i = 0;
+ try {
+ for (; i < size; ++i) {
+ ::new(static_cast<void*>(start + i)) T;
+ }
+ } catch (...) {
+ sp_array_destroy<false>(none, start, i);
+ throw;
+ }
+}
+#else
+template<bool E, class A, class T>
+inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type
+sp_array_default(A&, T* start, std::size_t size)
+{
+ for (std::size_t i = 0; i < size; ++i) {
+ ::new(static_cast<void*>(start + i)) T;
+ }
+}
+#endif
+
+template<class A>
+class sp_array_state {
+public:
+ typedef A type;
+
+ template<class U>
+ sp_array_state(const U& _allocator, std::size_t _size) BOOST_SP_NOEXCEPT
+ : allocator_(_allocator),
+ size_(_size) { }
+
+ A& allocator() BOOST_SP_NOEXCEPT {
+ return allocator_;
+ }
+
+ std::size_t size() const BOOST_SP_NOEXCEPT {
+ return size_;
+ }
+
+private:
+ A allocator_;
+ std::size_t size_;
+};
+
+template<class A, std::size_t N>
+class sp_size_array_state {
+public:
+ typedef A type;
+
+ template<class U>
+ sp_size_array_state(const U& _allocator, std::size_t) BOOST_SP_NOEXCEPT
+ : allocator_(_allocator) { }
+
+ A& allocator() BOOST_SP_NOEXCEPT {
+ return allocator_;
+ }
+
+ BOOST_CONSTEXPR std::size_t size() const BOOST_SP_NOEXCEPT {
+ return N;
+ }
+
+private:
+ A allocator_;
+};
+
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+template<class A>
+struct sp_use_construct {
+ enum {
+ value = true
+ };
+};
+
+template<class T>
+struct sp_use_construct<std::allocator<T> > {
+ enum {
+ value = false
+ };
+};
+#else
+template<class>
+struct sp_use_construct {
+ enum {
+ value = false
+ };
+};
+#endif
+
+template<class T, class U>
+struct sp_array_alignment {
+ enum {
+ value = sp_max_size<boost::alignment_of<T>::value,
+ boost::alignment_of<U>::value>::value
+ };
+};
+
+template<class T, class U>
+struct sp_array_offset {
+ enum {
+ value = sp_align_up<sizeof(T), sp_array_alignment<T, U>::value>::value
+ };
+};
+
+template<class T, class U>
+struct sp_array_storage {
+ enum {
+ value = sp_array_alignment<T, U>::value
+ };
+ typedef typename boost::type_with_alignment<value>::type type;
+};
+
+template<class T, class U>
+inline U*
+sp_array_start(void* base) BOOST_SP_NOEXCEPT
+{
+ enum {
+ size = sp_array_offset<T, U>::value
+ };
+ return reinterpret_cast<U*>(static_cast<char*>(base) + size);
+}
+
+template<class A, class T>
+class sp_array_creator {
+ typedef typename A::value_type scalar;
+
+ enum {
+ offset = sp_array_offset<T, scalar>::value
+ };
+
+ typedef typename sp_array_storage<T, scalar>::type type;
+
+public:
+ template<class U>
+ sp_array_creator(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
+ : other_(other),
+ size_(sp_objects<type>(offset + sizeof(scalar) * size)) { }
+
+ T* create() {
+ return reinterpret_cast<T*>(other_.allocate(size_));
+ }
+
+ void destroy(T* base) {
+ other_.deallocate(reinterpret_cast<type*>(base), size_);
+ }
+
+private:
+ typename sp_bind_allocator<A, type>::type other_;
+ std::size_t size_;
+};
+
+struct sp_default { };
+
+template<class T, bool E = sp_use_construct<T>::value>
+class sp_array_base
+ : public sp_counted_base {
+ typedef typename T::type allocator;
+
+public:
+ typedef typename allocator::value_type type;
+
+ template<class A>
+ sp_array_base(const A& other, std::size_t size, type* start)
+ : state_(other, size) {
+ sp_array_construct<E>(state_.allocator(), start, state_.size());
+ }
+
+ template<class A>
+ sp_array_base(const A& other, std::size_t size, const type* list,
+ std::size_t count, type* start)
+ : state_(other, size) {
+ sp_array_construct<E>(state_.allocator(), start, state_.size(), list,
+ count);
+ }
+
+ template<class A>
+ sp_array_base(sp_default, const A& other, std::size_t size, type* start)
+ : state_(other, size) {
+ sp_array_default(state_.allocator(), start, state_.size());
+ }
+
+ T& state() BOOST_SP_NOEXCEPT {
+ return state_;
+ }
+
+ virtual void dispose() {
+ sp_array_destroy<E>(state_.allocator(),
+ sp_array_start<sp_array_base, type>(this), state_.size());
+ }
+
+ virtual void destroy() {
+ sp_array_creator<allocator, sp_array_base> other(state_.allocator(),
+ state_.size());
+ this->~sp_array_base();
+ other.destroy(this);
+ }
+
+ virtual void* get_deleter(const sp_typeinfo&) {
+ return 0;
+ }
+
+ virtual void* get_local_deleter(const sp_typeinfo&) {
+ return 0;
+ }
+
+ virtual void* get_untyped_deleter() {
+ return 0;
+ }
+
+private:
+ T state_;
+};
+
+template<class A, class T>
+struct sp_array_result {
+public:
+ template<class U>
+ sp_array_result(const U& other, std::size_t size)
+ : creator_(other, size),
+ result_(creator_.create()) { }
+
+ ~sp_array_result() {
+ if (result_) {
+ creator_.destroy(result_);
+ }
+ }
+
+ T* get() const {
+ return result_;
+ }
+
+ void release() {
+ result_ = 0;
+ }
+
+private:
+ sp_array_result(const sp_array_result&);
+ sp_array_result& operator=(const sp_array_result&);
+
+ sp_array_creator<A, T> creator_;
+ T* result_;
+};
+
+} /* detail */
+
+template<class T, class A>
+inline typename detail::sp_if_array<T>::type
+allocate_shared(const A& allocator, std::size_t count)
+{
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::sp_array_state<other> state;
+ typedef detail::sp_array_base<state> base;
+ std::size_t size = count * detail::sp_array_count<type>::value;
+ detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_counted_base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size, start);
+ result.release();
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), detail::shared_count(node));
+}
+
+template<class T, class A>
+inline typename detail::sp_if_size_array<T>::type
+allocate_shared(const A& allocator)
+{
+ enum {
+ size = detail::sp_array_count<T>::value
+ };
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::sp_size_array_state<other, size> state;
+ typedef detail::sp_array_base<state> base;
+ detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_counted_base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size, start);
+ result.release();
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), detail::shared_count(node));
+}
+
+template<class T, class A>
+inline typename detail::sp_if_array<T>::type
+allocate_shared(const A& allocator, std::size_t count,
+ const typename detail::sp_array_element<T>::type& value)
+{
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::sp_array_state<other> state;
+ typedef detail::sp_array_base<state> base;
+ std::size_t size = count * detail::sp_array_count<type>::value;
+ detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_counted_base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size,
+ reinterpret_cast<const scalar*>(&value),
+ detail::sp_array_count<type>::value, start);
+ result.release();
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), detail::shared_count(node));
+}
+
+template<class T, class A>
+inline typename detail::sp_if_size_array<T>::type
+allocate_shared(const A& allocator,
+ const typename detail::sp_array_element<T>::type& value)
+{
+ enum {
+ size = detail::sp_array_count<T>::value
+ };
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::sp_size_array_state<other, size> state;
+ typedef detail::sp_array_base<state> base;
+ detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_counted_base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(allocator, size,
+ reinterpret_cast<const scalar*>(&value),
+ detail::sp_array_count<type>::value, start);
+ result.release();
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), detail::shared_count(node));
+}
+
+template<class T, class A>
+inline typename detail::sp_if_array<T>::type
+allocate_shared_noinit(const A& allocator, std::size_t count)
+{
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::sp_array_state<other> state;
+ typedef detail::sp_array_base<state, false> base;
+ std::size_t size = count * detail::sp_array_count<type>::value;
+ detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_counted_base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
+ size, start);
+ result.release();
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), detail::shared_count(node));
+}
+
+template<class T, class A>
+inline typename detail::sp_if_size_array<T>::type
+allocate_shared_noinit(const A& allocator)
+{
+ enum {
+ size = detail::sp_array_count<T>::value
+ };
+ typedef typename detail::sp_array_element<T>::type type;
+ typedef typename detail::sp_array_scalar<T>::type scalar;
+ typedef typename detail::sp_bind_allocator<A, scalar>::type other;
+ typedef detail::sp_size_array_state<other, size> state;
+ typedef detail::sp_array_base<state, false> base;
+ detail::sp_array_result<other, base> result(allocator, size);
+ detail::sp_counted_base* node = result.get();
+ scalar* start = detail::sp_array_start<base, scalar>(node);
+ ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
+ size, start);
+ result.release();
+ return shared_ptr<T>(detail::sp_internal_constructor_tag(),
+ reinterpret_cast<type*>(start), detail::shared_count(node));
+}
+
+} /* boost */
+
+#endif
diff --git a/include/boost/smart_ptr/atomic_shared_ptr.hpp b/include/boost/smart_ptr/atomic_shared_ptr.hpp
new file mode 100644
index 0000000..7c48507
--- /dev/null
+++ b/include/boost/smart_ptr/atomic_shared_ptr.hpp
@@ -0,0 +1,233 @@
+#ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED
+#define BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED
+
+//
+// atomic_shared_ptr.hpp
+//
+// 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/detail/spinlock.hpp>
+#include <cstring>
+
+namespace boost
+{
+
+template<class T> class atomic_shared_ptr
+{
+private:
+
+ boost::shared_ptr<T> p_;
+
+ mutable boost::detail::spinlock l_;
+
+ atomic_shared_ptr(const atomic_shared_ptr&);
+ atomic_shared_ptr& operator=(const atomic_shared_ptr&);
+
+private:
+
+ bool compare_exchange( shared_ptr<T>& v, shared_ptr<T> w ) BOOST_SP_NOEXCEPT
+ {
+ l_.lock();
+
+ if( p_._internal_equiv( v ) )
+ {
+ p_.swap( w );
+
+ l_.unlock();
+ return true;
+ }
+ else
+ {
+ shared_ptr<T> tmp( p_ );
+
+ l_.unlock();
+
+ tmp.swap( v );
+ return false;
+ }
+ }
+
+public:
+
+#if !defined( BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX ) && !defined( BOOST_NO_CXX11_CONSTEXPR )
+
+ constexpr atomic_shared_ptr() BOOST_SP_NOEXCEPT: l_ BOOST_DETAIL_SPINLOCK_INIT
+ {
+ }
+
+#else
+
+ atomic_shared_ptr() BOOST_SP_NOEXCEPT
+ {
+ boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
+ std::memcpy( &l_, &init, sizeof( init ) );
+ }
+
+#endif
+
+ atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+ : p_( std::move( p ) )
+#else
+ : p_( p )
+#endif
+ {
+ boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
+ std::memcpy( &l_, &init, sizeof( init ) );
+ }
+
+ atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
+ {
+ boost::detail::spinlock::scoped_lock lock( l_ );
+ p_.swap( r );
+
+ return *this;
+ }
+
+ BOOST_CONSTEXPR bool is_lock_free() const BOOST_SP_NOEXCEPT
+ {
+ return false;
+ }
+
+ shared_ptr<T> load() const BOOST_SP_NOEXCEPT
+ {
+ boost::detail::spinlock::scoped_lock lock( l_ );
+ return p_;
+ }
+
+ template<class M> shared_ptr<T> load( M ) const BOOST_SP_NOEXCEPT
+ {
+ boost::detail::spinlock::scoped_lock lock( l_ );
+ return p_;
+ }
+
+ operator shared_ptr<T>() const BOOST_SP_NOEXCEPT
+ {
+ boost::detail::spinlock::scoped_lock lock( l_ );
+ return p_;
+ }
+
+ void store( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
+ {
+ boost::detail::spinlock::scoped_lock lock( l_ );
+ p_.swap( r );
+ }
+
+ template<class M> void store( shared_ptr<T> r, M ) BOOST_SP_NOEXCEPT
+ {
+ boost::detail::spinlock::scoped_lock lock( l_ );
+ p_.swap( r );
+ }
+
+ shared_ptr<T> exchange( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
+ {
+ {
+ boost::detail::spinlock::scoped_lock lock( l_ );
+ p_.swap( r );
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ return std::move( r );
+
+#else
+
+ return r;
+
+#endif
+ }
+
+ template<class M> shared_ptr<T> exchange( shared_ptr<T> r, M ) BOOST_SP_NOEXCEPT
+ {
+ {
+ boost::detail::spinlock::scoped_lock lock( l_ );
+ p_.swap( r );
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ return std::move( r );
+
+#else
+
+ return r;
+
+#endif
+ }
+
+ template<class M> bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, M, M ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, w );
+ }
+
+ template<class M> bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, M ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, w );
+ }
+
+ bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, w );
+ }
+
+ template<class M> bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, M, M ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, w );
+ }
+
+ template<class M> bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, M ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, w );
+ }
+
+ bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, w );
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class M> bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, M, M ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, std::move( w ) );
+ }
+
+ template<class M> bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, M ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, std::move( w ) );
+ }
+
+ bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, std::move( w ) );
+ }
+
+ template<class M> bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, M, M ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, std::move( w ) );
+ }
+
+ template<class M> bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, M ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, std::move( w ) );
+ }
+
+ bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w ) BOOST_SP_NOEXCEPT
+ {
+ return compare_exchange( v, std::move( w ) );
+ }
+
+#endif
+};
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/bad_weak_ptr.hpp b/include/boost/smart_ptr/bad_weak_ptr.hpp
new file mode 100644
index 0000000..b086be5
--- /dev/null
+++ b/include/boost/smart_ptr/bad_weak_ptr.hpp
@@ -0,0 +1,70 @@
+#ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED
+#define BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/smart_ptr/bad_weak_ptr.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+//
+// 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)
+//
+
+#include <boost/config.hpp>
+#include <exception>
+
+#ifdef __BORLANDC__
+# pragma warn -8026 // Functions with excep. spec. are not expanded inline
+#endif
+
+namespace boost
+{
+
+// The standard library that comes with Borland C++ 5.5.1, 5.6.4
+// defines std::exception and its members as having C calling
+// convention (-pc). When the definition of bad_weak_ptr
+// is compiled with -ps, the compiler issues an error.
+// Hence, the temporary #pragma option -pc below.
+
+#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564
+# pragma option push -pc
+#endif
+
+#if defined(BOOST_CLANG)
+// Intel C++ on Mac defines __clang__ but doesn't support the pragma
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wweak-vtables"
+#endif
+
+class bad_weak_ptr: public std::exception
+{
+public:
+
+ virtual char const * what() const throw()
+ {
+ return "tr1::bad_weak_ptr";
+ }
+};
+
+#if defined(BOOST_CLANG)
+# pragma clang diagnostic pop
+#endif
+
+#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564
+# pragma option pop
+#endif
+
+} // namespace boost
+
+#ifdef __BORLANDC__
+# pragma warn .8026 // Functions with excep. spec. are not expanded inline
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/atomic_count.hpp b/include/boost/smart_ptr/detail/atomic_count.hpp
new file mode 100644
index 0000000..6e4f71a
--- /dev/null
+++ b/include/boost/smart_ptr/detail/atomic_count.hpp
@@ -0,0 +1,99 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/detail/atomic_count.hpp - thread/SMP safe reference counter
+//
+// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
+// Copyright (c) 2013 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// typedef <implementation-defined> boost::detail::atomic_count;
+//
+// atomic_count a(n);
+//
+// (n is convertible to long)
+//
+// Effects: Constructs an atomic_count with an initial value of n
+//
+// a;
+//
+// Returns: (long) the current value of a
+// Memory Ordering: acquire
+//
+// ++a;
+//
+// Effects: Atomically increments the value of a
+// Returns: (long) the new value of a
+// Memory Ordering: acquire/release
+//
+// --a;
+//
+// Effects: Atomically decrements the value of a
+// Returns: (long) the new value of a
+// Memory Ordering: acquire/release
+//
+
+#include <boost/config.hpp>
+#include <boost/smart_ptr/detail/sp_has_sync.hpp>
+
+#if defined( BOOST_AC_DISABLE_THREADS )
+# include <boost/smart_ptr/detail/atomic_count_nt.hpp>
+
+#elif defined( BOOST_AC_USE_STD_ATOMIC )
+# include <boost/smart_ptr/detail/atomic_count_std_atomic.hpp>
+
+#elif defined( BOOST_AC_USE_SPINLOCK )
+# include <boost/smart_ptr/detail/atomic_count_spin.hpp>
+
+#elif defined( BOOST_AC_USE_PTHREADS )
+# include <boost/smart_ptr/detail/atomic_count_pt.hpp>
+
+#elif defined( BOOST_SP_DISABLE_THREADS )
+# include <boost/smart_ptr/detail/atomic_count_nt.hpp>
+
+#elif defined( BOOST_SP_USE_STD_ATOMIC )
+# include <boost/smart_ptr/detail/atomic_count_std_atomic.hpp>
+
+#elif defined( BOOST_SP_USE_SPINLOCK )
+# include <boost/smart_ptr/detail/atomic_count_spin.hpp>
+
+#elif defined( BOOST_SP_USE_PTHREADS )
+# include <boost/smart_ptr/detail/atomic_count_pt.hpp>
+
+#elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 )
+# include <boost/smart_ptr/detail/atomic_count_nt.hpp>
+
+#elif !defined( BOOST_NO_CXX11_HDR_ATOMIC )
+# include <boost/smart_ptr/detail/atomic_count_std_atomic.hpp>
+
+#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined( __PATHSCALE__ )
+# include <boost/smart_ptr/detail/atomic_count_gcc_x86.hpp>
+
+#elif defined( BOOST_SP_HAS_SYNC )
+# include <boost/smart_ptr/detail/atomic_count_sync.hpp>
+
+#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# include <boost/smart_ptr/detail/atomic_count_win32.hpp>
+
+#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
+# include <boost/smart_ptr/detail/atomic_count_gcc.hpp>
+
+#elif !defined( BOOST_HAS_THREADS )
+# include <boost/smart_ptr/detail/atomic_count_nt.hpp>
+
+#else
+# include <boost/smart_ptr/detail/atomic_count_spin.hpp>
+
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/atomic_count_gcc.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp
new file mode 100644
index 0000000..df7e323
--- /dev/null
+++ b/include/boost/smart_ptr/detail/atomic_count_gcc.hpp
@@ -0,0 +1,72 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED
+
+//
+// boost/detail/atomic_count_gcc.hpp
+//
+// atomic_count for GNU libstdc++ v3
+//
+// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html
+//
+// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
+// Copyright (c) 2002 Lars Gullik Bjønnes <larsbj@lyx.org>
+// Copyright 2003-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#if __GNUC__ * 100 + __GNUC_MINOR__ >= 402
+# include <ext/atomicity.h>
+#else
+# include <bits/atomicity.h>
+#endif
+
+namespace boost
+{
+
+namespace detail
+{
+
+#if defined(__GLIBCXX__) // g++ 3.4+
+
+using __gnu_cxx::__atomic_add;
+using __gnu_cxx::__exchange_and_add;
+
+#endif
+
+class atomic_count
+{
+public:
+
+ explicit atomic_count( long v ) : value_( v ) {}
+
+ long operator++()
+ {
+ return __exchange_and_add( &value_, +1 ) + 1;
+ }
+
+ long operator--()
+ {
+ return __exchange_and_add( &value_, -1 ) - 1;
+ }
+
+ operator long() const
+ {
+ return __exchange_and_add( &value_, 0 );
+ }
+
+private:
+
+ atomic_count(atomic_count const &);
+ atomic_count & operator=(atomic_count const &);
+
+ mutable _Atomic_word value_;
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp
new file mode 100644
index 0000000..5c44d7c
--- /dev/null
+++ b/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp
@@ -0,0 +1,77 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED
+
+//
+// boost/detail/atomic_count_gcc_x86.hpp
+//
+// atomic_count for g++ on 486+/AMD64
+//
+// Copyright 2007 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)
+//
+
+namespace boost
+{
+
+namespace detail
+{
+
+class atomic_count
+{
+public:
+
+ explicit atomic_count( long v ) : value_( static_cast< int >( v ) ) {}
+
+ long operator++()
+ {
+ return atomic_exchange_and_add( &value_, +1 ) + 1;
+ }
+
+ long operator--()
+ {
+ return atomic_exchange_and_add( &value_, -1 ) - 1;
+ }
+
+ operator long() const
+ {
+ return atomic_exchange_and_add( &value_, 0 );
+ }
+
+private:
+
+ atomic_count(atomic_count const &);
+ atomic_count & operator=(atomic_count const &);
+
+ mutable int value_;
+
+private:
+
+ static int atomic_exchange_and_add( int * pw, int dv )
+ {
+ // int r = *pw;
+ // *pw += dv;
+ // return r;
+
+ int r;
+
+ __asm__ __volatile__
+ (
+ "lock\n\t"
+ "xadd %1, %0":
+ "+m"( *pw ), "=r"( r ): // outputs (%0, %1)
+ "1"( dv ): // inputs (%2 == %1)
+ "memory", "cc" // clobbers
+ );
+
+ return r;
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/atomic_count_nt.hpp b/include/boost/smart_ptr/detail/atomic_count_nt.hpp
new file mode 100644
index 0000000..3bbf138
--- /dev/null
+++ b/include/boost/smart_ptr/detail/atomic_count_nt.hpp
@@ -0,0 +1,59 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED
+
+//
+// boost/detail/atomic_count_nt.hpp
+//
+// Trivial atomic_count for the single-threaded case
+//
+// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html
+//
+// Copyright 2013 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+
+namespace boost
+{
+
+namespace detail
+{
+
+class atomic_count
+{
+public:
+
+ explicit atomic_count( long v ): value_( v )
+ {
+ }
+
+ long operator++()
+ {
+ return ++value_;
+ }
+
+ long operator--()
+ {
+ return --value_;
+ }
+
+ operator long() const
+ {
+ return value_;
+ }
+
+private:
+
+ atomic_count(atomic_count const &);
+ atomic_count & operator=(atomic_count const &);
+
+ long value_;
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/atomic_count_pt.hpp b/include/boost/smart_ptr/detail/atomic_count_pt.hpp
new file mode 100644
index 0000000..f99b910
--- /dev/null
+++ b/include/boost/smart_ptr/detail/atomic_count_pt.hpp
@@ -0,0 +1,97 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
+
+//
+// boost/detail/atomic_count_pthreads.hpp
+//
+// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
+//
+// 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)
+//
+
+#include <boost/assert.hpp>
+#include <pthread.h>
+
+//
+// The generic pthread_mutex-based implementation sometimes leads to
+// inefficiencies. Example: a class with two atomic_count members
+// can get away with a single mutex.
+//
+// Users can detect this situation by checking BOOST_AC_USE_PTHREADS.
+//
+
+namespace boost
+{
+
+namespace detail
+{
+
+class atomic_count
+{
+private:
+
+ class scoped_lock
+ {
+ public:
+
+ scoped_lock(pthread_mutex_t & m): m_(m)
+ {
+ BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
+ }
+
+ ~scoped_lock()
+ {
+ BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
+ }
+
+ private:
+
+ pthread_mutex_t & m_;
+ };
+
+public:
+
+ explicit atomic_count(long v): value_(v)
+ {
+ BOOST_VERIFY( pthread_mutex_init( &mutex_, 0 ) == 0 );
+ }
+
+ ~atomic_count()
+ {
+ BOOST_VERIFY( pthread_mutex_destroy( &mutex_ ) == 0 );
+ }
+
+ long operator++()
+ {
+ scoped_lock lock(mutex_);
+ return ++value_;
+ }
+
+ long operator--()
+ {
+ scoped_lock lock(mutex_);
+ return --value_;
+ }
+
+ operator long() const
+ {
+ scoped_lock lock(mutex_);
+ return value_;
+ }
+
+private:
+
+ atomic_count(atomic_count const &);
+ atomic_count & operator=(atomic_count const &);
+
+ mutable pthread_mutex_t mutex_;
+ long value_;
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/atomic_count_solaris.hpp b/include/boost/smart_ptr/detail/atomic_count_solaris.hpp
new file mode 100644
index 0000000..a13bcfb
--- /dev/null
+++ b/include/boost/smart_ptr/detail/atomic_count_solaris.hpp
@@ -0,0 +1,59 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED
+
+//
+// boost/detail/atomic_count_solaris.hpp
+// based on: boost/detail/atomic_count_win32.hpp
+//
+// Copyright (c) 2001-2005 Peter Dimov
+// Copyright (c) 2006 Michael van der Westhuizen
+//
+// 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)
+//
+
+#include <atomic.h>
+
+namespace boost
+{
+
+namespace detail
+{
+
+class atomic_count
+{
+public:
+
+ explicit atomic_count( uint32_t v ): value_( v )
+ {
+ }
+
+ long operator++()
+ {
+ return atomic_inc_32_nv( &value_ );
+ }
+
+ long operator--()
+ {
+ return atomic_dec_32_nv( &value_ );
+ }
+
+ operator uint32_t() const
+ {
+ return static_cast<uint32_t const volatile &>( value_ );
+ }
+
+private:
+
+ atomic_count( atomic_count const & );
+ atomic_count & operator=( atomic_count const & );
+
+ uint32_t value_;
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/atomic_count_spin.hpp b/include/boost/smart_ptr/detail/atomic_count_spin.hpp
new file mode 100644
index 0000000..8e62349
--- /dev/null
+++ b/include/boost/smart_ptr/detail/atomic_count_spin.hpp
@@ -0,0 +1,62 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED
+
+//
+// boost/detail/atomic_count_spin.hpp
+//
+// Copyright (c) 2013 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+
+#include <boost/smart_ptr/detail/spinlock_pool.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+class atomic_count
+{
+private:
+
+public:
+
+ explicit atomic_count( long v ): value_( v )
+ {
+ }
+
+ long operator++()
+ {
+ spinlock_pool<0>::scoped_lock lock( &value_ );
+ return ++value_;
+ }
+
+ long operator--()
+ {
+ spinlock_pool<0>::scoped_lock lock( &value_ );
+ return --value_;
+ }
+
+ operator long() const
+ {
+ spinlock_pool<0>::scoped_lock lock( &value_ );
+ return value_;
+ }
+
+private:
+
+ atomic_count(atomic_count const &);
+ atomic_count & operator=(atomic_count const &);
+
+ long value_;
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/atomic_count_std_atomic.hpp b/include/boost/smart_ptr/detail/atomic_count_std_atomic.hpp
new file mode 100644
index 0000000..55b9998
--- /dev/null
+++ b/include/boost/smart_ptr/detail/atomic_count_std_atomic.hpp
@@ -0,0 +1,60 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED
+
+//
+// boost/detail/atomic_count_std_atomic.hpp
+//
+// atomic_count for std::atomic
+//
+// Copyright 2013 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+
+#include <atomic>
+#include <cstdint>
+
+namespace boost
+{
+
+namespace detail
+{
+
+class atomic_count
+{
+public:
+
+ explicit atomic_count( long v ): value_( v )
+ {
+ }
+
+ long operator++()
+ {
+ return value_.fetch_add( 1, std::memory_order_acq_rel ) + 1;
+ }
+
+ long operator--()
+ {
+ return value_.fetch_sub( 1, std::memory_order_acq_rel ) - 1;
+ }
+
+ operator long() const
+ {
+ return value_.load( std::memory_order_acquire );
+ }
+
+private:
+
+ atomic_count(atomic_count const &);
+ atomic_count & operator=(atomic_count const &);
+
+ std::atomic_int_least32_t value_;
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/atomic_count_sync.hpp b/include/boost/smart_ptr/detail/atomic_count_sync.hpp
new file mode 100644
index 0000000..b6359b5
--- /dev/null
+++ b/include/boost/smart_ptr/detail/atomic_count_sync.hpp
@@ -0,0 +1,61 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED
+
+//
+// boost/detail/atomic_count_sync.hpp
+//
+// atomic_count for g++ 4.1+
+//
+// http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html
+//
+// Copyright 2007 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)
+//
+
+#if defined( __ia64__ ) && defined( __INTEL_COMPILER )
+# include <ia64intrin.h>
+#endif
+
+namespace boost
+{
+
+namespace detail
+{
+
+class atomic_count
+{
+public:
+
+ explicit atomic_count( long v ) : value_( v ) {}
+
+ long operator++()
+ {
+ return __sync_add_and_fetch( &value_, 1 );
+ }
+
+ long operator--()
+ {
+ return __sync_add_and_fetch( &value_, -1 );
+ }
+
+ operator long() const
+ {
+ return __sync_fetch_and_add( &value_, 0 );
+ }
+
+private:
+
+ atomic_count(atomic_count const &);
+ atomic_count & operator=(atomic_count const &);
+
+ mutable long value_;
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/atomic_count_win32.hpp b/include/boost/smart_ptr/detail/atomic_count_win32.hpp
new file mode 100644
index 0000000..633e73c
--- /dev/null
+++ b/include/boost/smart_ptr/detail/atomic_count_win32.hpp
@@ -0,0 +1,63 @@
+#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/detail/atomic_count_win32.hpp
+//
+// Copyright (c) 2001-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/smart_ptr/detail/sp_interlocked.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+class atomic_count
+{
+public:
+
+ explicit atomic_count( long v ): value_( v )
+ {
+ }
+
+ long operator++()
+ {
+ return BOOST_SP_INTERLOCKED_INCREMENT( &value_ );
+ }
+
+ long operator--()
+ {
+ return BOOST_SP_INTERLOCKED_DECREMENT( &value_ );
+ }
+
+ operator long() const
+ {
+ return static_cast<long const volatile &>( value_ );
+ }
+
+private:
+
+ atomic_count( atomic_count const & );
+ atomic_count & operator=( atomic_count const & );
+
+ long value_;
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/lightweight_mutex.hpp b/include/boost/smart_ptr/detail/lightweight_mutex.hpp
new file mode 100644
index 0000000..d46b193
--- /dev/null
+++ b/include/boost/smart_ptr/detail/lightweight_mutex.hpp
@@ -0,0 +1,42 @@
+#ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/detail/lightweight_mutex.hpp - lightweight mutex
+//
+// Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd.
+//
+// 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)
+//
+// typedef <unspecified> boost::detail::lightweight_mutex;
+//
+// boost::detail::lightweight_mutex is a header-only implementation of
+// a subset of the Mutex concept requirements:
+//
+// http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex
+//
+// It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX.
+//
+
+#include <boost/config.hpp>
+
+#if !defined(BOOST_HAS_THREADS)
+# include <boost/smart_ptr/detail/lwm_nop.hpp>
+#elif defined(BOOST_HAS_PTHREADS)
+# include <boost/smart_ptr/detail/lwm_pthreads.hpp>
+#elif defined(BOOST_HAS_WINTHREADS) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# include <boost/smart_ptr/detail/lwm_win32_cs.hpp>
+#else
+// Use #define BOOST_DISABLE_THREADS to avoid the error
+# error Unrecognized threading platform
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/local_counted_base.hpp b/include/boost/smart_ptr/detail/local_counted_base.hpp
new file mode 100644
index 0000000..fdfe2c6
--- /dev/null
+++ b/include/boost/smart_ptr/detail/local_counted_base.hpp
@@ -0,0 +1,148 @@
+#ifndef BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/local_counted_base.hpp
+//
+// 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/detail/shared_count.hpp>
+#include <boost/config.hpp>
+#include <utility>
+
+namespace boost
+{
+
+namespace detail
+{
+
+class local_counted_base
+{
+private:
+
+ local_counted_base & operator= ( local_counted_base const & );
+
+private:
+
+ // not 'int' or 'unsigned' to avoid aliasing and enable optimizations
+ enum count_type { min_ = 0, initial_ = 1, max_ = 2147483647 };
+
+ count_type local_use_count_;
+
+public:
+
+ BOOST_CONSTEXPR local_counted_base() BOOST_SP_NOEXCEPT: local_use_count_( initial_ )
+ {
+ }
+
+ BOOST_CONSTEXPR local_counted_base( local_counted_base const & ) BOOST_SP_NOEXCEPT: local_use_count_( initial_ )
+ {
+ }
+
+ virtual ~local_counted_base() /*BOOST_SP_NOEXCEPT*/
+ {
+ }
+
+ virtual void local_cb_destroy() BOOST_SP_NOEXCEPT = 0;
+
+ virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT = 0;
+
+ void add_ref() BOOST_SP_NOEXCEPT
+ {
+#if !defined(__NVCC__)
+#if defined( __has_builtin )
+# if __has_builtin( __builtin_assume )
+
+ __builtin_assume( local_use_count_ >= 1 );
+
+# endif
+#endif
+#endif
+
+ local_use_count_ = static_cast<count_type>( local_use_count_ + 1 );
+ }
+
+ void release() BOOST_SP_NOEXCEPT
+ {
+ local_use_count_ = static_cast<count_type>( local_use_count_ - 1 );
+
+ if( local_use_count_ == 0 )
+ {
+ local_cb_destroy();
+ }
+ }
+
+ long local_use_count() const BOOST_SP_NOEXCEPT
+ {
+ return local_use_count_;
+ }
+};
+
+class local_counted_impl: public local_counted_base
+{
+private:
+
+ local_counted_impl( local_counted_impl const & );
+
+private:
+
+ shared_count pn_;
+
+public:
+
+ explicit local_counted_impl( shared_count const& pn ): pn_( pn )
+ {
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ explicit local_counted_impl( shared_count && pn ): pn_( std::move(pn) )
+ {
+ }
+
+#endif
+
+ virtual void local_cb_destroy() BOOST_SP_NOEXCEPT
+ {
+ delete this;
+ }
+
+ virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT
+ {
+ return pn_;
+ }
+};
+
+class local_counted_impl_em: public local_counted_base
+{
+public:
+
+ shared_count pn_;
+
+ virtual void local_cb_destroy() BOOST_SP_NOEXCEPT
+ {
+ shared_count().swap( pn_ );
+ }
+
+ virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT
+ {
+ return pn_;
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/local_sp_deleter.hpp b/include/boost/smart_ptr/detail/local_sp_deleter.hpp
new file mode 100644
index 0000000..7d04f1d
--- /dev/null
+++ b/include/boost/smart_ptr/detail/local_sp_deleter.hpp
@@ -0,0 +1,91 @@
+#ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/local_sp_deleter.hpp
+//
+// 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/detail/local_counted_base.hpp>
+#include <boost/config.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+template<class D> class local_sp_deleter: public local_counted_impl_em
+{
+private:
+
+ D d_;
+
+public:
+
+ local_sp_deleter(): d_()
+ {
+ }
+
+ explicit local_sp_deleter( D const& d ) BOOST_SP_NOEXCEPT: d_( d )
+ {
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ explicit local_sp_deleter( D&& d ) BOOST_SP_NOEXCEPT: d_( std::move(d) )
+ {
+ }
+
+#endif
+
+ D& deleter()
+ {
+ return d_;
+ }
+
+ template<class Y> void operator()( Y* p ) BOOST_SP_NOEXCEPT
+ {
+ d_( p );
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ void operator()( boost::detail::sp_nullptr_t p ) BOOST_SP_NOEXCEPT
+ {
+ d_( p );
+ }
+
+#endif
+};
+
+template<> class local_sp_deleter<void>
+{
+};
+
+template<class D> D * get_local_deleter( local_sp_deleter<D> * p )
+{
+ return &p->deleter();
+}
+
+inline void * get_local_deleter( local_sp_deleter<void> * /*p*/ )
+{
+ return 0;
+}
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/lwm_nop.hpp b/include/boost/smart_ptr/detail/lwm_nop.hpp
new file mode 100644
index 0000000..521a88e
--- /dev/null
+++ b/include/boost/smart_ptr/detail/lwm_nop.hpp
@@ -0,0 +1,37 @@
+#ifndef BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/detail/lwm_nop.hpp
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+//
+// 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)
+//
+
+namespace boost
+{
+
+namespace detail
+{
+
+class lightweight_mutex
+{
+public:
+
+ typedef lightweight_mutex scoped_lock;
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/lwm_pthreads.hpp b/include/boost/smart_ptr/detail/lwm_pthreads.hpp
new file mode 100644
index 0000000..8eda518
--- /dev/null
+++ b/include/boost/smart_ptr/detail/lwm_pthreads.hpp
@@ -0,0 +1,87 @@
+#ifndef BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/detail/lwm_pthreads.hpp
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+//
+// 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)
+//
+
+#include <boost/assert.hpp>
+#include <pthread.h>
+
+namespace boost
+{
+
+namespace detail
+{
+
+class lightweight_mutex
+{
+private:
+
+ pthread_mutex_t m_;
+
+ lightweight_mutex(lightweight_mutex const &);
+ lightweight_mutex & operator=(lightweight_mutex const &);
+
+public:
+
+ lightweight_mutex()
+ {
+
+// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
+
+#if defined(__hpux) && defined(_DECTHREADS_)
+ BOOST_VERIFY( pthread_mutex_init( &m_, pthread_mutexattr_default ) == 0 );
+#else
+ BOOST_VERIFY( pthread_mutex_init( &m_, 0 ) == 0 );
+#endif
+ }
+
+ ~lightweight_mutex()
+ {
+ BOOST_VERIFY( pthread_mutex_destroy( &m_ ) == 0 );
+ }
+
+ class scoped_lock;
+ friend class scoped_lock;
+
+ class scoped_lock
+ {
+ private:
+
+ pthread_mutex_t & m_;
+
+ scoped_lock(scoped_lock const &);
+ scoped_lock & operator=(scoped_lock const &);
+
+ public:
+
+ scoped_lock(lightweight_mutex & m): m_(m.m_)
+ {
+ BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
+ }
+
+ ~scoped_lock()
+ {
+ BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
+ }
+ };
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/lwm_win32_cs.hpp b/include/boost/smart_ptr/detail/lwm_win32_cs.hpp
new file mode 100644
index 0000000..d8dccb0
--- /dev/null
+++ b/include/boost/smart_ptr/detail/lwm_win32_cs.hpp
@@ -0,0 +1,138 @@
+#ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/detail/lwm_win32_cs.hpp
+//
+// Copyright (c) 2002, 2003 Peter Dimov
+// Copyright (c) Microsoft Corporation 2014
+//
+// 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)
+//
+
+#include <boost/predef.h>
+
+#ifdef BOOST_USE_WINDOWS_H
+
+#include <windows.h>
+
+#else
+
+struct _RTL_CRITICAL_SECTION;
+
+#endif
+
+namespace boost
+{
+
+namespace detail
+{
+
+#ifndef BOOST_USE_WINDOWS_H
+
+struct critical_section
+{
+ struct critical_section_debug * DebugInfo;
+ long LockCount;
+ long RecursionCount;
+ void * OwningThread;
+ void * LockSemaphore;
+#if defined(_WIN64)
+ unsigned __int64 SpinCount;
+#else
+ unsigned long SpinCount;
+#endif
+};
+
+#if BOOST_PLAT_WINDOWS_RUNTIME
+extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSectionEx(::_RTL_CRITICAL_SECTION *, unsigned long, unsigned long);
+#else
+extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(::_RTL_CRITICAL_SECTION *);
+#endif
+extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(::_RTL_CRITICAL_SECTION *);
+extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(::_RTL_CRITICAL_SECTION *);
+extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(::_RTL_CRITICAL_SECTION *);
+
+typedef ::_RTL_CRITICAL_SECTION rtl_critical_section;
+
+#else // #ifndef BOOST_USE_WINDOWS_H
+
+typedef ::CRITICAL_SECTION critical_section;
+
+#if BOOST_PLAT_WINDOWS_RUNTIME
+using ::InitializeCriticalSectionEx;
+#else
+using ::InitializeCriticalSection;
+#endif
+using ::EnterCriticalSection;
+using ::LeaveCriticalSection;
+using ::DeleteCriticalSection;
+
+typedef ::CRITICAL_SECTION rtl_critical_section;
+
+#endif // #ifndef BOOST_USE_WINDOWS_H
+
+class lightweight_mutex
+{
+private:
+
+ critical_section cs_;
+
+ lightweight_mutex(lightweight_mutex const &);
+ lightweight_mutex & operator=(lightweight_mutex const &);
+
+public:
+
+ lightweight_mutex()
+ {
+#if BOOST_PLAT_WINDOWS_RUNTIME
+ boost::detail::InitializeCriticalSectionEx(reinterpret_cast< rtl_critical_section* >(&cs_), 4000, 0);
+#else
+ boost::detail::InitializeCriticalSection(reinterpret_cast< rtl_critical_section* >(&cs_));
+#endif
+ }
+
+ ~lightweight_mutex()
+ {
+ boost::detail::DeleteCriticalSection(reinterpret_cast< rtl_critical_section* >(&cs_));
+ }
+
+ class scoped_lock;
+ friend class scoped_lock;
+
+ class scoped_lock
+ {
+ private:
+
+ lightweight_mutex & m_;
+
+ scoped_lock(scoped_lock const &);
+ scoped_lock & operator=(scoped_lock const &);
+
+ public:
+
+ explicit scoped_lock(lightweight_mutex & m): m_(m)
+ {
+ boost::detail::EnterCriticalSection(reinterpret_cast< rtl_critical_section* >(&m_.cs_));
+ }
+
+ ~scoped_lock()
+ {
+ boost::detail::LeaveCriticalSection(reinterpret_cast< rtl_critical_section* >(&m_.cs_));
+ }
+ };
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/operator_bool.hpp b/include/boost/smart_ptr/detail/operator_bool.hpp
new file mode 100644
index 0000000..f9c5ef6
--- /dev/null
+++ b/include/boost/smart_ptr/detail/operator_bool.hpp
@@ -0,0 +1,64 @@
+// This header intentionally has no include guards.
+//
+// Copyright (c) 2001-2009, 2012 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
+
+#if !defined( BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS ) && !defined( BOOST_NO_CXX11_NULLPTR )\
+ && !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
+
+ explicit operator bool () const BOOST_SP_NOEXCEPT
+ {
+ return px != 0;
+ }
+
+#elif ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__)
+
+ operator bool () const BOOST_SP_NOEXCEPT
+ {
+ return px != 0;
+ }
+
+#elif defined( _MANAGED )
+
+ static void unspecified_bool( this_type*** )
+ {
+ }
+
+ typedef void (*unspecified_bool_type)( this_type*** );
+
+ operator unspecified_bool_type() const BOOST_SP_NOEXCEPT
+ {
+ return px == 0? 0: unspecified_bool;
+ }
+
+#elif \
+ ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \
+ ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \
+ ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) )
+
+ typedef element_type * (this_type::*unspecified_bool_type)() const;
+
+ operator unspecified_bool_type() const BOOST_SP_NOEXCEPT
+ {
+ return px == 0? 0: &this_type::get;
+ }
+
+#else
+
+ typedef element_type * this_type::*unspecified_bool_type;
+
+ operator unspecified_bool_type() const BOOST_SP_NOEXCEPT
+ {
+ return px == 0? 0: &this_type::px;
+ }
+
+#endif
+
+ // operator! is redundant, but some compilers need it
+ bool operator! () const BOOST_SP_NOEXCEPT
+ {
+ return px == 0;
+ }
diff --git a/include/boost/smart_ptr/detail/quick_allocator.hpp b/include/boost/smart_ptr/detail/quick_allocator.hpp
new file mode 100644
index 0000000..159bd5e
--- /dev/null
+++ b/include/boost/smart_ptr/detail/quick_allocator.hpp
@@ -0,0 +1,199 @@
+#ifndef BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/quick_allocator.hpp
+//
+// Copyright (c) 2003 David Abrahams
+// Copyright (c) 2003 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/config.hpp>
+
+#include <boost/smart_ptr/detail/lightweight_mutex.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+
+#include <new> // ::operator new, ::operator delete
+#include <cstddef> // std::size_t
+
+namespace boost
+{
+
+namespace detail
+{
+
+template<unsigned size, unsigned align_> union freeblock
+{
+ typedef typename boost::type_with_alignment<align_>::type aligner_type;
+ aligner_type aligner;
+ char bytes[size];
+ freeblock * next;
+};
+
+template<unsigned size, unsigned align_> struct allocator_impl
+{
+ typedef freeblock<size, align_> block;
+
+ // It may seem odd to use such small pages.
+ //
+ // However, on a typical Windows implementation that uses
+ // the OS allocator, "normal size" pages interact with the
+ // "ordinary" operator new, slowing it down dramatically.
+ //
+ // 512 byte pages are handled by the small object allocator,
+ // and don't interfere with ::new.
+ //
+ // The other alternative is to use much bigger pages (1M.)
+ //
+ // It is surprisingly easy to hit pathological behavior by
+ // varying the page size. g++ 2.96 on Red Hat Linux 7.2,
+ // for example, passionately dislikes 496. 512 seems OK.
+
+#if defined(BOOST_QA_PAGE_SIZE)
+
+ enum { items_per_page = BOOST_QA_PAGE_SIZE / size };
+
+#else
+
+ enum { items_per_page = 512 / size }; // 1048560 / size
+
+#endif
+
+#ifdef BOOST_HAS_THREADS
+
+ static lightweight_mutex & mutex()
+ {
+ static freeblock< sizeof( lightweight_mutex ), boost::alignment_of< lightweight_mutex >::value > fbm;
+ static lightweight_mutex * pm = new( &fbm ) lightweight_mutex;
+ return *pm;
+ }
+
+ static lightweight_mutex * mutex_init;
+
+#endif
+
+ static block * free;
+ static block * page;
+ static unsigned last;
+
+ static inline void * alloc()
+ {
+#ifdef BOOST_HAS_THREADS
+ lightweight_mutex::scoped_lock lock( mutex() );
+#endif
+ if(block * x = free)
+ {
+ free = x->next;
+ return x;
+ }
+ else
+ {
+ if(last == items_per_page)
+ {
+ // "Listen to me carefully: there is no memory leak"
+ // -- Scott Meyers, Eff C++ 2nd Ed Item 10
+ page = ::new block[items_per_page];
+ last = 0;
+ }
+
+ return &page[last++];
+ }
+ }
+
+ static inline void * alloc(std::size_t n)
+ {
+ if(n != size) // class-specific new called for a derived object
+ {
+ return ::operator new(n);
+ }
+ else
+ {
+#ifdef BOOST_HAS_THREADS
+ lightweight_mutex::scoped_lock lock( mutex() );
+#endif
+ if(block * x = free)
+ {
+ free = x->next;
+ return x;
+ }
+ else
+ {
+ if(last == items_per_page)
+ {
+ page = ::new block[items_per_page];
+ last = 0;
+ }
+
+ return &page[last++];
+ }
+ }
+ }
+
+ static inline void dealloc(void * pv)
+ {
+ if(pv != 0) // 18.4.1.1/13
+ {
+#ifdef BOOST_HAS_THREADS
+ lightweight_mutex::scoped_lock lock( mutex() );
+#endif
+ block * pb = static_cast<block *>(pv);
+ pb->next = free;
+ free = pb;
+ }
+ }
+
+ static inline void dealloc(void * pv, std::size_t n)
+ {
+ if(n != size) // class-specific delete called for a derived object
+ {
+ ::operator delete(pv);
+ }
+ else if(pv != 0) // 18.4.1.1/13
+ {
+#ifdef BOOST_HAS_THREADS
+ lightweight_mutex::scoped_lock lock( mutex() );
+#endif
+ block * pb = static_cast<block *>(pv);
+ pb->next = free;
+ free = pb;
+ }
+ }
+};
+
+#ifdef BOOST_HAS_THREADS
+
+template<unsigned size, unsigned align_>
+ lightweight_mutex * allocator_impl<size, align_>::mutex_init = &allocator_impl<size, align_>::mutex();
+
+#endif
+
+template<unsigned size, unsigned align_>
+ freeblock<size, align_> * allocator_impl<size, align_>::free = 0;
+
+template<unsigned size, unsigned align_>
+ freeblock<size, align_> * allocator_impl<size, align_>::page = 0;
+
+template<unsigned size, unsigned align_>
+ unsigned allocator_impl<size, align_>::last = allocator_impl<size, align_>::items_per_page;
+
+template<class T>
+struct quick_allocator: public allocator_impl< sizeof(T), boost::alignment_of<T>::value >
+{
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp
new file mode 100644
index 0000000..ae7d0fb
--- /dev/null
+++ b/include/boost/smart_ptr/detail/shared_count.hpp
@@ -0,0 +1,667 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/shared_count.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifdef __BORLANDC__
+# pragma warn -8027 // Functions containing try are not expanded inline
+#endif
+
+#include <boost/config.hpp>
+#include <boost/checked_delete.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/smart_ptr/bad_weak_ptr.hpp>
+#include <boost/smart_ptr/detail/sp_counted_base.hpp>
+#include <boost/smart_ptr/detail/sp_counted_impl.hpp>
+#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
+#include <boost/detail/workaround.hpp>
+// In order to avoid circular dependencies with Boost.TR1
+// we make sure that our include of <memory> doesn't try to
+// pull in the TR1 headers: that's why we use this header
+// rather than including <memory> directly:
+#include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
+#include <functional> // std::less
+
+#ifdef BOOST_NO_EXCEPTIONS
+# include <new> // std::bad_alloc
+#endif
+
+#include <boost/core/addressof.hpp>
+
+#if defined( BOOST_SP_DISABLE_DEPRECATED )
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+namespace boost
+{
+
+namespace movelib
+{
+
+template< class T, class D > class unique_ptr;
+
+} // namespace movelib
+
+namespace detail
+{
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+
+int const shared_count_id = 0x2C35F101;
+int const weak_count_id = 0x298C38A4;
+
+#endif
+
+struct sp_nothrow_tag {};
+
+template< class D > struct sp_inplace_tag
+{
+};
+
+template< class T > class sp_reference_wrapper
+{
+public:
+
+ explicit sp_reference_wrapper( T & t): t_( boost::addressof( t ) )
+ {
+ }
+
+ template< class Y > void operator()( Y * p ) const
+ {
+ (*t_)( p );
+ }
+
+private:
+
+ T * t_;
+};
+
+template< class D > struct sp_convert_reference
+{
+ typedef D type;
+};
+
+template< class D > struct sp_convert_reference< D& >
+{
+ typedef sp_reference_wrapper< D > type;
+};
+
+class weak_count;
+
+class shared_count
+{
+private:
+
+ sp_counted_base * pi_;
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ int id_;
+#endif
+
+ friend class weak_count;
+
+public:
+
+ BOOST_CONSTEXPR shared_count(): pi_(0) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ }
+
+ BOOST_CONSTEXPR explicit shared_count( sp_counted_base * pi ): pi_( pi ) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ }
+
+ template<class Y> explicit shared_count( Y * p ): pi_( 0 )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+#ifndef BOOST_NO_EXCEPTIONS
+
+ try
+ {
+ pi_ = new sp_counted_impl_p<Y>( p );
+ }
+ catch(...)
+ {
+ boost::checked_delete( p );
+ throw;
+ }
+
+#else
+
+ pi_ = new sp_counted_impl_p<Y>( p );
+
+ if( pi_ == 0 )
+ {
+ boost::checked_delete( p );
+ boost::throw_exception( std::bad_alloc() );
+ }
+
+#endif
+ }
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )
+ template<class Y, class D> shared_count( Y * p, D d ): pi_(0)
+#else
+ template<class P, class D> shared_count( P p, D d ): pi_(0)
+#endif
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )
+ typedef Y* P;
+#endif
+#ifndef BOOST_NO_EXCEPTIONS
+
+ try
+ {
+ pi_ = new sp_counted_impl_pd<P, D>(p, d);
+ }
+ catch(...)
+ {
+ d(p); // delete p
+ throw;
+ }
+
+#else
+
+ pi_ = new sp_counted_impl_pd<P, D>(p, d);
+
+ if(pi_ == 0)
+ {
+ d(p); // delete p
+ boost::throw_exception(std::bad_alloc());
+ }
+
+#endif
+ }
+
+#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
+
+ template< class P, class D > shared_count( P p, sp_inplace_tag<D> ): pi_( 0 )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+#ifndef BOOST_NO_EXCEPTIONS
+
+ try
+ {
+ pi_ = new sp_counted_impl_pd< P, D >( p );
+ }
+ catch( ... )
+ {
+ D::operator_fn( p ); // delete p
+ throw;
+ }
+
+#else
+
+ pi_ = new sp_counted_impl_pd< P, D >( p );
+
+ if( pi_ == 0 )
+ {
+ D::operator_fn( p ); // delete p
+ boost::throw_exception( std::bad_alloc() );
+ }
+
+#endif // #ifndef BOOST_NO_EXCEPTIONS
+ }
+
+#endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
+
+ template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ typedef sp_counted_impl_pda<P, D, A> impl_type;
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
+
+#else
+
+ typedef typename A::template rebind< impl_type >::other A2;
+
+#endif
+
+ A2 a2( a );
+
+#ifndef BOOST_NO_EXCEPTIONS
+
+ try
+ {
+ pi_ = a2.allocate( 1 );
+ ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
+ }
+ catch(...)
+ {
+ d( p );
+
+ if( pi_ != 0 )
+ {
+ a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
+ }
+
+ throw;
+ }
+
+#else
+
+ pi_ = a2.allocate( 1 );
+
+ if( pi_ != 0 )
+ {
+ ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
+ }
+ else
+ {
+ d( p );
+ boost::throw_exception( std::bad_alloc() );
+ }
+
+#endif
+ }
+
+#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
+
+ template< class P, class D, class A > shared_count( P p, sp_inplace_tag< D >, A a ): pi_( 0 )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ typedef sp_counted_impl_pda< P, D, A > impl_type;
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
+
+#else
+
+ typedef typename A::template rebind< impl_type >::other A2;
+
+#endif
+
+ A2 a2( a );
+
+#ifndef BOOST_NO_EXCEPTIONS
+
+ try
+ {
+ pi_ = a2.allocate( 1 );
+ ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
+ }
+ catch(...)
+ {
+ D::operator_fn( p );
+
+ if( pi_ != 0 )
+ {
+ a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
+ }
+
+ throw;
+ }
+
+#else
+
+ pi_ = a2.allocate( 1 );
+
+ if( pi_ != 0 )
+ {
+ ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
+ }
+ else
+ {
+ D::operator_fn( p );
+ boost::throw_exception( std::bad_alloc() );
+ }
+
+#endif // #ifndef BOOST_NO_EXCEPTIONS
+ }
+
+#endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
+
+#ifndef BOOST_NO_AUTO_PTR
+
+ // auto_ptr<Y> is special cased to provide the strong guarantee
+
+ template<class Y>
+ explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+#ifdef BOOST_NO_EXCEPTIONS
+
+ if( pi_ == 0 )
+ {
+ boost::throw_exception(std::bad_alloc());
+ }
+
+#endif
+
+ r.release();
+ }
+
+#endif
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR )
+
+ template<class Y, class D>
+ explicit shared_count( std::unique_ptr<Y, D> & r ): pi_( 0 )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ typedef typename sp_convert_reference<D>::type D2;
+
+ D2 d2( r.get_deleter() );
+ pi_ = new sp_counted_impl_pd< typename std::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
+
+#ifdef BOOST_NO_EXCEPTIONS
+
+ if( pi_ == 0 )
+ {
+ boost::throw_exception( std::bad_alloc() );
+ }
+
+#endif
+
+ r.release();
+ }
+
+#endif
+
+ template<class Y, class D>
+ explicit shared_count( boost::movelib::unique_ptr<Y, D> & r ): pi_( 0 )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ typedef typename sp_convert_reference<D>::type D2;
+
+ D2 d2( r.get_deleter() );
+ pi_ = new sp_counted_impl_pd< typename boost::movelib::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
+
+#ifdef BOOST_NO_EXCEPTIONS
+
+ if( pi_ == 0 )
+ {
+ boost::throw_exception( std::bad_alloc() );
+ }
+
+#endif
+
+ r.release();
+ }
+
+ ~shared_count() // nothrow
+ {
+ if( pi_ != 0 ) pi_->release();
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ id_ = 0;
+#endif
+ }
+
+ shared_count(shared_count const & r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ if( pi_ != 0 ) pi_->add_ref_copy();
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ shared_count(shared_count && r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ r.pi_ = 0;
+ }
+
+#endif
+
+ explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
+ shared_count( weak_count const & r, sp_nothrow_tag ); // constructs an empty *this when r.use_count() == 0
+
+ shared_count & operator= (shared_count const & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+
+ if( tmp != pi_ )
+ {
+ if( tmp != 0 ) tmp->add_ref_copy();
+ if( pi_ != 0 ) pi_->release();
+ pi_ = tmp;
+ }
+
+ return *this;
+ }
+
+ void swap(shared_count & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+ r.pi_ = pi_;
+ pi_ = tmp;
+ }
+
+ long use_count() const // nothrow
+ {
+ return pi_ != 0? pi_->use_count(): 0;
+ }
+
+ bool unique() const // nothrow
+ {
+ return use_count() == 1;
+ }
+
+ bool empty() const // nothrow
+ {
+ return pi_ == 0;
+ }
+
+ friend inline bool operator==(shared_count const & a, shared_count const & b)
+ {
+ return a.pi_ == b.pi_;
+ }
+
+ friend inline bool operator<(shared_count const & a, shared_count const & b)
+ {
+ return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
+ }
+
+ void * get_deleter( sp_typeinfo const & ti ) const
+ {
+ return pi_? pi_->get_deleter( ti ): 0;
+ }
+
+ void * get_local_deleter( sp_typeinfo const & ti ) const
+ {
+ return pi_? pi_->get_local_deleter( ti ): 0;
+ }
+
+ void * get_untyped_deleter() const
+ {
+ return pi_? pi_->get_untyped_deleter(): 0;
+ }
+};
+
+
+class weak_count
+{
+private:
+
+ sp_counted_base * pi_;
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ int id_;
+#endif
+
+ friend class shared_count;
+
+public:
+
+ BOOST_CONSTEXPR weak_count(): pi_(0) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(weak_count_id)
+#endif
+ {
+ }
+
+ weak_count(shared_count const & r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(weak_count_id)
+#endif
+ {
+ if(pi_ != 0) pi_->weak_add_ref();
+ }
+
+ weak_count(weak_count const & r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(weak_count_id)
+#endif
+ {
+ if(pi_ != 0) pi_->weak_add_ref();
+ }
+
+// Move support
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ weak_count(weak_count && r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(weak_count_id)
+#endif
+ {
+ r.pi_ = 0;
+ }
+
+#endif
+
+ ~weak_count() // nothrow
+ {
+ if(pi_ != 0) pi_->weak_release();
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ id_ = 0;
+#endif
+ }
+
+ weak_count & operator= (shared_count const & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+
+ if( tmp != pi_ )
+ {
+ if(tmp != 0) tmp->weak_add_ref();
+ if(pi_ != 0) pi_->weak_release();
+ pi_ = tmp;
+ }
+
+ return *this;
+ }
+
+ weak_count & operator= (weak_count const & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+
+ if( tmp != pi_ )
+ {
+ if(tmp != 0) tmp->weak_add_ref();
+ if(pi_ != 0) pi_->weak_release();
+ pi_ = tmp;
+ }
+
+ return *this;
+ }
+
+ void swap(weak_count & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+ r.pi_ = pi_;
+ pi_ = tmp;
+ }
+
+ long use_count() const // nothrow
+ {
+ return pi_ != 0? pi_->use_count(): 0;
+ }
+
+ bool empty() const // nothrow
+ {
+ return pi_ == 0;
+ }
+
+ friend inline bool operator==(weak_count const & a, weak_count const & b)
+ {
+ return a.pi_ == b.pi_;
+ }
+
+ friend inline bool operator<(weak_count const & a, weak_count const & b)
+ {
+ return std::less<sp_counted_base *>()(a.pi_, b.pi_);
+ }
+};
+
+inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+{
+ if( pi_ == 0 || !pi_->add_ref_lock() )
+ {
+ boost::throw_exception( boost::bad_weak_ptr() );
+ }
+}
+
+inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+{
+ if( pi_ != 0 && !pi_->add_ref_lock() )
+ {
+ pi_ = 0;
+ }
+}
+
+} // namespace detail
+
+} // namespace boost
+
+#if defined( BOOST_SP_DISABLE_DEPRECATED )
+#pragma GCC diagnostic pop
+#endif
+
+#ifdef __BORLANDC__
+# pragma warn .8027 // Functions containing try are not expanded inline
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_convertible.hpp b/include/boost/smart_ptr/detail/sp_convertible.hpp
new file mode 100644
index 0000000..4bba9ed
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_convertible.hpp
@@ -0,0 +1,92 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_convertible.hpp
+//
+// Copyright 2008 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
+
+#include <boost/config.hpp>
+#include <cstddef>
+
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( BOOST_NO_SFINAE )
+# define BOOST_SP_NO_SP_CONVERTIBLE
+#endif
+
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ < 303 )
+# define BOOST_SP_NO_SP_CONVERTIBLE
+#endif
+
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x630 )
+# define BOOST_SP_NO_SP_CONVERTIBLE
+#endif
+
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+namespace boost
+{
+
+namespace detail
+{
+
+template< class Y, class T > struct sp_convertible
+{
+ typedef char (&yes) [1];
+ typedef char (&no) [2];
+
+ static yes f( T* );
+ static no f( ... );
+
+ enum _vt { value = sizeof( (f)( static_cast<Y*>(0) ) ) == sizeof(yes) };
+};
+
+template< class Y, class T > struct sp_convertible< Y, T[] >
+{
+ enum _vt { value = false };
+};
+
+template< class Y, class T > struct sp_convertible< Y[], T[] >
+{
+ enum _vt { value = sp_convertible< Y[1], T[1] >::value };
+};
+
+template< class Y, std::size_t N, class T > struct sp_convertible< Y[N], T[] >
+{
+ enum _vt { value = sp_convertible< Y[1], T[1] >::value };
+};
+
+struct sp_empty
+{
+};
+
+template< bool > struct sp_enable_if_convertible_impl;
+
+template<> struct sp_enable_if_convertible_impl<true>
+{
+ typedef sp_empty type;
+};
+
+template<> struct sp_enable_if_convertible_impl<false>
+{
+};
+
+template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_if_convertible_impl< sp_convertible< Y, T >::value >
+{
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp
new file mode 100644
index 0000000..4386137
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp
@@ -0,0 +1,96 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/sp_counted_base.hpp
+//
+// Copyright 2005-2013 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/config.hpp>
+#include <boost/smart_ptr/detail/sp_has_sync.hpp>
+
+#if !defined( __c2__ ) && defined( __clang__ ) && defined( __has_extension )
+# if __has_extension( __c_atomic__ )
+# define BOOST_SP_HAS_CLANG_C11_ATOMICS
+# endif
+#endif
+
+#if defined( BOOST_SP_DISABLE_THREADS )
+# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
+
+#elif defined( BOOST_SP_USE_STD_ATOMIC )
+# include <boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp>
+
+#elif defined( BOOST_SP_USE_SPINLOCK )
+# include <boost/smart_ptr/detail/sp_counted_base_spin.hpp>
+
+#elif defined( BOOST_SP_USE_PTHREADS )
+# include <boost/smart_ptr/detail/sp_counted_base_pt.hpp>
+
+#elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 )
+# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
+
+#elif defined( BOOST_SP_HAS_CLANG_C11_ATOMICS )
+# include <boost/smart_ptr/detail/sp_counted_base_clang.hpp>
+
+#elif !defined( BOOST_NO_CXX11_HDR_ATOMIC )
+# include <boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp>
+
+#elif defined( __SNC__ )
+# include <boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp>
+
+#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined(__PATHSCALE__)
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp>
+
+#elif defined(__HP_aCC) && defined(__ia64)
+# include <boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp>
+
+#elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER ) && !defined(__PATHSCALE__)
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp>
+
+#elif defined( __IBMCPP__ ) && defined( __powerpc )
+# include <boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp>
+
+#elif defined( __MWERKS__ ) && defined( __POWERPC__ )
+# include <boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp>
+
+#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) && !defined(__PATHSCALE__) && !defined( _AIX )
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp>
+
+#elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) ) && !defined(__PATHSCALE__) && !defined( __mips16 )
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp>
+
+#elif defined( BOOST_SP_HAS_SYNC )
+# include <boost/smart_ptr/detail/sp_counted_base_sync.hpp>
+
+#elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) )
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp>
+
+#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined(__CYGWIN__)
+# include <boost/smart_ptr/detail/sp_counted_base_w32.hpp>
+
+#elif defined( _AIX )
+# include <boost/smart_ptr/detail/sp_counted_base_aix.hpp>
+
+#elif !defined( BOOST_HAS_THREADS )
+# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
+
+#else
+# include <boost/smart_ptr/detail/sp_counted_base_spin.hpp>
+
+#endif
+
+#undef BOOST_SP_HAS_CLANG_C11_ATOMICS
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp b/include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
new file mode 100644
index 0000000..ec6f6ee
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
@@ -0,0 +1,152 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED
+
+//
+// detail/sp_counted_base_acc_ia64.hpp - aC++ on HP-UX IA64
+//
+// Copyright 2007 Baruch Zilber
+// Copyright 2007 Boris Gubenko
+//
+// 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)
+//
+//
+// Lock-free algorithm by Alexander Terekhov
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+#include <machine/sys/inline.h>
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline void atomic_increment( int * pw )
+{
+ // ++*pw;
+
+ _Asm_fetchadd(_FASZ_W, _SEM_REL, pw, +1, _LDHINT_NONE);
+}
+
+inline int atomic_decrement( int * pw )
+{
+ // return --*pw;
+
+ int r = static_cast<int>(_Asm_fetchadd(_FASZ_W, _SEM_REL, pw, -1, _LDHINT_NONE));
+ if (1 == r)
+ {
+ _Asm_mf();
+ }
+
+ return r - 1;
+}
+
+inline int atomic_conditional_increment( int * pw )
+{
+ // if( *pw != 0 ) ++*pw;
+ // return *pw;
+
+ int v = *pw;
+
+ for (;;)
+ {
+ if (0 == v)
+ {
+ return 0;
+ }
+
+ _Asm_mov_to_ar(_AREG_CCV,
+ v,
+ (_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE));
+ int r = static_cast<int>(_Asm_cmpxchg(_SZ_W, _SEM_ACQ, pw, v + 1, _LDHINT_NONE));
+ if (r == v)
+ {
+ return r + 1;
+ }
+
+ v = r;
+ }
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ int use_count_; // #shared
+ int weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_decrement( &use_count_ ) == 0 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_decrement( &weak_count_ ) == 0 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return static_cast<int const volatile &>( use_count_ ); // TODO use ld.acq here
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp b/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
new file mode 100644
index 0000000..ce8ee68
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
@@ -0,0 +1,144 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_AIX_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_AIX_HPP_INCLUDED
+
+//
+// detail/sp_counted_base_aix.hpp
+// based on: detail/sp_counted_base_w32.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+// Copyright 2006 Michael van der Westhuizen
+//
+// 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)
+//
+//
+// Lock-free algorithm by Alexander Terekhov
+//
+// Thanks to Ben Hitchings for the #weak + (#shared != 0)
+// formulation
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+#include <builtins.h>
+#include <sys/atomic_op.h>
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline void atomic_increment( int32_t* pw )
+{
+ // ++*pw;
+
+ fetch_and_add( pw, 1 );
+}
+
+inline int32_t atomic_decrement( int32_t * pw )
+{
+ // return --*pw;
+
+ int32_t originalValue;
+
+ __lwsync();
+ originalValue = fetch_and_add( pw, -1 );
+ __isync();
+
+ return (originalValue - 1);
+}
+
+inline int32_t atomic_conditional_increment( int32_t * pw )
+{
+ // if( *pw != 0 ) ++*pw;
+ // return *pw;
+
+ int32_t tmp = fetch_and_add( pw, 0 );
+ for( ;; )
+ {
+ if( tmp == 0 ) return 0;
+ if( compare_and_swap( pw, &tmp, tmp + 1 ) ) return (tmp + 1);
+ }
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ int32_t use_count_; // #shared
+ int32_t weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_decrement( &use_count_ ) == 0 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_decrement( &weak_count_ ) == 0 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return fetch_and_add( const_cast<int32_t*>(&use_count_), 0 );
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_AIX_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_clang.hpp b/include/boost/smart_ptr/detail/sp_counted_base_clang.hpp
new file mode 100644
index 0000000..5d6e073
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_clang.hpp
@@ -0,0 +1,150 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_counted_base_clang.hpp - __c11 clang intrinsics
+//
+// Copyright (c) 2007, 2013, 2015 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
+
+#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/cstdint.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+typedef _Atomic( boost::int_least32_t ) atomic_int_least32_t;
+
+inline void atomic_increment( atomic_int_least32_t * pw )
+{
+ __c11_atomic_fetch_add( pw, 1, __ATOMIC_RELAXED );
+}
+
+inline boost::int_least32_t atomic_decrement( atomic_int_least32_t * pw )
+{
+ return __c11_atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL );
+}
+
+inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t * pw )
+{
+ // long r = *pw;
+ // if( r != 0 ) ++*pw;
+ // return r;
+
+ boost::int_least32_t r = __c11_atomic_load( pw, __ATOMIC_RELAXED );
+
+ for( ;; )
+ {
+ if( r == 0 )
+ {
+ return r;
+ }
+
+ if( __c11_atomic_compare_exchange_weak( pw, &r, r + 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED ) )
+ {
+ return r;
+ }
+ }
+}
+
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wweak-vtables"
+#endif
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ atomic_int_least32_t use_count_; // #shared
+ atomic_int_least32_t weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base()
+ {
+ __c11_atomic_init( &use_count_, 1 );
+ __c11_atomic_init( &weak_count_, 1 );
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_decrement( &use_count_ ) == 1 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_decrement( &weak_count_ ) == 1 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return __c11_atomic_load( const_cast< atomic_int_least32_t* >( &use_count_ ), __ATOMIC_ACQUIRE );
+ }
+};
+
+#if defined(__clang__)
+# pragma clang diagnostic pop
+#endif
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp
new file mode 100644
index 0000000..065f7c3
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp
@@ -0,0 +1,172 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/sp_counted_base_cw_ppc.hpp - CodeWarrior on PowerPC
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+//
+// Lock-free algorithm by Alexander Terekhov
+//
+// Thanks to Ben Hitchings for the #weak + (#shared != 0)
+// formulation
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline void atomic_increment( register long * pw )
+{
+ register int a;
+
+ asm
+ {
+loop:
+
+ lwarx a, 0, pw
+ addi a, a, 1
+ stwcx. a, 0, pw
+ bne- loop
+ }
+}
+
+inline long atomic_decrement( register long * pw )
+{
+ register int a;
+
+ asm
+ {
+ sync
+
+loop:
+
+ lwarx a, 0, pw
+ addi a, a, -1
+ stwcx. a, 0, pw
+ bne- loop
+
+ isync
+ }
+
+ return a;
+}
+
+inline long atomic_conditional_increment( register long * pw )
+{
+ register int a;
+
+ asm
+ {
+loop:
+
+ lwarx a, 0, pw
+ cmpwi a, 0
+ beq store
+
+ addi a, a, 1
+
+store:
+
+ stwcx. a, 0, pw
+ bne- loop
+ }
+
+ return a;
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ long use_count_; // #shared
+ long weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_decrement( &use_count_ ) == 0 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_decrement( &weak_count_ ) == 0 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return static_cast<long const volatile &>( use_count_ );
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp b/include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp
new file mode 100644
index 0000000..3a3d4d4
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp
@@ -0,0 +1,160 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/sp_counted_base_cw_x86.hpp - CodeWarrion on 486+
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+// Copyright 2005 Rene Rivera
+//
+// 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)
+//
+//
+// Lock-free algorithm by Alexander Terekhov
+//
+// Thanks to Ben Hitchings for the #weak + (#shared != 0)
+// formulation
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline int atomic_exchange_and_add( int * pw, int dv )
+{
+ // int r = *pw;
+ // *pw += dv;
+ // return r;
+
+ asm
+ {
+ mov esi, [pw]
+ mov eax, dv
+ lock xadd dword ptr [esi], eax
+ }
+}
+
+inline void atomic_increment( int * pw )
+{
+ //atomic_exchange_and_add( pw, 1 );
+
+ asm
+ {
+ mov esi, [pw]
+ lock inc dword ptr [esi]
+ }
+}
+
+inline int atomic_conditional_increment( int * pw )
+{
+ // int rv = *pw;
+ // if( rv != 0 ) ++*pw;
+ // return rv;
+
+ asm
+ {
+ mov esi, [pw]
+ mov eax, dword ptr [esi]
+ L0:
+ test eax, eax
+ je L1
+ mov ebx, eax
+ inc ebx
+ lock cmpxchg dword ptr [esi], ebx
+ jne L0
+ L1:
+ }
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ int use_count_; // #shared
+ int weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return static_cast<int const volatile &>( use_count_ );
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp
new file mode 100644
index 0000000..6c3cce8
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp
@@ -0,0 +1,159 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED
+
+//
+// detail/sp_counted_base_gcc_ia64.hpp - g++ on IA64
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2006 Peter Dimov
+// Copyright 2005 Ben Hutchings
+//
+// 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)
+//
+//
+// Lock-free algorithm by Alexander Terekhov
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline void atomic_increment( int * pw )
+{
+ // ++*pw;
+
+ int tmp;
+
+ // No barrier is required here but fetchadd always has an acquire or
+ // release barrier associated with it. We choose release as it should be
+ // cheaper.
+ __asm__ ("fetchadd4.rel %0=%1,1" :
+ "=r"(tmp), "=m"(*pw) :
+ "m"( *pw ));
+}
+
+inline int atomic_decrement( int * pw )
+{
+ // return --*pw;
+
+ int rv;
+
+ __asm__ (" fetchadd4.rel %0=%1,-1 ;; \n"
+ " cmp.eq p7,p0=1,%0 ;; \n"
+ "(p7) ld4.acq %0=%1 " :
+ "=&r"(rv), "=m"(*pw) :
+ "m"( *pw ) :
+ "p7");
+
+ return rv;
+}
+
+inline int atomic_conditional_increment( int * pw )
+{
+ // if( *pw != 0 ) ++*pw;
+ // return *pw;
+
+ int rv, tmp, tmp2;
+
+ __asm__ ("0: ld4 %0=%3 ;; \n"
+ " cmp.eq p7,p0=0,%0 ;; \n"
+ "(p7) br.cond.spnt 1f \n"
+ " mov ar.ccv=%0 \n"
+ " add %1=1,%0 ;; \n"
+ " cmpxchg4.acq %2=%3,%1,ar.ccv ;; \n"
+ " cmp.ne p7,p0=%0,%2 ;; \n"
+ "(p7) br.cond.spnt 0b \n"
+ " mov %0=%1 ;; \n"
+ "1:" :
+ "=&r"(rv), "=&r"(tmp), "=&r"(tmp2), "=m"(*pw) :
+ "m"( *pw ) :
+ "ar.ccv", "p7");
+
+ return rv;
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ int use_count_; // #shared
+ int weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_decrement( &use_count_ ) == 0 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_decrement( &weak_count_ ) == 0 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return static_cast<int const volatile &>( use_count_ ); // TODO use ld.acq here
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
new file mode 100644
index 0000000..c3175cf
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp
@@ -0,0 +1,189 @@
+#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED
+#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/sp_counted_base_gcc_mips.hpp - g++ on MIPS
+//
+// Copyright (c) 2009, Spirent Communications, Inc.
+//
+// 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)
+//
+//
+// Lock-free algorithm by Alexander Terekhov
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline void atomic_increment( int * pw )
+{
+ // ++*pw;
+
+ int tmp;
+
+ __asm__ __volatile__
+ (
+ "0:\n\t"
+ ".set push\n\t"
+#if !defined(__mips_isa_rev) || (__mips_isa_rev < 6)
+ ".set mips2\n\t"
+#endif
+ "ll %0, %1\n\t"
+ "addiu %0, 1\n\t"
+ "sc %0, %1\n\t"
+ ".set pop\n\t"
+ "beqz %0, 0b":
+ "=&r"( tmp ), "=m"( *pw ):
+ "m"( *pw )
+ );
+}
+
+inline int atomic_decrement( int * pw )
+{
+ // return --*pw;
+
+ int rv, tmp;
+
+ __asm__ __volatile__
+ (
+ "0:\n\t"
+ ".set push\n\t"
+#if !defined(__mips_isa_rev) || (__mips_isa_rev < 6)
+ ".set mips2\n\t"
+#endif
+ "ll %1, %2\n\t"
+ "addiu %0, %1, -1\n\t"
+ "sc %0, %2\n\t"
+ ".set pop\n\t"
+ "beqz %0, 0b\n\t"
+ "addiu %0, %1, -1":
+ "=&r"( rv ), "=&r"( tmp ), "=m"( *pw ):
+ "m"( *pw ):
+ "memory"
+ );
+
+ return rv;
+}
+
+inline int atomic_conditional_increment( int * pw )
+{
+ // if( *pw != 0 ) ++*pw;
+ // return *pw;
+
+ int rv, tmp;
+
+ __asm__ __volatile__
+ (
+ "0:\n\t"
+ ".set push\n\t"
+#if !defined(__mips_isa_rev) || (__mips_isa_rev < 6)
+ ".set mips2\n\t"
+#endif
+ "ll %0, %2\n\t"
+ "beqz %0, 1f\n\t"
+ "addiu %1, %0, 1\n\t"
+ "sc %1, %2\n\t"
+ ".set pop\n\t"
+ "beqz %1, 0b\n\t"
+ "addiu %0, %0, 1\n\t"
+ "1:":
+ "=&r"( rv ), "=&r"( tmp ), "=m"( *pw ):
+ "m"( *pw ):
+ "memory"
+ );
+
+ return rv;
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ int use_count_; // #shared
+ int weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_decrement( &use_count_ ) == 0 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_decrement( &weak_count_ ) == 0 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return static_cast<int const volatile &>( use_count_ );
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp
new file mode 100644
index 0000000..0fb8074
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp
@@ -0,0 +1,183 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/sp_counted_base_gcc_ppc.hpp - g++ on PowerPC
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+//
+// Lock-free algorithm by Alexander Terekhov
+//
+// Thanks to Ben Hitchings for the #weak + (#shared != 0)
+// formulation
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline void atomic_increment( int * pw )
+{
+ // ++*pw;
+
+ int tmp;
+
+ __asm__
+ (
+ "0:\n\t"
+ "lwarx %1, 0, %2\n\t"
+ "addi %1, %1, 1\n\t"
+ "stwcx. %1, 0, %2\n\t"
+ "bne- 0b":
+
+ "=m"( *pw ), "=&b"( tmp ):
+ "r"( pw ), "m"( *pw ):
+ "cc"
+ );
+}
+
+inline int atomic_decrement( int * pw )
+{
+ // return --*pw;
+
+ int rv;
+
+ __asm__ __volatile__
+ (
+ "sync\n\t"
+ "0:\n\t"
+ "lwarx %1, 0, %2\n\t"
+ "addi %1, %1, -1\n\t"
+ "stwcx. %1, 0, %2\n\t"
+ "bne- 0b\n\t"
+ "isync":
+
+ "=m"( *pw ), "=&b"( rv ):
+ "r"( pw ), "m"( *pw ):
+ "memory", "cc"
+ );
+
+ return rv;
+}
+
+inline int atomic_conditional_increment( int * pw )
+{
+ // if( *pw != 0 ) ++*pw;
+ // return *pw;
+
+ int rv;
+
+ __asm__
+ (
+ "0:\n\t"
+ "lwarx %1, 0, %2\n\t"
+ "cmpwi %1, 0\n\t"
+ "beq 1f\n\t"
+ "addi %1, %1, 1\n\t"
+ "1:\n\t"
+ "stwcx. %1, 0, %2\n\t"
+ "bne- 0b":
+
+ "=m"( *pw ), "=&b"( rv ):
+ "r"( pw ), "m"( *pw ):
+ "cc"
+ );
+
+ return rv;
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ int use_count_; // #shared
+ int weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_decrement( &use_count_ ) == 0 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_decrement( &weak_count_ ) == 0 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return static_cast<int const volatile &>( use_count_ );
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
new file mode 100644
index 0000000..b8bb707
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp
@@ -0,0 +1,168 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_counted_base_gcc_sparc.hpp - g++ on Sparc V8+
+//
+// Copyright (c) 2006 Piotr Wyderski
+// Copyright (c) 2006 Tomas Puverle
+// Copyright (c) 2006 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
+//
+// Thanks to Michael van der Westhuizen
+
+#include <boost/detail/sp_typeinfo.hpp>
+#include <inttypes.h> // int32_t
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ )
+{
+ __asm__ __volatile__( "cas [%1], %2, %0"
+ : "+r" (swap_)
+ : "r" (dest_), "r" (compare_)
+ : "memory" );
+
+ return swap_;
+}
+
+inline int32_t atomic_fetch_and_add( int32_t * pw, int32_t dv )
+{
+ // long r = *pw;
+ // *pw += dv;
+ // return r;
+
+ for( ;; )
+ {
+ int32_t r = *pw;
+
+ if( __builtin_expect((compare_and_swap(pw, r, r + dv) == r), 1) )
+ {
+ return r;
+ }
+ }
+}
+
+inline void atomic_increment( int32_t * pw )
+{
+ atomic_fetch_and_add( pw, 1 );
+}
+
+inline int32_t atomic_decrement( int32_t * pw )
+{
+ return atomic_fetch_and_add( pw, -1 );
+}
+
+inline int32_t atomic_conditional_increment( int32_t * pw )
+{
+ // long r = *pw;
+ // if( r != 0 ) ++*pw;
+ // return r;
+
+ for( ;; )
+ {
+ int32_t r = *pw;
+
+ if( r == 0 )
+ {
+ return r;
+ }
+
+ if( __builtin_expect( ( compare_and_swap( pw, r, r + 1 ) == r ), 1 ) )
+ {
+ return r;
+ }
+ }
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ int32_t use_count_; // #shared
+ int32_t weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_decrement( &use_count_ ) == 1 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_decrement( &weak_count_ ) == 1 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return const_cast< int32_t const volatile & >( use_count_ );
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
new file mode 100644
index 0000000..3d2dd61
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
@@ -0,0 +1,175 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/sp_counted_base_gcc_x86.hpp - g++ on 486+ or AMD64
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+//
+// Lock-free algorithm by Alexander Terekhov
+//
+// Thanks to Ben Hitchings for the #weak + (#shared != 0)
+// formulation
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline int atomic_exchange_and_add( int * pw, int dv )
+{
+ // int r = *pw;
+ // *pw += dv;
+ // return r;
+
+ int r;
+
+ __asm__ __volatile__
+ (
+ "lock\n\t"
+ "xadd %1, %0":
+ "=m"( *pw ), "=r"( r ): // outputs (%0, %1)
+ "m"( *pw ), "1"( dv ): // inputs (%2, %3 == %1)
+ "memory", "cc" // clobbers
+ );
+
+ return r;
+}
+
+inline void atomic_increment( int * pw )
+{
+ //atomic_exchange_and_add( pw, 1 );
+
+ __asm__
+ (
+ "lock\n\t"
+ "incl %0":
+ "=m"( *pw ): // output (%0)
+ "m"( *pw ): // input (%1)
+ "cc" // clobbers
+ );
+}
+
+inline int atomic_conditional_increment( int * pw )
+{
+ // int rv = *pw;
+ // if( rv != 0 ) ++*pw;
+ // return rv;
+
+ int rv, tmp;
+
+ __asm__
+ (
+ "movl %0, %%eax\n\t"
+ "0:\n\t"
+ "test %%eax, %%eax\n\t"
+ "je 1f\n\t"
+ "movl %%eax, %2\n\t"
+ "incl %2\n\t"
+ "lock\n\t"
+ "cmpxchgl %2, %0\n\t"
+ "jne 0b\n\t"
+ "1:":
+ "=m"( *pw ), "=&a"( rv ), "=&r"( tmp ): // outputs (%0, %1, %2)
+ "m"( *pw ): // input (%3)
+ "cc" // clobbers
+ );
+
+ return rv;
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ int use_count_; // #shared
+ int weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return static_cast<int const volatile &>( use_count_ );
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_nt.hpp b/include/boost/smart_ptr/detail/sp_counted_base_nt.hpp
new file mode 100644
index 0000000..dea905c
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_nt.hpp
@@ -0,0 +1,109 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/sp_counted_base_nt.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ long use_count_; // #shared
+ long weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ ++use_count_;
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ if( use_count_ == 0 ) return false;
+ ++use_count_;
+ return true;
+ }
+
+ void release() // nothrow
+ {
+ if( --use_count_ == 0 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ ++weak_count_;
+ }
+
+ void weak_release() // nothrow
+ {
+ if( --weak_count_ == 0 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return use_count_;
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp b/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp
new file mode 100644
index 0000000..85f2563
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp
@@ -0,0 +1,138 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/sp_counted_base_pt.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/assert.hpp>
+#include <pthread.h>
+
+namespace boost
+{
+
+namespace detail
+{
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ long use_count_; // #shared
+ long weak_count_; // #weak + (#shared != 0)
+
+ mutable pthread_mutex_t m_;
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
+
+#if defined(__hpux) && defined(_DECTHREADS_)
+ BOOST_VERIFY( pthread_mutex_init( &m_, pthread_mutexattr_default ) == 0 );
+#else
+ BOOST_VERIFY( pthread_mutex_init( &m_, 0 ) == 0 );
+#endif
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ BOOST_VERIFY( pthread_mutex_destroy( &m_ ) == 0 );
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
+ ++use_count_;
+ BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
+ bool r = use_count_ == 0? false: ( ++use_count_, true );
+ BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
+ return r;
+ }
+
+ void release() // nothrow
+ {
+ BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
+ long new_use_count = --use_count_;
+ BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
+
+ if( new_use_count == 0 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
+ ++weak_count_;
+ BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
+ }
+
+ void weak_release() // nothrow
+ {
+ BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
+ long new_weak_count = --weak_count_;
+ BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
+
+ if( new_weak_count == 0 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
+ long r = use_count_;
+ BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
+
+ return r;
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp b/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp
new file mode 100644
index 0000000..7b5f917
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp
@@ -0,0 +1,163 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SNC_PS3_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SNC_PS3_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_counted_base_gcc_sparc.hpp - g++ on Sparc V8+
+//
+// Copyright (c) 2006 Piotr Wyderski
+// Copyright (c) 2006 Tomas Puverle
+// Copyright (c) 2006 Peter Dimov
+// Copyright (c) 2011 Emil Dotchevski
+//
+// 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
+//
+// Thanks to Michael van der Westhuizen
+
+#include <boost/detail/sp_typeinfo.hpp>
+#include <inttypes.h> // uint32_t
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline uint32_t compare_and_swap( uint32_t * dest_, uint32_t compare_, uint32_t swap_ )
+{
+ return __builtin_cellAtomicCompareAndSwap32(dest_,compare_,swap_);
+}
+
+inline uint32_t atomic_fetch_and_add( uint32_t * pw, uint32_t dv )
+{
+ // long r = *pw;
+ // *pw += dv;
+ // return r;
+
+ for( ;; )
+ {
+ uint32_t r = *pw;
+
+ if( __builtin_expect((compare_and_swap(pw, r, r + dv) == r), 1) )
+ {
+ return r;
+ }
+ }
+}
+
+inline void atomic_increment( uint32_t * pw )
+{
+ (void) __builtin_cellAtomicIncr32( pw );
+}
+
+inline uint32_t atomic_decrement( uint32_t * pw )
+{
+ return __builtin_cellAtomicDecr32( pw );
+}
+
+inline uint32_t atomic_conditional_increment( uint32_t * pw )
+{
+ // long r = *pw;
+ // if( r != 0 ) ++*pw;
+ // return r;
+
+ for( ;; )
+ {
+ uint32_t r = *pw;
+
+ if( r == 0 )
+ {
+ return r;
+ }
+
+ if( __builtin_expect( ( compare_and_swap( pw, r, r + 1 ) == r ), 1 ) )
+ {
+ return r;
+ }
+ }
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ uint32_t use_count_; // #shared
+ uint32_t weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_decrement( &use_count_ ) == 1 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_decrement( &weak_count_ ) == 1 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return const_cast< uint32_t const volatile & >( use_count_ );
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SNC_PS3_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp b/include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp
new file mode 100644
index 0000000..0db9c6c
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp
@@ -0,0 +1,115 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED
+
+//
+// detail/sp_counted_base_solaris.hpp
+// based on: detail/sp_counted_base_w32.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+// Copyright 2006 Michael van der Westhuizen
+//
+// 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)
+//
+//
+// Lock-free algorithm by Alexander Terekhov
+//
+// Thanks to Ben Hitchings for the #weak + (#shared != 0)
+// formulation
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+#include <atomic.h>
+
+namespace boost
+{
+
+namespace detail
+{
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ uint32_t use_count_; // #shared
+ uint32_t weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_inc_32( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ for( ;; )
+ {
+ uint32_t tmp = static_cast< uint32_t const volatile& >( use_count_ );
+ if( tmp == 0 ) return false;
+ if( atomic_cas_32( &use_count_, tmp, tmp + 1 ) == tmp ) return true;
+ }
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_dec_32_nv( &use_count_ ) == 0 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_inc_32( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_dec_32_nv( &weak_count_ ) == 0 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return static_cast<long const volatile &>( use_count_ );
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_spin.hpp b/include/boost/smart_ptr/detail/sp_counted_base_spin.hpp
new file mode 100644
index 0000000..faf503a
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_spin.hpp
@@ -0,0 +1,133 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/sp_counted_base_spin.hpp - spinlock pool atomic emulation
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2008 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)
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/smart_ptr/detail/spinlock_pool.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline int atomic_exchange_and_add( int * pw, int dv )
+{
+ spinlock_pool<1>::scoped_lock lock( pw );
+
+ int r = *pw;
+ *pw += dv;
+ return r;
+}
+
+inline void atomic_increment( int * pw )
+{
+ spinlock_pool<1>::scoped_lock lock( pw );
+ ++*pw;
+}
+
+inline int atomic_conditional_increment( int * pw )
+{
+ spinlock_pool<1>::scoped_lock lock( pw );
+
+ int rv = *pw;
+ if( rv != 0 ) ++*pw;
+ return rv;
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ int use_count_; // #shared
+ int weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ spinlock_pool<1>::scoped_lock lock( &use_count_ );
+ return use_count_;
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp b/include/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp
new file mode 100644
index 0000000..9f562b9
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp
@@ -0,0 +1,138 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_counted_base_std_atomic.hpp - C++11 std::atomic
+//
+// Copyright (c) 2007, 2013 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/detail/sp_typeinfo.hpp>
+#include <atomic>
+#include <cstdint>
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline void atomic_increment( std::atomic_int_least32_t * pw )
+{
+ pw->fetch_add( 1, std::memory_order_relaxed );
+}
+
+inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw )
+{
+ return pw->fetch_sub( 1, std::memory_order_acq_rel );
+}
+
+inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_t * pw )
+{
+ // long r = *pw;
+ // if( r != 0 ) ++*pw;
+ // return r;
+
+ std::int_least32_t r = pw->load( std::memory_order_relaxed );
+
+ for( ;; )
+ {
+ if( r == 0 )
+ {
+ return r;
+ }
+
+ if( pw->compare_exchange_weak( r, r + 1, std::memory_order_relaxed, std::memory_order_relaxed ) )
+ {
+ return r;
+ }
+ }
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ std::atomic_int_least32_t use_count_; // #shared
+ std::atomic_int_least32_t weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_decrement( &use_count_ ) == 1 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_decrement( &weak_count_ ) == 1 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return use_count_.load( std::memory_order_acquire );
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_sync.hpp b/include/boost/smart_ptr/detail/sp_counted_base_sync.hpp
new file mode 100644
index 0000000..d2138e7
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_sync.hpp
@@ -0,0 +1,157 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_counted_base_sync.hpp - g++ 4.1+ __sync intrinsics
+//
+// Copyright (c) 2007 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
+
+#include <boost/detail/sp_typeinfo.hpp>
+#include <limits.h>
+
+#if defined( __ia64__ ) && defined( __INTEL_COMPILER )
+# include <ia64intrin.h>
+#endif
+
+namespace boost
+{
+
+namespace detail
+{
+
+#if INT_MAX >= 2147483647
+
+typedef int sp_int32_t;
+
+#else
+
+typedef long sp_int32_t;
+
+#endif
+
+inline void atomic_increment( sp_int32_t * pw )
+{
+ __sync_fetch_and_add( pw, 1 );
+}
+
+inline sp_int32_t atomic_decrement( sp_int32_t * pw )
+{
+ return __sync_fetch_and_add( pw, -1 );
+}
+
+inline sp_int32_t atomic_conditional_increment( sp_int32_t * pw )
+{
+ // long r = *pw;
+ // if( r != 0 ) ++*pw;
+ // return r;
+
+ sp_int32_t r = *pw;
+
+ for( ;; )
+ {
+ if( r == 0 )
+ {
+ return r;
+ }
+
+ sp_int32_t r2 = __sync_val_compare_and_swap( pw, r, r + 1 );
+
+ if( r2 == r )
+ {
+ return r;
+ }
+ else
+ {
+ r = r2;
+ }
+ }
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ sp_int32_t use_count_; // #shared
+ sp_int32_t weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_decrement( &use_count_ ) == 1 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_decrement( &weak_count_ ) == 1 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return const_cast< sp_int32_t const volatile & >( use_count_ );
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp
new file mode 100644
index 0000000..f2de3b0
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp
@@ -0,0 +1,152 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_VACPP_PPC_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_VACPP_PPC_HPP_INCLUDED
+
+//
+// detail/sp_counted_base_vacpp_ppc.hpp - xlC(vacpp) on POWER
+// based on: detail/sp_counted_base_w32.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+// Copyright 2006 Michael van der Westhuizen
+// Copyright 2012 IBM Corp.
+//
+// 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)
+//
+//
+// Lock-free algorithm by Alexander Terekhov
+//
+// Thanks to Ben Hitchings for the #weak + (#shared != 0)
+// formulation
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+
+extern "builtin" void __lwsync(void);
+extern "builtin" void __isync(void);
+extern "builtin" int __fetch_and_add(volatile int* addr, int val);
+extern "builtin" int __compare_and_swap(volatile int*, int*, int);
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline void atomic_increment( int *pw )
+{
+ // ++*pw;
+ __lwsync();
+ __fetch_and_add(pw, 1);
+ __isync();
+}
+
+inline int atomic_decrement( int *pw )
+{
+ // return --*pw;
+ __lwsync();
+ int originalValue = __fetch_and_add(pw, -1);
+ __isync();
+
+ return (originalValue - 1);
+}
+
+inline int atomic_conditional_increment( int *pw )
+{
+ // if( *pw != 0 ) ++*pw;
+ // return *pw;
+
+ __lwsync();
+ int v = *const_cast<volatile int*>(pw);
+ for (;;)
+ // loop until state is known
+ {
+ if (v == 0) return 0;
+ if (__compare_and_swap(pw, &v, v + 1))
+ {
+ __isync(); return (v + 1);
+ }
+ }
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ int use_count_; // #shared
+ int weak_count_; // #weak + (#shared != 0)
+ char pad[64] __attribute__((__aligned__(64)));
+ // pad to prevent false sharing
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_decrement( &use_count_ ) == 0 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_decrement( &weak_count_ ) == 0 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return *const_cast<volatile int*>(&use_count_);
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_VACPP_PPC_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_base_w32.hpp b/include/boost/smart_ptr/detail/sp_counted_base_w32.hpp
new file mode 100644
index 0000000..960e42e
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_base_w32.hpp
@@ -0,0 +1,132 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/sp_counted_base_w32.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+//
+// Lock-free algorithm by Alexander Terekhov
+//
+// Thanks to Ben Hitchings for the #weak + (#shared != 0)
+// formulation
+//
+
+#include <boost/smart_ptr/detail/sp_interlocked.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/detail/sp_typeinfo.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ long use_count_; // #shared
+ long weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ BOOST_SP_INTERLOCKED_INCREMENT( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ for( ;; )
+ {
+ long tmp = static_cast< long const volatile& >( use_count_ );
+ if( tmp == 0 ) return false;
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1200 )
+
+ // work around a code generation bug
+
+ long tmp2 = tmp + 1;
+ if( BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true;
+
+#else
+
+ if( BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true;
+
+#endif
+ }
+ }
+
+ void release() // nothrow
+ {
+ if( BOOST_SP_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ BOOST_SP_INTERLOCKED_INCREMENT( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( BOOST_SP_INTERLOCKED_DECREMENT( &weak_count_ ) == 0 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return static_cast<long const volatile &>( use_count_ );
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp
new file mode 100644
index 0000000..fa2f75e
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp
@@ -0,0 +1,292 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/sp_counted_impl.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR)
+# error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible.
+#endif
+
+#include <boost/checked_delete.hpp>
+#include <boost/smart_ptr/detail/sp_counted_base.hpp>
+#include <boost/core/addressof.hpp>
+
+#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
+#include <boost/smart_ptr/detail/quick_allocator.hpp>
+#endif
+
+#if defined(BOOST_SP_USE_STD_ALLOCATOR)
+#include <memory> // std::allocator
+#endif
+
+#include <cstddef> // std::size_t
+
+namespace boost
+{
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+
+void sp_scalar_constructor_hook( void * px, std::size_t size, void * pn );
+void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn );
+
+#endif
+
+namespace detail
+{
+
+// get_local_deleter
+
+template<class D> class local_sp_deleter;
+
+template<class D> D * get_local_deleter( D * /*p*/ )
+{
+ return 0;
+}
+
+template<class D> D * get_local_deleter( local_sp_deleter<D> * p );
+
+//
+
+template<class X> class sp_counted_impl_p: public sp_counted_base
+{
+private:
+
+ X * px_;
+
+ sp_counted_impl_p( sp_counted_impl_p const & );
+ sp_counted_impl_p & operator= ( sp_counted_impl_p const & );
+
+ typedef sp_counted_impl_p<X> this_type;
+
+public:
+
+ explicit sp_counted_impl_p( X * px ): px_( px )
+ {
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ boost::sp_scalar_constructor_hook( px, sizeof(X), this );
+#endif
+ }
+
+ virtual void dispose() // nothrow
+ {
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ boost::sp_scalar_destructor_hook( px_, sizeof(X), this );
+#endif
+ boost::checked_delete( px_ );
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & )
+ {
+ return 0;
+ }
+
+ virtual void * get_local_deleter( sp_typeinfo const & )
+ {
+ return 0;
+ }
+
+ virtual void * get_untyped_deleter()
+ {
+ return 0;
+ }
+
+#if defined(BOOST_SP_USE_STD_ALLOCATOR)
+
+ void * operator new( std::size_t )
+ {
+ return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) );
+ }
+
+ void operator delete( void * p )
+ {
+ std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 );
+ }
+
+#endif
+
+#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
+
+ void * operator new( std::size_t )
+ {
+ return quick_allocator<this_type>::alloc();
+ }
+
+ void operator delete( void * p )
+ {
+ quick_allocator<this_type>::dealloc( p );
+ }
+
+#endif
+};
+
+//
+// Borland's Codeguard trips up over the -Vx- option here:
+//
+#ifdef __CODEGUARD__
+# pragma option push -Vx-
+#endif
+
+template<class P, class D> class sp_counted_impl_pd: public sp_counted_base
+{
+private:
+
+ P ptr; // copy constructor must not throw
+ D del; // copy constructor must not throw
+
+ sp_counted_impl_pd( sp_counted_impl_pd const & );
+ sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );
+
+ typedef sp_counted_impl_pd<P, D> this_type;
+
+public:
+
+ // pre: d(p) must not throw
+
+ sp_counted_impl_pd( P p, D & d ): ptr( p ), del( d )
+ {
+ }
+
+ sp_counted_impl_pd( P p ): ptr( p ), del()
+ {
+ }
+
+ virtual void dispose() // nothrow
+ {
+ del( ptr );
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti )
+ {
+ return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0;
+ }
+
+ virtual void * get_local_deleter( sp_typeinfo const & ti )
+ {
+ return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( del ) ): 0;
+ }
+
+ virtual void * get_untyped_deleter()
+ {
+ return &reinterpret_cast<char&>( del );
+ }
+
+#if defined(BOOST_SP_USE_STD_ALLOCATOR)
+
+ void * operator new( std::size_t )
+ {
+ return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) );
+ }
+
+ void operator delete( void * p )
+ {
+ std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 );
+ }
+
+#endif
+
+#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
+
+ void * operator new( std::size_t )
+ {
+ return quick_allocator<this_type>::alloc();
+ }
+
+ void operator delete( void * p )
+ {
+ quick_allocator<this_type>::dealloc( p );
+ }
+
+#endif
+};
+
+template<class P, class D, class A> class sp_counted_impl_pda: public sp_counted_base
+{
+private:
+
+ P p_; // copy constructor must not throw
+ D d_; // copy constructor must not throw
+ A a_; // copy constructor must not throw
+
+ sp_counted_impl_pda( sp_counted_impl_pda const & );
+ sp_counted_impl_pda & operator= ( sp_counted_impl_pda const & );
+
+ typedef sp_counted_impl_pda<P, D, A> this_type;
+
+public:
+
+ // pre: d( p ) must not throw
+
+ sp_counted_impl_pda( P p, D & d, A a ): p_( p ), d_( d ), a_( a )
+ {
+ }
+
+ sp_counted_impl_pda( P p, A a ): p_( p ), d_( a ), a_( a )
+ {
+ }
+
+ virtual void dispose() // nothrow
+ {
+ d_( p_ );
+ }
+
+ virtual void destroy() // nothrow
+ {
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ typedef typename std::allocator_traits<A>::template rebind_alloc< this_type > A2;
+
+#else
+
+ typedef typename A::template rebind< this_type >::other A2;
+
+#endif
+
+ A2 a2( a_ );
+
+ this->~this_type();
+
+ a2.deallocate( this, 1 );
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti )
+ {
+ return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast<char&>( d_ ): 0;
+ }
+
+ virtual void * get_local_deleter( sp_typeinfo const & ti )
+ {
+ return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( d_ ) ): 0;
+ }
+
+ virtual void * get_untyped_deleter()
+ {
+ return &reinterpret_cast<char&>( d_ );
+ }
+};
+
+#ifdef __CODEGUARD__
+# pragma option pop
+#endif
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_disable_deprecated.hpp b/include/boost/smart_ptr/detail/sp_disable_deprecated.hpp
new file mode 100644
index 0000000..f79bdf3
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_disable_deprecated.hpp
@@ -0,0 +1,40 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_DISABLE_DEPRECATED_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_DISABLE_DEPRECATED_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/smart_ptr/detail/sp_disable_deprecated.hpp
+//
+// Copyright 2015 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)
+//
+
+#include <boost/config.hpp>
+
+#if defined( __GNUC__ ) && ( defined( __GXX_EXPERIMENTAL_CXX0X__ ) || ( __cplusplus >= 201103L ) )
+
+# if defined( BOOST_GCC )
+
+# if BOOST_GCC >= 40600
+# define BOOST_SP_DISABLE_DEPRECATED
+# endif
+
+# elif defined( __clang__ ) && defined( __has_warning )
+
+# if __has_warning( "-Wdeprecated-declarations" )
+# define BOOST_SP_DISABLE_DEPRECATED
+# endif
+
+# endif
+
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_DISABLE_DEPRECATED_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_forward.hpp b/include/boost/smart_ptr/detail/sp_forward.hpp
new file mode 100644
index 0000000..8fdec65
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_forward.hpp
@@ -0,0 +1,52 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_FORWARD_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_FORWARD_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_forward.hpp
+//
+// Copyright 2008,2012 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
+
+#include <boost/config.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+#if defined( BOOST_GCC ) && __GNUC__ * 100 + __GNUC_MINOR__ <= 404
+
+// GCC 4.4 supports an outdated version of rvalue references and creates a copy of the forwarded object.
+// This results in warnings 'returning reference to temporary'. Therefore we use a special version similar to std::forward.
+template< class T > T&& sp_forward( T && t ) BOOST_NOEXCEPT
+{
+ return t;
+}
+
+#else
+
+template< class T > T&& sp_forward( T & t ) BOOST_NOEXCEPT
+{
+ return static_cast< T&& >( t );
+}
+
+#endif
+
+#endif
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_FORWARD_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_has_sync.hpp b/include/boost/smart_ptr/detail/sp_has_sync.hpp
new file mode 100644
index 0000000..e1debf0
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_has_sync.hpp
@@ -0,0 +1,69 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/smart_ptr/detail/sp_has_sync.hpp
+//
+// Copyright (c) 2008, 2009 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)
+//
+// Defines the BOOST_SP_HAS_SYNC macro if the __sync_* intrinsics
+// are available.
+//
+
+#ifndef BOOST_SP_NO_SYNC
+
+#if !defined( __c2__ ) && defined( __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 )
+
+# define BOOST_SP_HAS_SYNC
+
+#elif defined( __IBMCPP__ ) && ( __IBMCPP__ >= 1210 ) && !defined( __COMPILER_VER__ )
+
+# define BOOST_SP_HAS_SYNC
+
+#elif !defined( __c2__ ) && defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
+
+#define BOOST_SP_HAS_SYNC
+
+#if defined( __arm__ ) || defined( __armel__ )
+#undef BOOST_SP_HAS_SYNC
+#endif
+
+#if defined( __hppa ) || defined( __hppa__ )
+#undef BOOST_SP_HAS_SYNC
+#endif
+
+#if defined( __m68k__ )
+#undef BOOST_SP_HAS_SYNC
+#endif
+
+#if defined( __sh__ )
+#undef BOOST_SP_HAS_SYNC
+#endif
+
+#if defined( __sparc__ )
+#undef BOOST_SP_HAS_SYNC
+#endif
+
+#if defined( __INTEL_COMPILER ) && !defined( __ia64__ ) && ( __INTEL_COMPILER < 1110 )
+#undef BOOST_SP_HAS_SYNC
+#endif
+
+#if defined(__PATHSCALE__) && ((__PATHCC__ == 4) && (__PATHCC_MINOR__ < 9))
+#undef BOOST_SP_HAS_SYNC
+#endif
+
+#endif
+
+#endif // #ifndef BOOST_SP_NO_SYNC
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_interlocked.hpp b/include/boost/smart_ptr/detail/sp_interlocked.hpp
new file mode 100644
index 0000000..68ce292
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_interlocked.hpp
@@ -0,0 +1,168 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_INTERLOCKED_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_INTERLOCKED_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/detail/sp_interlocked.hpp
+//
+// Copyright 2005, 2014 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
+//
+
+#include <boost/config.hpp>
+
+// BOOST_SP_HAS_INTRIN_H
+
+// VC9 has intrin.h, but it collides with <utility>
+#if defined( BOOST_MSVC ) && BOOST_MSVC >= 1600
+
+# define BOOST_SP_HAS_INTRIN_H
+
+// Unlike __MINGW64__, __MINGW64_VERSION_MAJOR is defined by MinGW-w64 for both 32 and 64-bit targets.
+#elif defined( __MINGW64_VERSION_MAJOR )
+
+// MinGW-w64 provides intrin.h for both 32 and 64-bit targets.
+# define BOOST_SP_HAS_INTRIN_H
+
+#elif defined( __LP64__ )
+
+// We have to use intrin.h on Cygwin 64
+# define BOOST_SP_HAS_INTRIN_H
+
+// Intel C++ on Windows on VC10+ stdlib
+#elif defined( BOOST_INTEL_WIN ) && defined( _CPPLIB_VER ) && _CPPLIB_VER >= 520
+
+# define BOOST_SP_HAS_INTRIN_H
+
+#endif
+
+#if defined( BOOST_USE_WINDOWS_H )
+
+# include <windows.h>
+
+# define BOOST_SP_INTERLOCKED_INCREMENT InterlockedIncrement
+# define BOOST_SP_INTERLOCKED_DECREMENT InterlockedDecrement
+# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE InterlockedCompareExchange
+# define BOOST_SP_INTERLOCKED_EXCHANGE InterlockedExchange
+# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD InterlockedExchangeAdd
+
+#elif defined( BOOST_USE_INTRIN_H ) || defined( BOOST_SP_HAS_INTRIN_H )
+
+#include <intrin.h>
+
+# define BOOST_SP_INTERLOCKED_INCREMENT _InterlockedIncrement
+# define BOOST_SP_INTERLOCKED_DECREMENT _InterlockedDecrement
+# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange
+# define BOOST_SP_INTERLOCKED_EXCHANGE _InterlockedExchange
+# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD _InterlockedExchangeAdd
+
+#elif defined( _WIN32_WCE )
+
+#if _WIN32_WCE >= 0x600
+
+extern "C" long __cdecl _InterlockedIncrement( long volatile * );
+extern "C" long __cdecl _InterlockedDecrement( long volatile * );
+extern "C" long __cdecl _InterlockedCompareExchange( long volatile *, long, long );
+extern "C" long __cdecl _InterlockedExchange( long volatile *, long );
+extern "C" long __cdecl _InterlockedExchangeAdd( long volatile *, long );
+
+# define BOOST_SP_INTERLOCKED_INCREMENT _InterlockedIncrement
+# define BOOST_SP_INTERLOCKED_DECREMENT _InterlockedDecrement
+# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange
+# define BOOST_SP_INTERLOCKED_EXCHANGE _InterlockedExchange
+# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD _InterlockedExchangeAdd
+
+#else
+
+// under Windows CE we still have old-style Interlocked* functions
+
+extern "C" long __cdecl InterlockedIncrement( long* );
+extern "C" long __cdecl InterlockedDecrement( long* );
+extern "C" long __cdecl InterlockedCompareExchange( long*, long, long );
+extern "C" long __cdecl InterlockedExchange( long*, long );
+extern "C" long __cdecl InterlockedExchangeAdd( long*, long );
+
+# define BOOST_SP_INTERLOCKED_INCREMENT InterlockedIncrement
+# define BOOST_SP_INTERLOCKED_DECREMENT InterlockedDecrement
+# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE InterlockedCompareExchange
+# define BOOST_SP_INTERLOCKED_EXCHANGE InterlockedExchange
+# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD InterlockedExchangeAdd
+
+#endif
+
+#elif defined( BOOST_MSVC ) || defined( BOOST_INTEL_WIN )
+
+#if defined( __CLRCALL_PURE_OR_CDECL )
+
+extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedIncrement( long volatile * );
+extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedDecrement( long volatile * );
+extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedCompareExchange( long volatile *, long, long );
+extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedExchange( long volatile *, long );
+extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedExchangeAdd( long volatile *, long );
+
+#else
+
+extern "C" long __cdecl _InterlockedIncrement( long volatile * );
+extern "C" long __cdecl _InterlockedDecrement( long volatile * );
+extern "C" long __cdecl _InterlockedCompareExchange( long volatile *, long, long );
+extern "C" long __cdecl _InterlockedExchange( long volatile *, long );
+extern "C" long __cdecl _InterlockedExchangeAdd( long volatile *, long );
+
+# if defined( BOOST_MSVC ) && BOOST_MSVC == 1310
+//From MSDN, Visual Studio .NET 2003 spedific: To declare one of the interlocked functions
+//for use as an intrinsic, the function must be declared with the leading underscore and
+//the new function must appear in a #pragma intrinsic statement.
+# pragma intrinsic( _InterlockedIncrement )
+# pragma intrinsic( _InterlockedDecrement )
+# pragma intrinsic( _InterlockedCompareExchange )
+# pragma intrinsic( _InterlockedExchange )
+# pragma intrinsic( _InterlockedExchangeAdd )
+# endif
+
+#endif
+
+# define BOOST_SP_INTERLOCKED_INCREMENT _InterlockedIncrement
+# define BOOST_SP_INTERLOCKED_DECREMENT _InterlockedDecrement
+# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange
+# define BOOST_SP_INTERLOCKED_EXCHANGE _InterlockedExchange
+# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD _InterlockedExchangeAdd
+
+#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )
+
+namespace boost
+{
+
+namespace detail
+{
+
+extern "C" __declspec(dllimport) long __stdcall InterlockedIncrement( long volatile * );
+extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement( long volatile * );
+extern "C" __declspec(dllimport) long __stdcall InterlockedCompareExchange( long volatile *, long, long );
+extern "C" __declspec(dllimport) long __stdcall InterlockedExchange( long volatile *, long );
+extern "C" __declspec(dllimport) long __stdcall InterlockedExchangeAdd( long volatile *, long );
+
+} // namespace detail
+
+} // namespace boost
+
+# define BOOST_SP_INTERLOCKED_INCREMENT ::boost::detail::InterlockedIncrement
+# define BOOST_SP_INTERLOCKED_DECREMENT ::boost::detail::InterlockedDecrement
+# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE ::boost::detail::InterlockedCompareExchange
+# define BOOST_SP_INTERLOCKED_EXCHANGE ::boost::detail::InterlockedExchange
+# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD ::boost::detail::InterlockedExchangeAdd
+
+#else
+
+# error "Interlocked intrinsics not available"
+
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_INTERLOCKED_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_noexcept.hpp b/include/boost/smart_ptr/detail/sp_noexcept.hpp
new file mode 100644
index 0000000..1287ba4
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_noexcept.hpp
@@ -0,0 +1,48 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_NOEXCEPT_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_NOEXCEPT_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_noexcept.hpp
+//
+// Copyright 2016, 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
+
+#include <boost/config.hpp>
+
+// BOOST_SP_NOEXCEPT
+
+#if defined( BOOST_MSVC ) && BOOST_MSVC >= 1700 && BOOST_MSVC < 1900
+
+# define BOOST_SP_NOEXCEPT BOOST_NOEXCEPT_OR_NOTHROW
+
+#else
+
+# define BOOST_SP_NOEXCEPT BOOST_NOEXCEPT
+
+#endif
+
+// BOOST_SP_NOEXCEPT_WITH_ASSERT
+
+#if defined(BOOST_DISABLE_ASSERTS) || ( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && defined(NDEBUG) )
+
+# define BOOST_SP_NOEXCEPT_WITH_ASSERT BOOST_SP_NOEXCEPT
+
+#elif defined(BOOST_ENABLE_ASSERT_HANDLER) || ( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && !defined(NDEBUG) )
+
+# define BOOST_SP_NOEXCEPT_WITH_ASSERT
+
+#else
+
+# define BOOST_SP_NOEXCEPT_WITH_ASSERT BOOST_SP_NOEXCEPT
+
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_NOEXCEPT_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/sp_nullptr_t.hpp b/include/boost/smart_ptr/detail/sp_nullptr_t.hpp
new file mode 100644
index 0000000..219ae80
--- /dev/null
+++ b/include/boost/smart_ptr/detail/sp_nullptr_t.hpp
@@ -0,0 +1,45 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_NULLPTR_T_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_NULLPTR_T_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_nullptr_t.hpp
+//
+// Copyright 2013 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/config.hpp>
+#include <cstddef>
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+namespace boost
+{
+
+namespace detail
+{
+
+#if !defined( BOOST_NO_CXX11_DECLTYPE ) && ( ( defined( __clang__ ) && !defined( _LIBCPP_VERSION ) ) || defined( __INTEL_COMPILER ) )
+
+ typedef decltype(nullptr) sp_nullptr_t;
+
+#else
+
+ typedef std::nullptr_t sp_nullptr_t;
+
+#endif
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // !defined( BOOST_NO_CXX11_NULLPTR )
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_NULLPTR_T_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/spinlock.hpp b/include/boost/smart_ptr/detail/spinlock.hpp
new file mode 100644
index 0000000..0b618df
--- /dev/null
+++ b/include/boost/smart_ptr/detail/spinlock.hpp
@@ -0,0 +1,68 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/detail/spinlock.hpp
+//
+// Copyright (c) 2008 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)
+//
+// struct spinlock
+// {
+// void lock();
+// bool try_lock();
+// void unlock();
+//
+// class scoped_lock;
+// };
+//
+// #define BOOST_DETAIL_SPINLOCK_INIT <unspecified>
+//
+
+#include <boost/config.hpp>
+#include <boost/smart_ptr/detail/sp_has_sync.hpp>
+
+#if defined( BOOST_SP_USE_STD_ATOMIC )
+# if !defined( __clang__ )
+# include <boost/smart_ptr/detail/spinlock_std_atomic.hpp>
+# else
+// Clang (at least up to 3.4) can't compile spinlock_pool when
+// using std::atomic, so substitute the __sync implementation instead.
+# include <boost/smart_ptr/detail/spinlock_sync.hpp>
+# endif
+
+#elif defined( BOOST_SP_USE_PTHREADS )
+# include <boost/smart_ptr/detail/spinlock_pt.hpp>
+
+#elif !defined( BOOST_NO_CXX11_HDR_ATOMIC )
+# include <boost/smart_ptr/detail/spinlock_std_atomic.hpp>
+
+#elif defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ )
+# include <boost/smart_ptr/detail/spinlock_gcc_arm.hpp>
+
+#elif defined( BOOST_SP_HAS_SYNC )
+# include <boost/smart_ptr/detail/spinlock_sync.hpp>
+
+#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# include <boost/smart_ptr/detail/spinlock_w32.hpp>
+
+#elif defined(BOOST_HAS_PTHREADS)
+# include <boost/smart_ptr/detail/spinlock_pt.hpp>
+
+#elif !defined(BOOST_HAS_THREADS)
+# include <boost/smart_ptr/detail/spinlock_nt.hpp>
+
+#else
+# error Unrecognized threading platform
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp b/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp
new file mode 100644
index 0000000..24d08a8
--- /dev/null
+++ b/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp
@@ -0,0 +1,121 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED
+
+//
+// Copyright (c) 2008, 2011 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)
+//
+
+#include <boost/smart_ptr/detail/yield_k.hpp>
+
+#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7S__)
+
+# define BOOST_SP_ARM_BARRIER "dmb"
+# define BOOST_SP_ARM_HAS_LDREX
+
+#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__)
+
+# define BOOST_SP_ARM_BARRIER "mcr p15, 0, r0, c7, c10, 5"
+# define BOOST_SP_ARM_HAS_LDREX
+
+#else
+
+# define BOOST_SP_ARM_BARRIER ""
+
+#endif
+
+namespace boost
+{
+
+namespace detail
+{
+
+class spinlock
+{
+public:
+
+ int v_;
+
+public:
+
+ bool try_lock()
+ {
+ int r;
+
+#ifdef BOOST_SP_ARM_HAS_LDREX
+
+ __asm__ __volatile__(
+ "ldrex %0, [%2]; \n"
+ "cmp %0, %1; \n"
+ "strexne %0, %1, [%2]; \n"
+ BOOST_SP_ARM_BARRIER :
+ "=&r"( r ): // outputs
+ "r"( 1 ), "r"( &v_ ): // inputs
+ "memory", "cc" );
+
+#else
+
+ __asm__ __volatile__(
+ "swp %0, %1, [%2];\n"
+ BOOST_SP_ARM_BARRIER :
+ "=&r"( r ): // outputs
+ "r"( 1 ), "r"( &v_ ): // inputs
+ "memory", "cc" );
+
+#endif
+
+ return r == 0;
+ }
+
+ void lock()
+ {
+ for( unsigned k = 0; !try_lock(); ++k )
+ {
+ boost::detail::yield( k );
+ }
+ }
+
+ void unlock()
+ {
+ __asm__ __volatile__( BOOST_SP_ARM_BARRIER ::: "memory" );
+ *const_cast< int volatile* >( &v_ ) = 0;
+ __asm__ __volatile__( BOOST_SP_ARM_BARRIER ::: "memory" );
+ }
+
+public:
+
+ class scoped_lock
+ {
+ private:
+
+ spinlock & sp_;
+
+ scoped_lock( scoped_lock const & );
+ scoped_lock & operator=( scoped_lock const & );
+
+ public:
+
+ explicit scoped_lock( spinlock & sp ): sp_( sp )
+ {
+ sp.lock();
+ }
+
+ ~scoped_lock()
+ {
+ sp_.unlock();
+ }
+ };
+};
+
+} // namespace detail
+} // namespace boost
+
+#define BOOST_DETAIL_SPINLOCK_INIT {0}
+
+#undef BOOST_SP_ARM_BARRIER
+#undef BOOST_SP_ARM_HAS_LDREX
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/spinlock_nt.hpp b/include/boost/smart_ptr/detail/spinlock_nt.hpp
new file mode 100644
index 0000000..1f399d0
--- /dev/null
+++ b/include/boost/smart_ptr/detail/spinlock_nt.hpp
@@ -0,0 +1,89 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// Copyright (c) 2008 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)
+//
+
+#include <boost/assert.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+class spinlock
+{
+public:
+
+ bool locked_;
+
+public:
+
+ inline bool try_lock()
+ {
+ if( locked_ )
+ {
+ return false;
+ }
+ else
+ {
+ locked_ = true;
+ return true;
+ }
+ }
+
+ inline void lock()
+ {
+ BOOST_ASSERT( !locked_ );
+ locked_ = true;
+ }
+
+ inline void unlock()
+ {
+ BOOST_ASSERT( locked_ );
+ locked_ = false;
+ }
+
+public:
+
+ class scoped_lock
+ {
+ private:
+
+ spinlock & sp_;
+
+ scoped_lock( scoped_lock const & );
+ scoped_lock & operator=( scoped_lock const & );
+
+ public:
+
+ explicit scoped_lock( spinlock & sp ): sp_( sp )
+ {
+ sp.lock();
+ }
+
+ ~scoped_lock()
+ {
+ sp_.unlock();
+ }
+ };
+};
+
+} // namespace detail
+} // namespace boost
+
+#define BOOST_DETAIL_SPINLOCK_INIT { false }
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/spinlock_pool.hpp b/include/boost/smart_ptr/detail/spinlock_pool.hpp
new file mode 100644
index 0000000..39cf180
--- /dev/null
+++ b/include/boost/smart_ptr/detail/spinlock_pool.hpp
@@ -0,0 +1,91 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/detail/spinlock_pool.hpp
+//
+// Copyright (c) 2008 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)
+//
+// spinlock_pool<0> is reserved for atomic<>, when/if it arrives
+// spinlock_pool<1> is reserved for shared_ptr reference counts
+// spinlock_pool<2> is reserved for shared_ptr atomic access
+//
+
+#include <boost/config.hpp>
+#include <boost/smart_ptr/detail/spinlock.hpp>
+#include <cstddef>
+
+namespace boost
+{
+
+namespace detail
+{
+
+template< int M > class spinlock_pool
+{
+private:
+
+ static spinlock pool_[ 41 ];
+
+public:
+
+ static spinlock & spinlock_for( void const * pv )
+ {
+#if defined(__VMS) && __INITIAL_POINTER_SIZE == 64
+ std::size_t i = reinterpret_cast< unsigned long long >( pv ) % 41;
+#else
+ std::size_t i = reinterpret_cast< std::size_t >( pv ) % 41;
+#endif
+ return pool_[ i ];
+ }
+
+ class scoped_lock
+ {
+ private:
+
+ spinlock & sp_;
+
+ scoped_lock( scoped_lock const & );
+ scoped_lock & operator=( scoped_lock const & );
+
+ public:
+
+ explicit scoped_lock( void const * pv ): sp_( spinlock_for( pv ) )
+ {
+ sp_.lock();
+ }
+
+ ~scoped_lock()
+ {
+ sp_.unlock();
+ }
+ };
+};
+
+template< int M > spinlock spinlock_pool< M >::pool_[ 41 ] =
+{
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT
+};
+
+} // namespace detail
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/spinlock_pt.hpp b/include/boost/smart_ptr/detail/spinlock_pt.hpp
new file mode 100644
index 0000000..f9cabfc
--- /dev/null
+++ b/include/boost/smart_ptr/detail/spinlock_pt.hpp
@@ -0,0 +1,79 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// Copyright (c) 2008 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)
+//
+
+#include <pthread.h>
+
+namespace boost
+{
+
+namespace detail
+{
+
+class spinlock
+{
+public:
+
+ pthread_mutex_t v_;
+
+public:
+
+ bool try_lock()
+ {
+ return pthread_mutex_trylock( &v_ ) == 0;
+ }
+
+ void lock()
+ {
+ pthread_mutex_lock( &v_ );
+ }
+
+ void unlock()
+ {
+ pthread_mutex_unlock( &v_ );
+ }
+
+public:
+
+ class scoped_lock
+ {
+ private:
+
+ spinlock & sp_;
+
+ scoped_lock( scoped_lock const & );
+ scoped_lock & operator=( scoped_lock const & );
+
+ public:
+
+ explicit scoped_lock( spinlock & sp ): sp_( sp )
+ {
+ sp.lock();
+ }
+
+ ~scoped_lock()
+ {
+ sp_.unlock();
+ }
+ };
+};
+
+} // namespace detail
+} // namespace boost
+
+#define BOOST_DETAIL_SPINLOCK_INIT { PTHREAD_MUTEX_INITIALIZER }
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/spinlock_std_atomic.hpp b/include/boost/smart_ptr/detail/spinlock_std_atomic.hpp
new file mode 100644
index 0000000..a61c1cd
--- /dev/null
+++ b/include/boost/smart_ptr/detail/spinlock_std_atomic.hpp
@@ -0,0 +1,83 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_STD_ATOMIC_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_STD_ATOMIC_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// Copyright (c) 2014 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)
+//
+
+#include <boost/smart_ptr/detail/yield_k.hpp>
+#include <atomic>
+
+namespace boost
+{
+
+namespace detail
+{
+
+class spinlock
+{
+public:
+
+ std::atomic_flag v_;
+
+public:
+
+ bool try_lock()
+ {
+ return !v_.test_and_set( std::memory_order_acquire );
+ }
+
+ void lock()
+ {
+ for( unsigned k = 0; !try_lock(); ++k )
+ {
+ boost::detail::yield( k );
+ }
+ }
+
+ void unlock()
+ {
+ v_ .clear( std::memory_order_release );
+ }
+
+public:
+
+ class scoped_lock
+ {
+ private:
+
+ spinlock & sp_;
+
+ scoped_lock( scoped_lock const & );
+ scoped_lock & operator=( scoped_lock const & );
+
+ public:
+
+ explicit scoped_lock( spinlock & sp ): sp_( sp )
+ {
+ sp.lock();
+ }
+
+ ~scoped_lock()
+ {
+ sp_.unlock();
+ }
+ };
+};
+
+} // namespace detail
+} // namespace boost
+
+#define BOOST_DETAIL_SPINLOCK_INIT { ATOMIC_FLAG_INIT }
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_STD_ATOMIC_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/spinlock_sync.hpp b/include/boost/smart_ptr/detail/spinlock_sync.hpp
new file mode 100644
index 0000000..a7145c5
--- /dev/null
+++ b/include/boost/smart_ptr/detail/spinlock_sync.hpp
@@ -0,0 +1,87 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// Copyright (c) 2008 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)
+//
+
+#include <boost/smart_ptr/detail/yield_k.hpp>
+
+#if defined( __ia64__ ) && defined( __INTEL_COMPILER )
+# include <ia64intrin.h>
+#endif
+
+namespace boost
+{
+
+namespace detail
+{
+
+class spinlock
+{
+public:
+
+ int v_;
+
+public:
+
+ bool try_lock()
+ {
+ int r = __sync_lock_test_and_set( &v_, 1 );
+ return r == 0;
+ }
+
+ void lock()
+ {
+ for( unsigned k = 0; !try_lock(); ++k )
+ {
+ boost::detail::yield( k );
+ }
+ }
+
+ void unlock()
+ {
+ __sync_lock_release( &v_ );
+ }
+
+public:
+
+ class scoped_lock
+ {
+ private:
+
+ spinlock & sp_;
+
+ scoped_lock( scoped_lock const & );
+ scoped_lock & operator=( scoped_lock const & );
+
+ public:
+
+ explicit scoped_lock( spinlock & sp ): sp_( sp )
+ {
+ sp.lock();
+ }
+
+ ~scoped_lock()
+ {
+ sp_.unlock();
+ }
+ };
+};
+
+} // namespace detail
+} // namespace boost
+
+#define BOOST_DETAIL_SPINLOCK_INIT {0}
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/spinlock_w32.hpp b/include/boost/smart_ptr/detail/spinlock_w32.hpp
new file mode 100644
index 0000000..d34e4fc
--- /dev/null
+++ b/include/boost/smart_ptr/detail/spinlock_w32.hpp
@@ -0,0 +1,113 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// Copyright (c) 2008 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)
+//
+
+#include <boost/smart_ptr/detail/sp_interlocked.hpp>
+#include <boost/smart_ptr/detail/yield_k.hpp>
+
+// BOOST_COMPILER_FENCE
+
+#if defined(__INTEL_COMPILER)
+
+#define BOOST_COMPILER_FENCE __memory_barrier();
+
+#elif defined( _MSC_VER ) && _MSC_VER >= 1310
+
+extern "C" void _ReadWriteBarrier();
+#pragma intrinsic( _ReadWriteBarrier )
+
+#define BOOST_COMPILER_FENCE _ReadWriteBarrier();
+
+#elif defined(__GNUC__)
+
+#define BOOST_COMPILER_FENCE __asm__ __volatile__( "" : : : "memory" );
+
+#else
+
+#define BOOST_COMPILER_FENCE
+
+#endif
+
+//
+
+namespace boost
+{
+
+namespace detail
+{
+
+class spinlock
+{
+public:
+
+ long v_;
+
+public:
+
+ bool try_lock()
+ {
+ long r = BOOST_SP_INTERLOCKED_EXCHANGE( &v_, 1 );
+
+ BOOST_COMPILER_FENCE
+
+ return r == 0;
+ }
+
+ void lock()
+ {
+ for( unsigned k = 0; !try_lock(); ++k )
+ {
+ boost::detail::yield( k );
+ }
+ }
+
+ void unlock()
+ {
+ BOOST_COMPILER_FENCE
+ *const_cast< long volatile* >( &v_ ) = 0;
+ }
+
+public:
+
+ class scoped_lock
+ {
+ private:
+
+ spinlock & sp_;
+
+ scoped_lock( scoped_lock const & );
+ scoped_lock & operator=( scoped_lock const & );
+
+ public:
+
+ explicit scoped_lock( spinlock & sp ): sp_( sp )
+ {
+ sp.lock();
+ }
+
+ ~scoped_lock()
+ {
+ sp_.unlock();
+ }
+ };
+};
+
+} // namespace detail
+} // namespace boost
+
+#define BOOST_DETAIL_SPINLOCK_INIT {0}
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/detail/yield_k.hpp b/include/boost/smart_ptr/detail/yield_k.hpp
new file mode 100644
index 0000000..403f32f
--- /dev/null
+++ b/include/boost/smart_ptr/detail/yield_k.hpp
@@ -0,0 +1,183 @@
+#ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// yield_k.hpp
+//
+// Copyright (c) 2008 Peter Dimov
+// Copyright (c) Microsoft Corporation 2014
+//
+// void yield( unsigned k );
+//
+// Typical use:
+//
+// for( unsigned k = 0; !try_lock(); ++k ) yield( k );
+//
+// 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
+//
+
+#include <boost/config.hpp>
+#include <boost/predef.h>
+
+#if BOOST_PLAT_WINDOWS_RUNTIME
+#include <thread>
+#endif
+
+// BOOST_SMT_PAUSE
+
+#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) && !defined(__c2__)
+
+extern "C" void _mm_pause();
+
+#define BOOST_SMT_PAUSE _mm_pause();
+
+#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+
+#define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );
+
+#endif
+
+//
+
+#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )
+
+#if defined( BOOST_USE_WINDOWS_H )
+# include <windows.h>
+#endif
+
+namespace boost
+{
+
+namespace detail
+{
+
+#if !defined( BOOST_USE_WINDOWS_H ) && !BOOST_PLAT_WINDOWS_RUNTIME
+
+#if defined(__clang__) && defined(__x86_64__)
+// clang x64 warns that __stdcall is ignored
+# define BOOST_SP_STDCALL
+#else
+# define BOOST_SP_STDCALL __stdcall
+#endif
+
+#if defined(__LP64__) // Cygwin 64
+ extern "C" __declspec(dllimport) void BOOST_SP_STDCALL Sleep( unsigned int ms );
+#else
+ extern "C" __declspec(dllimport) void BOOST_SP_STDCALL Sleep( unsigned long ms );
+#endif
+
+#undef BOOST_SP_STDCALL
+
+#endif // !defined( BOOST_USE_WINDOWS_H ) && !BOOST_PLAT_WINDOWS_RUNTIME
+
+inline void yield( unsigned k )
+{
+ if( k < 4 )
+ {
+ }
+#if defined( BOOST_SMT_PAUSE )
+ else if( k < 16 )
+ {
+ BOOST_SMT_PAUSE
+ }
+#endif
+#if !BOOST_PLAT_WINDOWS_RUNTIME
+ else if( k < 32 )
+ {
+ Sleep( 0 );
+ }
+ else
+ {
+ Sleep( 1 );
+ }
+#else
+ else
+ {
+ // Sleep isn't supported on the Windows Runtime.
+ std::this_thread::yield();
+ }
+#endif
+}
+
+} // namespace detail
+
+} // namespace boost
+
+#elif defined( BOOST_HAS_PTHREADS )
+
+#ifndef _AIX
+#include <sched.h>
+#else
+ // AIX's sched.h defines ::var which sometimes conflicts with Lambda's var
+ extern "C" int sched_yield(void);
+#endif
+
+#include <time.h>
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline void yield( unsigned k )
+{
+ if( k < 4 )
+ {
+ }
+#if defined( BOOST_SMT_PAUSE )
+ else if( k < 16 )
+ {
+ BOOST_SMT_PAUSE
+ }
+#endif
+ else if( k < 32 || k & 1 )
+ {
+ sched_yield();
+ }
+ else
+ {
+ // g++ -Wextra warns on {} or {0}
+ struct timespec rqtp = { 0, 0 };
+
+ // POSIX says that timespec has tv_sec and tv_nsec
+ // But it doesn't guarantee order or placement
+
+ rqtp.tv_sec = 0;
+ rqtp.tv_nsec = 1000;
+
+ nanosleep( &rqtp, 0 );
+ }
+}
+
+} // namespace detail
+
+} // namespace boost
+
+#else
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline void yield( unsigned )
+{
+}
+
+} // namespace detail
+
+} // namespace boost
+
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/enable_shared_from_raw.hpp b/include/boost/smart_ptr/enable_shared_from_raw.hpp
new file mode 100644
index 0000000..5cd3574
--- /dev/null
+++ b/include/boost/smart_ptr/enable_shared_from_raw.hpp
@@ -0,0 +1,165 @@
+#ifndef BOOST_ENABLE_SHARED_FROM_RAW_HPP_INCLUDED
+#define BOOST_ENABLE_SHARED_FROM_RAW_HPP_INCLUDED
+
+//
+// enable_shared_from_raw.hpp
+//
+// Copyright 2002, 2009, 2014 Peter Dimov
+// Copyright 2008-2009 Frank Mori Hess
+//
+// 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
+//
+
+#include <boost/config.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/assert.hpp>
+#include <boost/detail/workaround.hpp>
+
+namespace boost
+{
+template<typename T> boost::shared_ptr<T> shared_from_raw(T *);
+template<typename T> boost::weak_ptr<T> weak_from_raw(T *);
+
+namespace detail
+{
+template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_raw const * pe );
+
+} // namespace detail
+
+class enable_shared_from_raw
+{
+protected:
+
+ enable_shared_from_raw()
+ {
+ }
+
+ enable_shared_from_raw( enable_shared_from_raw const & )
+ {
+ }
+
+ enable_shared_from_raw & operator=( enable_shared_from_raw const & )
+ {
+ return *this;
+ }
+
+ ~enable_shared_from_raw()
+ {
+ BOOST_ASSERT( shared_this_.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist
+ }
+
+private:
+
+ void init_if_expired() const
+ {
+ if( weak_this_.expired() )
+ {
+ shared_this_.reset( static_cast<void*>(0), detail::esft2_deleter_wrapper() );
+ weak_this_ = shared_this_;
+ }
+ }
+
+ void init_if_empty() const
+ {
+ if( weak_this_._empty() )
+ {
+ shared_this_.reset( static_cast<void*>(0), detail::esft2_deleter_wrapper() );
+ weak_this_ = shared_this_;
+ }
+ }
+
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+private:
+ template<class Y> friend class shared_ptr;
+ template<typename T> friend boost::shared_ptr<T> shared_from_raw(T *);
+ template<typename T> friend boost::weak_ptr<T> weak_from_raw(T *);
+ template< class X, class Y > friend inline void detail::sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_raw const * pe );
+#endif
+
+ shared_ptr<void const volatile> shared_from_this() const
+ {
+ init_if_expired();
+ return shared_ptr<void const volatile>( weak_this_ );
+ }
+
+ shared_ptr<void const volatile> shared_from_this() const volatile
+ {
+ return const_cast< enable_shared_from_raw const * >( this )->shared_from_this();
+ }
+
+ weak_ptr<void const volatile> weak_from_this() const
+ {
+ init_if_empty();
+ return weak_this_;
+ }
+
+ weak_ptr<void const volatile> weak_from_this() const volatile
+ {
+ return const_cast< enable_shared_from_raw const * >( this )->weak_from_this();
+ }
+
+ // Note: invoked automatically by shared_ptr; do not call
+ template<class X, class Y> void _internal_accept_owner( shared_ptr<X> * ppx, Y * ) const
+ {
+ BOOST_ASSERT( ppx != 0 );
+
+ if( weak_this_.expired() )
+ {
+ weak_this_ = *ppx;
+ }
+ else if( shared_this_.use_count() != 0 )
+ {
+ BOOST_ASSERT( ppx->unique() ); // no weak_ptrs should exist either, but there's no way to check that
+
+ detail::esft2_deleter_wrapper * pd = boost::get_deleter<detail::esft2_deleter_wrapper>( shared_this_ );
+ BOOST_ASSERT( pd != 0 );
+
+ pd->set_deleter( *ppx );
+
+ ppx->reset( shared_this_, ppx->get() );
+ shared_this_.reset();
+ }
+ }
+
+ mutable weak_ptr<void const volatile> weak_this_;
+
+private:
+
+ mutable shared_ptr<void const volatile> shared_this_;
+};
+
+template<typename T>
+boost::shared_ptr<T> shared_from_raw(T *p)
+{
+ BOOST_ASSERT(p != 0);
+ return boost::shared_ptr<T>(p->enable_shared_from_raw::shared_from_this(), p);
+}
+
+template<typename T>
+boost::weak_ptr<T> weak_from_raw(T *p)
+{
+ BOOST_ASSERT(p != 0);
+ boost::weak_ptr<T> result;
+ result._internal_aliasing_assign(p->enable_shared_from_raw::weak_from_this(), p);
+ return result;
+}
+
+namespace detail
+{
+ template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_raw const * pe )
+ {
+ if( pe != 0 )
+ {
+ pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
+ }
+ }
+} // namepsace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_ENABLE_SHARED_FROM_RAW_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/enable_shared_from_this.hpp b/include/boost/smart_ptr/enable_shared_from_this.hpp
new file mode 100644
index 0000000..fc4de0b
--- /dev/null
+++ b/include/boost/smart_ptr/enable_shared_from_this.hpp
@@ -0,0 +1,90 @@
+#ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
+#define BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
+
+//
+// enable_shared_from_this.hpp
+//
+// Copyright 2002, 2009 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
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+#include <boost/smart_ptr/weak_ptr.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+namespace boost
+{
+
+template<class T> class enable_shared_from_this
+{
+protected:
+
+ BOOST_CONSTEXPR enable_shared_from_this() BOOST_SP_NOEXCEPT
+ {
+ }
+
+ BOOST_CONSTEXPR enable_shared_from_this(enable_shared_from_this const &) BOOST_SP_NOEXCEPT
+ {
+ }
+
+ enable_shared_from_this & operator=(enable_shared_from_this const &) BOOST_SP_NOEXCEPT
+ {
+ return *this;
+ }
+
+ ~enable_shared_from_this() BOOST_SP_NOEXCEPT // ~weak_ptr<T> newer throws, so this call also must not throw
+ {
+ }
+
+public:
+
+ shared_ptr<T> shared_from_this()
+ {
+ shared_ptr<T> p( weak_this_ );
+ BOOST_ASSERT( p.get() == this );
+ return p;
+ }
+
+ shared_ptr<T const> shared_from_this() const
+ {
+ shared_ptr<T const> p( weak_this_ );
+ BOOST_ASSERT( p.get() == this );
+ return p;
+ }
+
+ weak_ptr<T> weak_from_this() BOOST_SP_NOEXCEPT
+ {
+ return weak_this_;
+ }
+
+ weak_ptr<T const> weak_from_this() const BOOST_SP_NOEXCEPT
+ {
+ return weak_this_;
+ }
+
+public: // actually private, but avoids compiler template friendship issues
+
+ // Note: invoked automatically by shared_ptr; do not call
+ template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const BOOST_SP_NOEXCEPT
+ {
+ if( weak_this_.expired() )
+ {
+ weak_this_ = shared_ptr<T>( *ppx, py );
+ }
+ }
+
+private:
+
+ mutable weak_ptr<T> weak_this_;
+};
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp
new file mode 100644
index 0000000..0ab075d
--- /dev/null
+++ b/include/boost/smart_ptr/intrusive_ptr.hpp
@@ -0,0 +1,361 @@
+#ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
+#define BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
+
+//
+// intrusive_ptr.hpp
+//
+// Copyright (c) 2001, 2002 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+#include <boost/config.hpp>
+
+#include <boost/assert.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/smart_ptr/detail/sp_convertible.hpp>
+#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
+
+#include <boost/config/no_tr1/functional.hpp> // for std::less
+
+#if !defined(BOOST_NO_IOSTREAM)
+#if !defined(BOOST_NO_IOSFWD)
+#include <iosfwd> // for std::basic_ostream
+#else
+#include <ostream>
+#endif
+#endif
+
+
+namespace boost
+{
+
+//
+// intrusive_ptr
+//
+// A smart pointer that uses intrusive reference counting.
+//
+// Relies on unqualified calls to
+//
+// void intrusive_ptr_add_ref(T * p);
+// void intrusive_ptr_release(T * p);
+//
+// (p != 0)
+//
+// The object is responsible for destroying itself.
+//
+
+template<class T> class intrusive_ptr
+{
+private:
+
+ typedef intrusive_ptr this_type;
+
+public:
+
+ typedef T element_type;
+
+ BOOST_CONSTEXPR intrusive_ptr() BOOST_SP_NOEXCEPT : px( 0 )
+ {
+ }
+
+ intrusive_ptr( T * p, bool add_ref = true ): px( p )
+ {
+ if( px != 0 && add_ref ) intrusive_ptr_add_ref( px );
+ }
+
+#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
+
+ template<class U>
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ intrusive_ptr( intrusive_ptr<U> const & rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty() )
+
+#else
+
+ intrusive_ptr( intrusive_ptr<U> const & rhs )
+
+#endif
+ : px( rhs.get() )
+ {
+ if( px != 0 ) intrusive_ptr_add_ref( px );
+ }
+
+#endif
+
+ intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px )
+ {
+ if( px != 0 ) intrusive_ptr_add_ref( px );
+ }
+
+ ~intrusive_ptr()
+ {
+ if( px != 0 ) intrusive_ptr_release( px );
+ }
+
+#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
+
+ template<class U> intrusive_ptr & operator=(intrusive_ptr<U> const & rhs)
+ {
+ this_type(rhs).swap(*this);
+ return *this;
+ }
+
+#endif
+
+// Move support
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ intrusive_ptr(intrusive_ptr && rhs) BOOST_SP_NOEXCEPT : px( rhs.px )
+ {
+ rhs.px = 0;
+ }
+
+ intrusive_ptr & operator=(intrusive_ptr && rhs) BOOST_SP_NOEXCEPT
+ {
+ this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);
+ return *this;
+ }
+
+ template<class U> friend class intrusive_ptr;
+
+ template<class U>
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ intrusive_ptr(intrusive_ptr<U> && rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty())
+
+#else
+
+ intrusive_ptr(intrusive_ptr<U> && rhs)
+
+#endif
+ : px( rhs.px )
+ {
+ rhs.px = 0;
+ }
+
+ template<class U>
+ intrusive_ptr & operator=(intrusive_ptr<U> && rhs) BOOST_SP_NOEXCEPT
+ {
+ this_type( static_cast< intrusive_ptr<U> && >( rhs ) ).swap(*this);
+ return *this;
+ }
+
+#endif
+
+ intrusive_ptr & operator=(intrusive_ptr const & rhs)
+ {
+ this_type(rhs).swap(*this);
+ return *this;
+ }
+
+ intrusive_ptr & operator=(T * rhs)
+ {
+ this_type(rhs).swap(*this);
+ return *this;
+ }
+
+ void reset()
+ {
+ this_type().swap( *this );
+ }
+
+ void reset( T * rhs )
+ {
+ this_type( rhs ).swap( *this );
+ }
+
+ void reset( T * rhs, bool add_ref )
+ {
+ this_type( rhs, add_ref ).swap( *this );
+ }
+
+ T * get() const BOOST_SP_NOEXCEPT
+ {
+ return px;
+ }
+
+ T * detach() BOOST_SP_NOEXCEPT
+ {
+ T * ret = px;
+ px = 0;
+ return ret;
+ }
+
+ T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT
+ {
+ BOOST_ASSERT( px != 0 );
+ return *px;
+ }
+
+ T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT
+ {
+ BOOST_ASSERT( px != 0 );
+ return px;
+ }
+
+// implicit conversion to "bool"
+#include <boost/smart_ptr/detail/operator_bool.hpp>
+
+ void swap(intrusive_ptr & rhs) BOOST_SP_NOEXCEPT
+ {
+ T * tmp = px;
+ px = rhs.px;
+ rhs.px = tmp;
+ }
+
+private:
+
+ T * px;
+};
+
+template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
+{
+ return a.get() == b.get();
+}
+
+template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
+{
+ return a.get() != b.get();
+}
+
+template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b) BOOST_SP_NOEXCEPT
+{
+ return a.get() == b;
+}
+
+template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b) BOOST_SP_NOEXCEPT
+{
+ return a.get() != b;
+}
+
+template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
+{
+ return a == b.get();
+}
+
+template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
+{
+ return a != b.get();
+}
+
+#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
+
+// Resolve the ambiguity between our op!= and the one in rel_ops
+
+template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) BOOST_SP_NOEXCEPT
+{
+ return a.get() != b.get();
+}
+
+#endif
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+template<class T> inline bool operator==( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator==( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator!=( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+#endif
+
+template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) BOOST_SP_NOEXCEPT
+{
+ return std::less<T *>()(a.get(), b.get());
+}
+
+template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) BOOST_SP_NOEXCEPT
+{
+ lhs.swap(rhs);
+}
+
+// mem_fn support
+
+template<class T> T * get_pointer(intrusive_ptr<T> const & p) BOOST_SP_NOEXCEPT
+{
+ return p.get();
+}
+
+template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
+{
+ return static_cast<T *>(p.get());
+}
+
+template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
+{
+ return const_cast<T *>(p.get());
+}
+
+template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
+{
+ return dynamic_cast<T *>(p.get());
+}
+
+// operator<<
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
+
+template<class Y> std::ostream & operator<< (std::ostream & os, intrusive_ptr<Y> const & p)
+{
+ os << p.get();
+ return os;
+}
+
+#else
+
+// in STLport's no-iostreams mode no iostream symbols can be used
+#ifndef _STLP_NO_IOSTREAMS
+
+# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
+// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
+using std::basic_ostream;
+template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
+# else
+template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
+# endif
+{
+ os << p.get();
+ return os;
+}
+
+#endif // _STLP_NO_IOSTREAMS
+
+#endif // __GNUC__ < 3
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+// hash_value
+
+template< class T > struct hash;
+
+template< class T > std::size_t hash_value( boost::intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return boost::hash< T* >()( p.get() );
+}
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/intrusive_ref_counter.hpp b/include/boost/smart_ptr/intrusive_ref_counter.hpp
new file mode 100644
index 0000000..c2f918d
--- /dev/null
+++ b/include/boost/smart_ptr/intrusive_ref_counter.hpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * 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)
+ */
+/*!
+ * \file intrusive_ref_counter.hpp
+ * \author Andrey Semashev
+ * \date 12.03.2009
+ *
+ * This header contains a reference counter class for \c intrusive_ptr.
+ */
+
+#ifndef BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
+#define BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
+
+#include <boost/config.hpp>
+#include <boost/smart_ptr/detail/atomic_count.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+// This is a bogus MSVC warning, which is flagged by friend declarations of intrusive_ptr_add_ref and intrusive_ptr_release in intrusive_ref_counter:
+// 'name' : the inline specifier cannot be used when a friend declaration refers to a specialization of a function template
+// Note that there is no inline specifier in the declarations.
+#pragma warning(disable: 4396)
+#endif
+
+namespace boost {
+
+namespace sp_adl_block {
+
+/*!
+ * \brief Thread unsafe reference counter policy for \c intrusive_ref_counter
+ *
+ * The policy instructs the \c intrusive_ref_counter base class to implement
+ * a reference counter suitable for single threaded use only. Pointers to the same
+ * object with this kind of reference counter must not be used by different threads.
+ */
+struct thread_unsafe_counter
+{
+ typedef unsigned int type;
+
+ static unsigned int load(unsigned int const& counter) BOOST_SP_NOEXCEPT
+ {
+ return counter;
+ }
+
+ static void increment(unsigned int& counter) BOOST_SP_NOEXCEPT
+ {
+ ++counter;
+ }
+
+ static unsigned int decrement(unsigned int& counter) BOOST_SP_NOEXCEPT
+ {
+ return --counter;
+ }
+};
+
+/*!
+ * \brief Thread safe reference counter policy for \c intrusive_ref_counter
+ *
+ * The policy instructs the \c intrusive_ref_counter base class to implement
+ * a thread-safe reference counter, if the target platform supports multithreading.
+ */
+struct thread_safe_counter
+{
+ typedef boost::detail::atomic_count type;
+
+ static unsigned int load(boost::detail::atomic_count const& counter) BOOST_SP_NOEXCEPT
+ {
+ return static_cast< unsigned int >(static_cast< long >(counter));
+ }
+
+ static void increment(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT
+ {
+ ++counter;
+ }
+
+ static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT
+ {
+ return static_cast< unsigned int >(--counter);
+ }
+};
+
+template< typename DerivedT, typename CounterPolicyT = thread_safe_counter >
+class intrusive_ref_counter;
+
+template< typename DerivedT, typename CounterPolicyT >
+void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
+template< typename DerivedT, typename CounterPolicyT >
+void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
+
+/*!
+ * \brief A reference counter base class
+ *
+ * This base class can be used with user-defined classes to add support
+ * for \c intrusive_ptr. The class contains a reference counter defined by the \c CounterPolicyT.
+ * Upon releasing the last \c intrusive_ptr referencing the object
+ * derived from the \c intrusive_ref_counter class, operator \c delete
+ * is automatically called on the pointer to the object.
+ *
+ * The other template parameter, \c DerivedT, is the user's class that derives from \c intrusive_ref_counter.
+ */
+template< typename DerivedT, typename CounterPolicyT >
+class intrusive_ref_counter
+{
+private:
+ //! Reference counter type
+ typedef typename CounterPolicyT::type counter_type;
+ //! Reference counter
+ mutable counter_type m_ref_counter;
+
+public:
+ /*!
+ * Default constructor
+ *
+ * \post <tt>use_count() == 0</tt>
+ */
+ intrusive_ref_counter() BOOST_SP_NOEXCEPT : m_ref_counter(0)
+ {
+ }
+
+ /*!
+ * Copy constructor
+ *
+ * \post <tt>use_count() == 0</tt>
+ */
+ intrusive_ref_counter(intrusive_ref_counter const&) BOOST_SP_NOEXCEPT : m_ref_counter(0)
+ {
+ }
+
+ /*!
+ * Assignment
+ *
+ * \post The reference counter is not modified after assignment
+ */
+ intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_SP_NOEXCEPT { return *this; }
+
+ /*!
+ * \return The reference counter
+ */
+ unsigned int use_count() const BOOST_SP_NOEXCEPT
+ {
+ return CounterPolicyT::load(m_ref_counter);
+ }
+
+protected:
+ /*!
+ * Destructor
+ */
+ BOOST_DEFAULTED_FUNCTION(~intrusive_ref_counter(), {})
+
+ friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
+ friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
+};
+
+template< typename DerivedT, typename CounterPolicyT >
+inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT
+{
+ CounterPolicyT::increment(p->m_ref_counter);
+}
+
+template< typename DerivedT, typename CounterPolicyT >
+inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT
+{
+ if (CounterPolicyT::decrement(p->m_ref_counter) == 0)
+ delete static_cast< const DerivedT* >(p);
+}
+
+} // namespace sp_adl_block
+
+using sp_adl_block::intrusive_ref_counter;
+using sp_adl_block::thread_unsafe_counter;
+using sp_adl_block::thread_safe_counter;
+
+} // namespace boost
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
diff --git a/include/boost/smart_ptr/local_shared_ptr.hpp b/include/boost/smart_ptr/local_shared_ptr.hpp
new file mode 100644
index 0000000..1bf1fdf
--- /dev/null
+++ b/include/boost/smart_ptr/local_shared_ptr.hpp
@@ -0,0 +1,684 @@
+#ifndef BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED
+#define BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED
+
+// local_shared_ptr.hpp
+//
+// 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+
+namespace boost
+{
+
+template<class T> class local_shared_ptr;
+
+namespace detail
+{
+
+template< class E, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn )
+{
+ boost::detail::sp_assert_convertible< Y, E >();
+
+ typedef boost::detail::local_sp_deleter< boost::checked_deleter<Y> > D;
+
+ boost::shared_ptr<E> p2( p, D() );
+
+ D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() );
+
+ pd->pn_ = p2._internal_count();
+
+ pn = pd;
+}
+
+template< class E, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E[] > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn )
+{
+ boost::detail::sp_assert_convertible< Y[], E[] >();
+
+ typedef boost::detail::local_sp_deleter< boost::checked_array_deleter<E> > D;
+
+ boost::shared_ptr<E[]> p2( p, D() );
+
+ D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() );
+
+ pd->pn_ = p2._internal_count();
+
+ pn = pd;
+}
+
+template< class E, std::size_t N, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E[N] > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn )
+{
+ boost::detail::sp_assert_convertible< Y[N], E[N] >();
+
+ typedef boost::detail::local_sp_deleter< boost::checked_array_deleter<E> > D;
+
+ boost::shared_ptr<E[N]> p2( p, D() );
+
+ D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() );
+
+ pd->pn_ = p2._internal_count();
+
+ pn = pd;
+}
+
+template< class E, class P, class D > inline void lsp_deleter_construct( boost::local_shared_ptr< E > * /*ppx*/, P p, D const& d, boost::detail::local_counted_base * & pn )
+{
+ typedef boost::detail::local_sp_deleter<D> D2;
+
+ boost::shared_ptr<E> p2( p, D2( d ) );
+
+ D2 * pd = static_cast< D2 * >( p2._internal_get_untyped_deleter() );
+
+ pd->pn_ = p2._internal_count();
+
+ pn = pd;
+}
+
+template< class E, class P, class D, class A > inline void lsp_allocator_construct( boost::local_shared_ptr< E > * /*ppx*/, P p, D const& d, A const& a, boost::detail::local_counted_base * & pn )
+{
+ typedef boost::detail::local_sp_deleter<D> D2;
+
+ boost::shared_ptr<E> p2( p, D2( d ), a );
+
+ D2 * pd = static_cast< D2 * >( p2._internal_get_untyped_deleter() );
+
+ pd->pn_ = p2._internal_count();
+
+ pn = pd;
+}
+
+struct lsp_internal_constructor_tag
+{
+};
+
+} // namespace detail
+
+//
+// local_shared_ptr
+//
+// as shared_ptr, but local to a thread.
+// reference count manipulations are non-atomic.
+//
+
+template<class T> class local_shared_ptr
+{
+private:
+
+ typedef local_shared_ptr this_type;
+
+public:
+
+ typedef typename boost::detail::sp_element<T>::type element_type;
+
+private:
+
+ element_type * px;
+ boost::detail::local_counted_base * pn;
+
+ template<class Y> friend class local_shared_ptr;
+
+public:
+
+ // destructor
+
+ ~local_shared_ptr() BOOST_SP_NOEXCEPT
+ {
+ if( pn )
+ {
+ pn->release();
+ }
+ }
+
+ // constructors
+
+ BOOST_CONSTEXPR local_shared_ptr() BOOST_SP_NOEXCEPT : px( 0 ), pn( 0 )
+ {
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ BOOST_CONSTEXPR local_shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn( 0 )
+ {
+ }
+
+#endif
+
+ // internal constructor, used by make_shared
+ BOOST_CONSTEXPR local_shared_ptr( boost::detail::lsp_internal_constructor_tag, element_type * px_, boost::detail::local_counted_base * pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( pn_ )
+ {
+ }
+
+ template<class Y>
+ explicit local_shared_ptr( Y * p ): px( p ), pn( 0 )
+ {
+ boost::detail::lsp_pointer_construct( this, p, pn );
+ }
+
+ template<class Y, class D> local_shared_ptr( Y * p, D d ): px( p ), pn( 0 )
+ {
+ boost::detail::lsp_deleter_construct( this, p, d, pn );
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ template<class D> local_shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( 0 )
+ {
+ boost::detail::lsp_deleter_construct( this, p, d, pn );
+ }
+
+#endif
+
+ template<class Y, class D, class A> local_shared_ptr( Y * p, D d, A a ): px( p ), pn( 0 )
+ {
+ boost::detail::lsp_allocator_construct( this, p, d, a, pn );
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ template<class D, class A> local_shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( 0 )
+ {
+ boost::detail::lsp_allocator_construct( this, p, d, a, pn );
+ }
+
+#endif
+
+ // construction from shared_ptr
+
+ template<class Y> local_shared_ptr( shared_ptr<Y> const & r,
+ typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() )
+ : px( r.get() ), pn( 0 )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ if( r.use_count() != 0 )
+ {
+ pn = new boost::detail::local_counted_impl( r._internal_count() );
+ }
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y> local_shared_ptr( shared_ptr<Y> && r,
+ typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() )
+ : px( r.get() ), pn( 0 )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ if( r.use_count() != 0 )
+ {
+ pn = new boost::detail::local_counted_impl( r._internal_count() );
+ r.reset();
+ }
+ }
+
+#endif
+
+ // construction from unique_ptr
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template< class Y, class D >
+ local_shared_ptr( std::unique_ptr< Y, D > && r,
+ typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() )
+ : px( r.get() ), pn( 0 )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ if( px )
+ {
+ pn = new boost::detail::local_counted_impl( shared_ptr<T>( std::move(r) )._internal_count() );
+ }
+ }
+
+#endif
+
+ template< class Y, class D >
+ local_shared_ptr( boost::movelib::unique_ptr< Y, D > r ); // !
+ // : px( r.get() ), pn( new boost::detail::local_counted_impl( shared_ptr<T>( std::move(r) ) ) )
+ //{
+ // boost::detail::sp_assert_convertible< Y, T >();
+ //}
+
+ // copy constructor
+
+ local_shared_ptr( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
+ {
+ if( pn )
+ {
+ pn->add_ref();
+ }
+ }
+
+ // move constructor
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ local_shared_ptr( local_shared_ptr && r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
+ {
+ r.px = 0;
+ r.pn = 0;
+ }
+
+#endif
+
+ // converting copy constructor
+
+ template<class Y> local_shared_ptr( local_shared_ptr<Y> const & r,
+ typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() ) BOOST_SP_NOEXCEPT
+ : px( r.px ), pn( r.pn )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ if( pn )
+ {
+ pn->add_ref();
+ }
+ }
+
+ // converting move constructor
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y> local_shared_ptr( local_shared_ptr<Y> && r,
+ typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() ) BOOST_SP_NOEXCEPT
+ : px( r.px ), pn( r.pn )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ r.px = 0;
+ r.pn = 0;
+ }
+
+#endif
+
+ // aliasing
+
+ template<class Y>
+ local_shared_ptr( local_shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn )
+ {
+ if( pn )
+ {
+ pn->add_ref();
+ }
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y>
+ local_shared_ptr( local_shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn )
+ {
+ r.px = 0;
+ r.pn = 0;
+ }
+
+#endif
+
+ // assignment
+
+ local_shared_ptr & operator=( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr( r ).swap( *this );
+ return *this;
+ }
+
+ template<class Y> local_shared_ptr & operator=( local_shared_ptr<Y> const & r ) BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr( r ).swap( *this );
+ return *this;
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ local_shared_ptr & operator=( local_shared_ptr && r ) BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr( std::move( r ) ).swap( *this );
+ return *this;
+ }
+
+ template<class Y>
+ local_shared_ptr & operator=( local_shared_ptr<Y> && r ) BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr( std::move( r ) ).swap( *this );
+ return *this;
+ }
+
+#endif
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ local_shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr().swap(*this);
+ return *this;
+ }
+
+#endif
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y, class D>
+ local_shared_ptr & operator=( std::unique_ptr<Y, D> && r )
+ {
+ local_shared_ptr( std::move(r) ).swap( *this );
+ return *this;
+ }
+
+#endif
+
+ template<class Y, class D>
+ local_shared_ptr & operator=( boost::movelib::unique_ptr<Y, D> r ); // !
+
+ // reset
+
+ void reset() BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr().swap( *this );
+ }
+
+ template<class Y> void reset( Y * p ) // Y must be complete
+ {
+ local_shared_ptr( p ).swap( *this );
+ }
+
+ template<class Y, class D> void reset( Y * p, D d )
+ {
+ local_shared_ptr( p, d ).swap( *this );
+ }
+
+ template<class Y, class D, class A> void reset( Y * p, D d, A a )
+ {
+ local_shared_ptr( p, d, a ).swap( *this );
+ }
+
+ template<class Y> void reset( local_shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr( r, p ).swap( *this );
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y> void reset( local_shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT
+ {
+ local_shared_ptr( std::move( r ), p ).swap( *this );
+ }
+
+#endif
+
+ // accessors
+
+ typename boost::detail::sp_dereference< T >::type operator* () const BOOST_SP_NOEXCEPT
+ {
+ return *px;
+ }
+
+ typename boost::detail::sp_member_access< T >::type operator-> () const BOOST_SP_NOEXCEPT
+ {
+ return px;
+ }
+
+ typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const BOOST_SP_NOEXCEPT_WITH_ASSERT
+ {
+ BOOST_ASSERT( px != 0 );
+ BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
+
+ return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
+ }
+
+ element_type * get() const BOOST_SP_NOEXCEPT
+ {
+ return px;
+ }
+
+ // implicit conversion to "bool"
+#include <boost/smart_ptr/detail/operator_bool.hpp>
+
+ long local_use_count() const BOOST_SP_NOEXCEPT
+ {
+ return pn? pn->local_use_count(): 0;
+ }
+
+ // conversions to shared_ptr, weak_ptr
+
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+ template<class Y, class E = typename boost::detail::sp_enable_if_convertible<T,Y>::type> operator shared_ptr<Y>() const BOOST_SP_NOEXCEPT
+#else
+ template<class Y> operator shared_ptr<Y>() const BOOST_SP_NOEXCEPT
+#endif
+ {
+ boost::detail::sp_assert_convertible<T, Y>();
+
+ if( pn )
+ {
+ return shared_ptr<Y>( boost::detail::sp_internal_constructor_tag(), px, pn->local_cb_get_shared_count() );
+ }
+ else
+ {
+ return shared_ptr<Y>();
+ }
+ }
+
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+ template<class Y, class E = typename boost::detail::sp_enable_if_convertible<T,Y>::type> operator weak_ptr<Y>() const BOOST_SP_NOEXCEPT
+#else
+ template<class Y> operator weak_ptr<Y>() const BOOST_SP_NOEXCEPT
+#endif
+ {
+ boost::detail::sp_assert_convertible<T, Y>();
+
+ if( pn )
+ {
+ return shared_ptr<Y>( boost::detail::sp_internal_constructor_tag(), px, pn->local_cb_get_shared_count() );
+ }
+ else
+ {
+ return weak_ptr<Y>();
+ }
+ }
+
+ // swap
+
+ void swap( local_shared_ptr & r ) BOOST_SP_NOEXCEPT
+ {
+ std::swap( px, r.px );
+ std::swap( pn, r.pn );
+ }
+
+ // owner_before
+
+ template<class Y> bool owner_before( local_shared_ptr<Y> const & r ) const BOOST_SP_NOEXCEPT
+ {
+ return std::less< boost::detail::local_counted_base* >()( pn, r.pn );
+ }
+};
+
+template<class T, class U> inline bool operator==( local_shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
+{
+ return a.get() == b.get();
+}
+
+template<class T, class U> inline bool operator!=( local_shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
+{
+ return a.get() != b.get();
+}
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+template<class T> inline bool operator==( local_shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator==( boost::detail::sp_nullptr_t, local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator!=( local_shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+#endif
+
+template<class T, class U> inline bool operator==( local_shared_ptr<T> const & a, shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
+{
+ return a.get() == b.get();
+}
+
+template<class T, class U> inline bool operator!=( local_shared_ptr<T> const & a, shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
+{
+ return a.get() != b.get();
+}
+
+template<class T, class U> inline bool operator==( shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
+{
+ return a.get() == b.get();
+}
+
+template<class T, class U> inline bool operator!=( shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
+{
+ return a.get() != b.get();
+}
+
+template<class T, class U> inline bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) BOOST_SP_NOEXCEPT
+{
+ return a.owner_before( b );
+}
+
+template<class T> inline void swap( local_shared_ptr<T> & a, local_shared_ptr<T> & b ) BOOST_SP_NOEXCEPT
+{
+ a.swap( b );
+}
+
+template<class T, class U> local_shared_ptr<T> static_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
+{
+ (void) static_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = static_cast< E* >( r.get() );
+ return local_shared_ptr<T>( r, p );
+}
+
+template<class T, class U> local_shared_ptr<T> const_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
+{
+ (void) const_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = const_cast< E* >( r.get() );
+ return local_shared_ptr<T>( r, p );
+}
+
+template<class T, class U> local_shared_ptr<T> dynamic_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
+{
+ (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = dynamic_cast< E* >( r.get() );
+ return p? local_shared_ptr<T>( r, p ): local_shared_ptr<T>();
+}
+
+template<class T, class U> local_shared_ptr<T> reinterpret_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
+{
+ (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = reinterpret_cast< E* >( r.get() );
+ return local_shared_ptr<T>( r, p );
+}
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+template<class T, class U> local_shared_ptr<T> static_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) static_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = static_cast< E* >( r.get() );
+ return local_shared_ptr<T>( std::move(r), p );
+}
+
+template<class T, class U> local_shared_ptr<T> const_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) const_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = const_cast< E* >( r.get() );
+ return local_shared_ptr<T>( std::move(r), p );
+}
+
+template<class T, class U> local_shared_ptr<T> dynamic_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = dynamic_cast< E* >( r.get() );
+ return p? local_shared_ptr<T>( std::move(r), p ): local_shared_ptr<T>();
+}
+
+template<class T, class U> local_shared_ptr<T> reinterpret_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename local_shared_ptr<T>::element_type E;
+
+ E * p = reinterpret_cast< E* >( r.get() );
+ return local_shared_ptr<T>( std::move(r), p );
+}
+
+#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+// get_pointer() enables boost::mem_fn to recognize local_shared_ptr
+
+template<class T> inline typename local_shared_ptr<T>::element_type * get_pointer( local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get();
+}
+
+// operator<<
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+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 )
+{
+ os << p.get();
+ return os;
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+// get_deleter
+
+template<class D, class T> D * get_deleter( local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return get_deleter<D>( shared_ptr<T>( p ) );
+}
+
+// hash_value
+
+template< class T > struct hash;
+
+template< class T > std::size_t hash_value( local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return boost::hash< typename local_shared_ptr<T>::element_type* >()( p.get() );
+}
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/make_local_shared.hpp b/include/boost/smart_ptr/make_local_shared.hpp
new file mode 100644
index 0000000..23114fe
--- /dev/null
+++ b/include/boost/smart_ptr/make_local_shared.hpp
@@ -0,0 +1,17 @@
+#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED
+#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED
+
+// make_local_shared.hpp
+//
+// 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
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/make_local_shared_object.hpp>
+#include <boost/smart_ptr/make_local_shared_array.hpp>
+
+#endif // #ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/make_local_shared_array.hpp b/include/boost/smart_ptr/make_local_shared_array.hpp
new file mode 100644
index 0000000..663f834
--- /dev/null
+++ b/include/boost/smart_ptr/make_local_shared_array.hpp
@@ -0,0 +1,67 @@
+/*
+Copyright 2017 Peter Dimov
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP
+#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP
+
+#include <boost/smart_ptr/allocate_local_shared_array.hpp>
+
+namespace boost {
+
+template<class T>
+inline typename detail::lsp_if_size_array<T>::type
+make_local_shared()
+{
+ return boost::allocate_local_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>());
+}
+
+template<class T>
+inline typename detail::lsp_if_size_array<T>::type
+make_local_shared(const typename detail::sp_array_element<T>::type& value)
+{
+ return boost::allocate_local_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), value);
+}
+
+template<class T>
+inline typename detail::lsp_if_array<T>::type
+make_local_shared(std::size_t size)
+{
+ return boost::allocate_local_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), size);
+}
+
+template<class T>
+inline typename detail::lsp_if_array<T>::type
+make_local_shared(std::size_t size,
+ const typename detail::sp_array_element<T>::type& value)
+{
+ return boost::allocate_local_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), size, value);
+}
+
+template<class T>
+inline typename detail::lsp_if_size_array<T>::type
+make_local_shared_noinit()
+{
+ return allocate_local_shared_noinit<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>());
+}
+
+template<class T>
+inline typename detail::lsp_if_array<T>::type
+make_local_shared_noinit(std::size_t size)
+{
+ return allocate_local_shared_noinit<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), size);
+}
+
+} /* boost */
+
+#endif
diff --git a/include/boost/smart_ptr/make_local_shared_object.hpp b/include/boost/smart_ptr/make_local_shared_object.hpp
new file mode 100644
index 0000000..ab83d60
--- /dev/null
+++ b/include/boost/smart_ptr/make_local_shared_object.hpp
@@ -0,0 +1,199 @@
+#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_OBJECT_HPP_INCLUDED
+#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_OBJECT_HPP_INCLUDED
+
+// make_local_shared_object.hpp
+//
+// 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
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/config.hpp>
+#include <utility>
+#include <cstddef>
+
+namespace boost
+{
+
+namespace detail
+{
+
+// lsp_if_not_array
+
+template<class T> struct lsp_if_not_array
+{
+ typedef boost::local_shared_ptr<T> type;
+};
+
+template<class T> struct lsp_if_not_array<T[]>
+{
+};
+
+template<class T, std::size_t N> struct lsp_if_not_array<T[N]>
+{
+};
+
+// lsp_ms_deleter
+
+template<class T, class A> class lsp_ms_deleter: public local_counted_impl_em
+{
+private:
+
+ typedef typename sp_aligned_storage<sizeof(T), ::boost::alignment_of<T>::value>::type storage_type;
+
+ storage_type storage_;
+ A a_;
+ bool initialized_;
+
+private:
+
+ void destroy() BOOST_SP_NOEXCEPT
+ {
+ if( initialized_ )
+ {
+ T * p = reinterpret_cast< T* >( storage_.data_ );
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ std::allocator_traits<A>::destroy( a_, p );
+
+#else
+
+ p->~T();
+
+#endif
+
+ initialized_ = false;
+ }
+ }
+
+public:
+
+ explicit lsp_ms_deleter( A const & a ) BOOST_SP_NOEXCEPT : a_( a ), initialized_( false )
+ {
+ }
+
+ // optimization: do not copy storage_
+ lsp_ms_deleter( lsp_ms_deleter const & r ) BOOST_SP_NOEXCEPT : a_( r.a_), initialized_( false )
+ {
+ }
+
+ ~lsp_ms_deleter() BOOST_SP_NOEXCEPT
+ {
+ destroy();
+ }
+
+ void operator()( T * ) BOOST_SP_NOEXCEPT
+ {
+ destroy();
+ }
+
+ static void operator_fn( T* ) BOOST_SP_NOEXCEPT // operator() can't be static
+ {
+ }
+
+ void * address() BOOST_SP_NOEXCEPT
+ {
+ return storage_.data_;
+ }
+
+ void set_initialized() BOOST_SP_NOEXCEPT
+ {
+ initialized_ = true;
+ }
+};
+
+} // namespace detail
+
+template<class T, class A, class... Args> typename boost::detail::lsp_if_not_array<T>::type allocate_local_shared( A const & a, Args&&... args )
+{
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
+
+#else
+
+ typedef typename A::template rebind<T>::other A2;
+
+#endif
+
+ A2 a2( a );
+
+ typedef boost::detail::lsp_ms_deleter<T, A2> D;
+
+ boost::shared_ptr<T> pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
+
+ D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
+ void * pv = pd->address();
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ std::allocator_traits<A2>::construct( a2, static_cast< T* >( pv ), std::forward<Args>( args )... );
+
+#else
+
+ ::new( pv ) T( std::forward<Args>( args )... );
+
+#endif
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+
+ pd->pn_ = pt._internal_count();
+
+ return boost::local_shared_ptr<T>( boost::detail::lsp_internal_constructor_tag(), pt2, pd );
+}
+
+template<class T, class A> typename boost::detail::lsp_if_not_array<T>::type allocate_local_shared_noinit( A const & a )
+{
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
+
+#else
+
+ typedef typename A::template rebind<T>::other A2;
+
+#endif
+
+ A2 a2( a );
+
+ typedef boost::detail::lsp_ms_deleter< T, std::allocator<T> > D;
+
+ boost::shared_ptr<T> pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
+
+ D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
+ void * pv = pd->address();
+
+ ::new( pv ) T;
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+
+ pd->pn_ = pt._internal_count();
+
+ return boost::local_shared_ptr<T>( boost::detail::lsp_internal_constructor_tag(), pt2, pd );
+}
+
+template<class T, class... Args> typename boost::detail::lsp_if_not_array<T>::type make_local_shared( Args&&... args )
+{
+ return boost::allocate_local_shared<T>( std::allocator<T>(), std::forward<Args>(args)... );
+}
+
+template<class T> typename boost::detail::lsp_if_not_array<T>::type make_local_shared_noinit()
+{
+ return boost::allocate_shared_noinit<T>( std::allocator<T>() );
+}
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/make_shared.hpp b/include/boost/smart_ptr/make_shared.hpp
new file mode 100644
index 0000000..dd9191c
--- /dev/null
+++ b/include/boost/smart_ptr/make_shared.hpp
@@ -0,0 +1,21 @@
+#ifndef BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED
+#define BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED
+
+// make_shared.hpp
+//
+// Copyright (c) 2007, 2008, 2012 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
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/smart_ptr/make_shared_object.hpp>
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_SFINAE )
+# include <boost/smart_ptr/make_shared_array.hpp>
+# include <boost/smart_ptr/allocate_shared_array.hpp>
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp
new file mode 100644
index 0000000..2eaf4db
--- /dev/null
+++ b/include/boost/smart_ptr/make_shared_array.hpp
@@ -0,0 +1,66 @@
+/*
+Copyright 2012-2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
+#define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
+
+#include <boost/smart_ptr/allocate_shared_array.hpp>
+
+namespace boost {
+
+template<class T>
+inline typename detail::sp_if_size_array<T>::type
+make_shared()
+{
+ return boost::allocate_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>());
+}
+
+template<class T>
+inline typename detail::sp_if_size_array<T>::type
+make_shared(const typename detail::sp_array_element<T>::type& value)
+{
+ return boost::allocate_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), value);
+}
+
+template<class T>
+inline typename detail::sp_if_array<T>::type
+make_shared(std::size_t size)
+{
+ return boost::allocate_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), size);
+}
+
+template<class T>
+inline typename detail::sp_if_array<T>::type
+make_shared(std::size_t size,
+ const typename detail::sp_array_element<T>::type& value)
+{
+ return boost::allocate_shared<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), size, value);
+}
+
+template<class T>
+inline typename detail::sp_if_size_array<T>::type
+make_shared_noinit()
+{
+ return allocate_shared_noinit<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>());
+}
+
+template<class T>
+inline typename detail::sp_if_array<T>::type
+make_shared_noinit(std::size_t size)
+{
+ return allocate_shared_noinit<T>(std::allocator<typename
+ detail::sp_array_scalar<T>::type>(), size);
+}
+
+} /* boost */
+
+#endif
diff --git a/include/boost/smart_ptr/make_shared_object.hpp b/include/boost/smart_ptr/make_shared_object.hpp
new file mode 100644
index 0000000..c681602
--- /dev/null
+++ b/include/boost/smart_ptr/make_shared_object.hpp
@@ -0,0 +1,801 @@
+#ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED
+#define BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED
+
+// make_shared_object.hpp
+//
+// Copyright (c) 2007, 2008, 2012 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
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/config.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/detail/sp_forward.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <cstddef>
+#include <new>
+
+namespace boost
+{
+
+namespace detail
+{
+
+template< std::size_t N, std::size_t A > struct sp_aligned_storage
+{
+ union type
+ {
+ char data_[ N ];
+ typename boost::type_with_alignment< A >::type align_;
+ };
+};
+
+template< class T > class sp_ms_deleter
+{
+private:
+
+ typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
+
+ bool initialized_;
+ storage_type storage_;
+
+private:
+
+ void destroy() BOOST_SP_NOEXCEPT
+ {
+ if( initialized_ )
+ {
+#if defined( __GNUC__ )
+
+ // fixes incorrect aliasing warning
+ T * p = reinterpret_cast< T* >( storage_.data_ );
+ p->~T();
+
+#else
+
+ reinterpret_cast< T* >( storage_.data_ )->~T();
+
+#endif
+
+ initialized_ = false;
+ }
+ }
+
+public:
+
+ sp_ms_deleter() BOOST_SP_NOEXCEPT : initialized_( false )
+ {
+ }
+
+ template<class A> explicit sp_ms_deleter( A const & ) BOOST_SP_NOEXCEPT : initialized_( false )
+ {
+ }
+
+ // optimization: do not copy storage_
+ sp_ms_deleter( sp_ms_deleter const & ) BOOST_SP_NOEXCEPT : initialized_( false )
+ {
+ }
+
+ ~sp_ms_deleter() BOOST_SP_NOEXCEPT
+ {
+ destroy();
+ }
+
+ void operator()( T * ) BOOST_SP_NOEXCEPT
+ {
+ destroy();
+ }
+
+ static void operator_fn( T* ) BOOST_SP_NOEXCEPT // operator() can't be static
+ {
+ }
+
+ void * address() BOOST_SP_NOEXCEPT
+ {
+ return storage_.data_;
+ }
+
+ void set_initialized() BOOST_SP_NOEXCEPT
+ {
+ initialized_ = true;
+ }
+};
+
+template< class T, class A > class sp_as_deleter
+{
+private:
+
+ typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
+
+ storage_type storage_;
+ A a_;
+ bool initialized_;
+
+private:
+
+ void destroy() BOOST_SP_NOEXCEPT
+ {
+ if( initialized_ )
+ {
+ T * p = reinterpret_cast< T* >( storage_.data_ );
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ std::allocator_traits<A>::destroy( a_, p );
+
+#else
+
+ p->~T();
+
+#endif
+
+ initialized_ = false;
+ }
+ }
+
+public:
+
+ sp_as_deleter( A const & a ) BOOST_SP_NOEXCEPT : a_( a ), initialized_( false )
+ {
+ }
+
+ // optimization: do not copy storage_
+ sp_as_deleter( sp_as_deleter const & r ) BOOST_SP_NOEXCEPT : a_( r.a_), initialized_( false )
+ {
+ }
+
+ ~sp_as_deleter() BOOST_SP_NOEXCEPT
+ {
+ destroy();
+ }
+
+ void operator()( T * ) BOOST_SP_NOEXCEPT
+ {
+ destroy();
+ }
+
+ static void operator_fn( T* ) BOOST_SP_NOEXCEPT // operator() can't be static
+ {
+ }
+
+ void * address() BOOST_SP_NOEXCEPT
+ {
+ return storage_.data_;
+ }
+
+ void set_initialized() BOOST_SP_NOEXCEPT
+ {
+ initialized_ = true;
+ }
+};
+
+template< class T > struct sp_if_not_array
+{
+ typedef boost::shared_ptr< T > type;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T > struct sp_if_not_array< T[] >
+{
+};
+
+#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
+
+template< class T, std::size_t N > struct sp_if_not_array< T[N] >
+{
+};
+
+#endif
+
+#endif
+
+} // namespace detail
+
+#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
+# define BOOST_SP_MSD( T ) boost::detail::sp_inplace_tag< boost::detail::sp_ms_deleter< T > >()
+#else
+# define BOOST_SP_MSD( T ) boost::detail::sp_ms_deleter< T >()
+#endif
+
+// _noinit versions
+
+template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared_noinit()
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T;
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared_noinit( A const & a )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T;
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+// Variadic templates, rvalue reference
+
+template< class T, class... Args > typename boost::detail::sp_if_not_array< T >::type make_shared( Args && ... args )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T( boost::detail::sp_forward<Args>( args )... );
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A, class... Args > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, Args && ... args )
+{
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
+ A2 a2( a );
+
+ typedef boost::detail::sp_as_deleter< T, A2 > D;
+
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
+
+#else
+
+ typedef boost::detail::sp_ms_deleter< T > D;
+
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a );
+
+#endif
+
+ D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
+ void * pv = pd->address();
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ std::allocator_traits<A2>::construct( a2, static_cast< T* >( pv ), boost::detail::sp_forward<Args>( args )... );
+
+#else
+
+ ::new( pv ) T( boost::detail::sp_forward<Args>( args )... );
+
+#endif
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+#else // !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+// Common zero-argument versions
+
+template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared()
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T();
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T();
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+// C++03 version
+
+template< class T, class A1 >
+typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A, class A1 >
+typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A1, class A2 >
+typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A, class A1, class A2 >
+typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A1, class A2, class A3 >
+typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 ),
+ boost::forward<A3>( a3 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A, class A1, class A2, class A3 >
+typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 ),
+ boost::forward<A3>( a3 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A1, class A2, class A3, class A4 >
+typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 ),
+ boost::forward<A3>( a3 ),
+ boost::forward<A4>( a4 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A, class A1, class A2, class A3, class A4 >
+typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 ),
+ boost::forward<A3>( a3 ),
+ boost::forward<A4>( a4 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A1, class A2, class A3, class A4, class A5 >
+typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 ),
+ boost::forward<A3>( a3 ),
+ boost::forward<A4>( a4 ),
+ boost::forward<A5>( a5 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A, class A1, class A2, class A3, class A4, class A5 >
+typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 ),
+ boost::forward<A3>( a3 ),
+ boost::forward<A4>( a4 ),
+ boost::forward<A5>( a5 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
+typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 ),
+ boost::forward<A3>( a3 ),
+ boost::forward<A4>( a4 ),
+ boost::forward<A5>( a5 ),
+ boost::forward<A6>( a6 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 >
+typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 ),
+ boost::forward<A3>( a3 ),
+ boost::forward<A4>( a4 ),
+ boost::forward<A5>( a5 ),
+ boost::forward<A6>( a6 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
+typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6, BOOST_FWD_REF(A7) a7 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 ),
+ boost::forward<A3>( a3 ),
+ boost::forward<A4>( a4 ),
+ boost::forward<A5>( a5 ),
+ boost::forward<A6>( a6 ),
+ boost::forward<A7>( a7 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
+typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6, BOOST_FWD_REF(A7) a7 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 ),
+ boost::forward<A3>( a3 ),
+ boost::forward<A4>( a4 ),
+ boost::forward<A5>( a5 ),
+ boost::forward<A6>( a6 ),
+ boost::forward<A7>( a7 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
+typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6, BOOST_FWD_REF(A7) a7, BOOST_FWD_REF(A8) a8 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 ),
+ boost::forward<A3>( a3 ),
+ boost::forward<A4>( a4 ),
+ boost::forward<A5>( a5 ),
+ boost::forward<A6>( a6 ),
+ boost::forward<A7>( a7 ),
+ boost::forward<A8>( a8 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
+typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6, BOOST_FWD_REF(A7) a7, BOOST_FWD_REF(A8) a8 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 ),
+ boost::forward<A3>( a3 ),
+ boost::forward<A4>( a4 ),
+ boost::forward<A5>( a5 ),
+ boost::forward<A6>( a6 ),
+ boost::forward<A7>( a7 ),
+ boost::forward<A8>( a8 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
+typename boost::detail::sp_if_not_array< T >::type make_shared( BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6, BOOST_FWD_REF(A7) a7, BOOST_FWD_REF(A8) a8, BOOST_FWD_REF(A9) a9 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 ),
+ boost::forward<A3>( a3 ),
+ boost::forward<A4>( a4 ),
+ boost::forward<A5>( a5 ),
+ boost::forward<A6>( a6 ),
+ boost::forward<A7>( a7 ),
+ boost::forward<A8>( a8 ),
+ boost::forward<A9>( a9 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
+typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(A4) a4, BOOST_FWD_REF(A5) a5, BOOST_FWD_REF(A6) a6, BOOST_FWD_REF(A7) a7, BOOST_FWD_REF(A8) a8, BOOST_FWD_REF(A9) a9 )
+{
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
+
+ boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
+
+ void * pv = pd->address();
+
+ ::new( pv ) T(
+ boost::forward<A1>( a1 ),
+ boost::forward<A2>( a2 ),
+ boost::forward<A3>( a3 ),
+ boost::forward<A4>( a4 ),
+ boost::forward<A5>( a5 ),
+ boost::forward<A6>( a6 ),
+ boost::forward<A7>( a7 ),
+ boost::forward<A8>( a8 ),
+ boost::forward<A9>( a9 )
+ );
+
+ pd->set_initialized();
+
+ T * pt2 = static_cast< T* >( pv );
+
+ boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+ return boost::shared_ptr< T >( pt, pt2 );
+}
+
+#endif // !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+#undef BOOST_SP_MSD
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/make_unique.hpp b/include/boost/smart_ptr/make_unique.hpp
new file mode 100644
index 0000000..eed5033
--- /dev/null
+++ b/include/boost/smart_ptr/make_unique.hpp
@@ -0,0 +1,110 @@
+/*
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_SMART_PTR_MAKE_UNIQUE_HPP
+#define BOOST_SMART_PTR_MAKE_UNIQUE_HPP
+
+#include <boost/config.hpp>
+#include <memory>
+#include <utility>
+
+namespace boost {
+namespace detail {
+
+template<class T>
+struct up_if_object {
+ typedef std::unique_ptr<T> type;
+};
+
+template<class T>
+struct up_if_object<T[]> { };
+
+template<class T, std::size_t N>
+struct up_if_object<T[N]> { };
+
+template<class T>
+struct up_if_array { };
+
+template<class T>
+struct up_if_array<T[]> {
+ typedef std::unique_ptr<T[]> type;
+};
+
+template<class T>
+struct up_remove_reference {
+ typedef T type;
+};
+
+template<class T>
+struct up_remove_reference<T&> {
+ typedef T type;
+};
+
+template<class T>
+struct up_remove_reference<T&&> {
+ typedef T type;
+};
+
+template<class T>
+struct up_element { };
+
+template<class T>
+struct up_element<T[]> {
+ typedef T type;
+};
+
+} /* detail */
+
+template<class T>
+inline typename detail::up_if_object<T>::type
+make_unique()
+{
+ return std::unique_ptr<T>(new T());
+}
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+template<class T, class... Args>
+inline typename detail::up_if_object<T>::type
+make_unique(Args&&... args)
+{
+ return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+#endif
+
+template<class T>
+inline typename detail::up_if_object<T>::type
+make_unique(typename detail::up_remove_reference<T>::type&& value)
+{
+ return std::unique_ptr<T>(new T(std::move(value)));
+}
+
+template<class T>
+inline typename detail::up_if_object<T>::type
+make_unique_noinit()
+{
+ return std::unique_ptr<T>(new T);
+}
+
+template<class T>
+inline typename detail::up_if_array<T>::type
+make_unique(std::size_t size)
+{
+ return std::unique_ptr<T>(new typename
+ detail::up_element<T>::type[size]());
+}
+
+template<class T>
+inline typename detail::up_if_array<T>::type
+make_unique_noinit(std::size_t size)
+{
+ return std::unique_ptr<T>(new typename
+ detail::up_element<T>::type[size]);
+}
+
+} /* boost */
+
+#endif
diff --git a/include/boost/smart_ptr/owner_less.hpp b/include/boost/smart_ptr/owner_less.hpp
new file mode 100644
index 0000000..5f50aeb
--- /dev/null
+++ b/include/boost/smart_ptr/owner_less.hpp
@@ -0,0 +1,34 @@
+#ifndef BOOST_SMART_PTR_OWNER_LESS_HPP_INCLUDED
+#define BOOST_SMART_PTR_OWNER_LESS_HPP_INCLUDED
+
+//
+// owner_less.hpp
+//
+// Copyright (c) 2008 Frank Mori Hess
+// Copyright (c) 2016 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+namespace boost
+{
+
+template<class T = void> struct owner_less
+{
+ typedef bool result_type;
+ typedef T first_argument_type;
+ typedef T second_argument_type;
+
+ template<class U, class V> bool operator()( U const & u, V const & v ) const
+ {
+ return u.owner_before( v );
+ }
+};
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_OWNER_LESS_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/scoped_array.hpp b/include/boost/smart_ptr/scoped_array.hpp
new file mode 100644
index 0000000..05dd05a
--- /dev/null
+++ b/include/boost/smart_ptr/scoped_array.hpp
@@ -0,0 +1,132 @@
+#ifndef BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED
+#define BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED
+
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001, 2002 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/config.hpp>
+#include <boost/assert.hpp>
+#include <boost/checked_delete.hpp>
+#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
+
+#include <boost/detail/workaround.hpp>
+
+#include <cstddef> // for std::ptrdiff_t
+
+namespace boost
+{
+
+// Debug hooks
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+
+void sp_array_constructor_hook(void * p);
+void sp_array_destructor_hook(void * p);
+
+#endif
+
+// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
+// is guaranteed, either on destruction of the scoped_array or via an explicit
+// reset(). Use shared_array or std::vector if your needs are more complex.
+
+template<class T> class scoped_array // noncopyable
+{
+private:
+
+ T * px;
+
+ scoped_array(scoped_array const &);
+ scoped_array & operator=(scoped_array const &);
+
+ typedef scoped_array<T> this_type;
+
+ void operator==( scoped_array const& ) const;
+ void operator!=( scoped_array const& ) const;
+
+public:
+
+ typedef T element_type;
+
+ explicit scoped_array( T * p = 0 ) BOOST_SP_NOEXCEPT : px( p )
+ {
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ boost::sp_array_constructor_hook( px );
+#endif
+ }
+
+ ~scoped_array() BOOST_SP_NOEXCEPT
+ {
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ boost::sp_array_destructor_hook( px );
+#endif
+ boost::checked_array_delete( px );
+ }
+
+ void reset(T * p = 0) BOOST_SP_NOEXCEPT_WITH_ASSERT
+ {
+ BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
+ this_type(p).swap(*this);
+ }
+
+ T & operator[](std::ptrdiff_t i) const BOOST_SP_NOEXCEPT_WITH_ASSERT
+ {
+ BOOST_ASSERT( px != 0 );
+ BOOST_ASSERT( i >= 0 );
+ return px[i];
+ }
+
+ T * get() const BOOST_SP_NOEXCEPT
+ {
+ return px;
+ }
+
+// implicit conversion to "bool"
+#include <boost/smart_ptr/detail/operator_bool.hpp>
+
+ void swap(scoped_array & b) BOOST_SP_NOEXCEPT
+ {
+ T * tmp = b.px;
+ b.px = px;
+ px = tmp;
+ }
+};
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+template<class T> inline bool operator==( scoped_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator==( boost::detail::sp_nullptr_t, scoped_array<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator!=( scoped_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, scoped_array<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+#endif
+
+template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) BOOST_SP_NOEXCEPT
+{
+ a.swap(b);
+}
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/scoped_ptr.hpp b/include/boost/smart_ptr/scoped_ptr.hpp
new file mode 100644
index 0000000..5325eba
--- /dev/null
+++ b/include/boost/smart_ptr/scoped_ptr.hpp
@@ -0,0 +1,167 @@
+#ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
+#define BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
+
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001, 2002 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+
+#include <boost/config.hpp>
+#include <boost/assert.hpp>
+#include <boost/checked_delete.hpp>
+#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
+#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
+#include <boost/detail/workaround.hpp>
+
+#ifndef BOOST_NO_AUTO_PTR
+# include <memory> // for std::auto_ptr
+#endif
+
+#if defined( BOOST_SP_DISABLE_DEPRECATED )
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+namespace boost
+{
+
+// Debug hooks
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+
+void sp_scalar_constructor_hook(void * p);
+void sp_scalar_destructor_hook(void * p);
+
+#endif
+
+// scoped_ptr mimics a built-in pointer except that it guarantees deletion
+// of the object pointed to, either on destruction of the scoped_ptr or via
+// an explicit reset(). scoped_ptr is a simple solution for simple needs;
+// use shared_ptr or std::auto_ptr if your needs are more complex.
+
+template<class T> class scoped_ptr // noncopyable
+{
+private:
+
+ T * px;
+
+ scoped_ptr(scoped_ptr const &);
+ scoped_ptr & operator=(scoped_ptr const &);
+
+ typedef scoped_ptr<T> this_type;
+
+ void operator==( scoped_ptr const& ) const;
+ void operator!=( scoped_ptr const& ) const;
+
+public:
+
+ typedef T element_type;
+
+ explicit scoped_ptr( T * p = 0 ) BOOST_SP_NOEXCEPT : px( p )
+ {
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ boost::sp_scalar_constructor_hook( px );
+#endif
+ }
+
+#ifndef BOOST_NO_AUTO_PTR
+
+ explicit scoped_ptr( std::auto_ptr<T> p ) BOOST_SP_NOEXCEPT : px( p.release() )
+ {
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ boost::sp_scalar_constructor_hook( px );
+#endif
+ }
+
+#endif
+
+ ~scoped_ptr() BOOST_SP_NOEXCEPT
+ {
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ boost::sp_scalar_destructor_hook( px );
+#endif
+ boost::checked_delete( px );
+ }
+
+ void reset(T * p = 0) BOOST_SP_NOEXCEPT_WITH_ASSERT
+ {
+ BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
+ this_type(p).swap(*this);
+ }
+
+ T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT
+ {
+ BOOST_ASSERT( px != 0 );
+ return *px;
+ }
+
+ T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT
+ {
+ BOOST_ASSERT( px != 0 );
+ return px;
+ }
+
+ T * get() const BOOST_SP_NOEXCEPT
+ {
+ return px;
+ }
+
+// implicit conversion to "bool"
+#include <boost/smart_ptr/detail/operator_bool.hpp>
+
+ void swap(scoped_ptr & b) BOOST_SP_NOEXCEPT
+ {
+ T * tmp = b.px;
+ b.px = px;
+ px = tmp;
+ }
+};
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+template<class T> inline bool operator==( scoped_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator==( boost::detail::sp_nullptr_t, scoped_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator!=( scoped_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, scoped_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+#endif
+
+template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) BOOST_SP_NOEXCEPT
+{
+ a.swap(b);
+}
+
+// get_pointer(p) is a generic way to say p.get()
+
+template<class T> inline T * get_pointer(scoped_ptr<T> const & p) BOOST_SP_NOEXCEPT
+{
+ return p.get();
+}
+
+} // namespace boost
+
+#if defined( BOOST_SP_DISABLE_DEPRECATED )
+#pragma GCC diagnostic pop
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp
new file mode 100644
index 0000000..3ffa742
--- /dev/null
+++ b/include/boost/smart_ptr/shared_array.hpp
@@ -0,0 +1,293 @@
+#ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED
+#define BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED
+
+//
+// shared_array.hpp
+//
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001, 2002, 2012 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+#include <boost/config.hpp> // for broken compiler workarounds
+
+#include <memory> // TR1 cyclic inclusion fix
+
+#include <boost/assert.hpp>
+#include <boost/checked_delete.hpp>
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/detail/shared_count.hpp>
+#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
+#include <boost/detail/workaround.hpp>
+
+#include <cstddef> // for std::ptrdiff_t
+#include <algorithm> // for std::swap
+#include <functional> // for std::less
+
+namespace boost
+{
+
+//
+// shared_array
+//
+// shared_array extends shared_ptr to arrays.
+// The array pointed to is deleted when the last shared_array pointing to it
+// is destroyed or reset.
+//
+
+template<class T> class shared_array
+{
+private:
+
+ // Borland 5.5.1 specific workarounds
+ typedef checked_array_deleter<T> deleter;
+ typedef shared_array<T> this_type;
+
+public:
+
+ typedef T element_type;
+
+ shared_array() BOOST_SP_NOEXCEPT : px( 0 ), pn()
+ {
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ shared_array( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn()
+ {
+ }
+
+#endif
+
+ template<class Y>
+ explicit shared_array( Y * p ): px( p ), pn( p, checked_array_deleter<Y>() )
+ {
+ boost::detail::sp_assert_convertible< Y[], T[] >();
+ }
+
+ //
+ // Requirements: D's copy constructor must not throw
+ //
+ // shared_array will release p by calling d(p)
+ //
+
+ template<class Y, class D> shared_array( Y * p, D d ): px( p ), pn( p, d )
+ {
+ boost::detail::sp_assert_convertible< Y[], T[] >();
+ }
+
+ // As above, but with allocator. A's copy constructor shall not throw.
+
+ template<class Y, class D, class A> shared_array( Y * p, D d, A a ): px( p ), pn( p, d, a )
+ {
+ boost::detail::sp_assert_convertible< Y[], T[] >();
+ }
+
+// generated copy constructor, destructor are fine...
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+// ... except in C++0x, move disables the implicit copy
+
+ shared_array( shared_array const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
+ {
+ }
+
+ shared_array( shared_array && r ) BOOST_SP_NOEXCEPT : px( r.px ), pn()
+ {
+ pn.swap( r.pn );
+ r.px = 0;
+ }
+
+#endif
+
+ // conversion
+
+ template<class Y>
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ shared_array( shared_array<Y> const & r, typename boost::detail::sp_enable_if_convertible< Y[], T[] >::type = boost::detail::sp_empty() )
+
+#else
+
+ shared_array( shared_array<Y> const & r )
+
+#endif
+ BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
+ {
+ boost::detail::sp_assert_convertible< Y[], T[] >();
+ }
+
+ // aliasing
+
+ template< class Y >
+ shared_array( shared_array<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn )
+ {
+ }
+
+ // assignment
+
+ shared_array & operator=( shared_array const & r ) BOOST_SP_NOEXCEPT
+ {
+ this_type( r ).swap( *this );
+ return *this;
+ }
+
+#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
+
+ template<class Y>
+ shared_array & operator=( shared_array<Y> const & r ) BOOST_SP_NOEXCEPT
+ {
+ this_type( r ).swap( *this );
+ return *this;
+ }
+
+#endif
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ shared_array & operator=( shared_array && r ) BOOST_SP_NOEXCEPT
+ {
+ this_type( static_cast< shared_array && >( r ) ).swap( *this );
+ return *this;
+ }
+
+ template<class Y>
+ shared_array & operator=( shared_array<Y> && r ) BOOST_SP_NOEXCEPT
+ {
+ this_type( static_cast< shared_array<Y> && >( r ) ).swap( *this );
+ return *this;
+ }
+
+#endif
+
+ void reset() BOOST_SP_NOEXCEPT
+ {
+ this_type().swap( *this );
+ }
+
+ template<class Y> void reset( Y * p ) // Y must be complete
+ {
+ BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
+ this_type( p ).swap( *this );
+ }
+
+ template<class Y, class D> void reset( Y * p, D d )
+ {
+ this_type( p, d ).swap( *this );
+ }
+
+ template<class Y, class D, class A> void reset( Y * p, D d, A a )
+ {
+ this_type( p, d, a ).swap( *this );
+ }
+
+ template<class Y> void reset( shared_array<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT
+ {
+ this_type( r, p ).swap( *this );
+ }
+
+ T & operator[] (std::ptrdiff_t i) const BOOST_SP_NOEXCEPT_WITH_ASSERT
+ {
+ BOOST_ASSERT(px != 0);
+ BOOST_ASSERT(i >= 0);
+ return px[i];
+ }
+
+ T * get() const BOOST_SP_NOEXCEPT
+ {
+ return px;
+ }
+
+// implicit conversion to "bool"
+#include <boost/smart_ptr/detail/operator_bool.hpp>
+
+ bool unique() const BOOST_SP_NOEXCEPT
+ {
+ return pn.unique();
+ }
+
+ long use_count() const BOOST_SP_NOEXCEPT
+ {
+ return pn.use_count();
+ }
+
+ void swap(shared_array<T> & other) BOOST_SP_NOEXCEPT
+ {
+ std::swap(px, other.px);
+ pn.swap(other.pn);
+ }
+
+ void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
+ {
+ return pn.get_deleter( ti );
+ }
+
+private:
+
+ template<class Y> friend class shared_array;
+
+ T * px; // contained pointer
+ detail::shared_count pn; // reference counter
+
+}; // shared_array
+
+template<class T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT
+{
+ return a.get() == b.get();
+}
+
+template<class T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT
+{
+ return a.get() != b.get();
+}
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+template<class T> inline bool operator==( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator!=( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+#endif
+
+template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT
+{
+ return std::less<T*>()(a.get(), b.get());
+}
+
+template<class T> void swap(shared_array<T> & a, shared_array<T> & b) BOOST_SP_NOEXCEPT
+{
+ a.swap(b);
+}
+
+template< class D, class T > D * get_deleter( shared_array<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return static_cast< D * >( p._internal_get_deleter( BOOST_SP_TYPEID(D) ) );
+}
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp
new file mode 100644
index 0000000..4ac0699
--- /dev/null
+++ b/include/boost/smart_ptr/shared_ptr.hpp
@@ -0,0 +1,1184 @@
+#ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
+#define BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
+
+//
+// shared_ptr.hpp
+//
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001-2008 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)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+#include <boost/config.hpp> // for broken compiler workarounds
+
+// In order to avoid circular dependencies with Boost.TR1
+// we make sure that our include of <memory> doesn't try to
+// pull in the TR1 headers: that's why we use this header
+// rather than including <memory> directly:
+#include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
+
+#include <boost/assert.hpp>
+#include <boost/checked_delete.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/smart_ptr/detail/shared_count.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/smart_ptr/detail/sp_convertible.hpp>
+#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
+#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
+
+#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
+#include <boost/smart_ptr/detail/spinlock_pool.hpp>
+#endif
+
+#include <algorithm> // for std::swap
+#include <functional> // for std::less
+#include <typeinfo> // for std::bad_cast
+#include <cstddef> // for std::size_t
+
+#if !defined(BOOST_NO_IOSTREAM)
+#if !defined(BOOST_NO_IOSFWD)
+#include <iosfwd> // for std::basic_ostream
+#else
+#include <ostream>
+#endif
+#endif
+
+#if defined( BOOST_SP_DISABLE_DEPRECATED )
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+namespace boost
+{
+
+template<class T> class shared_ptr;
+template<class T> class weak_ptr;
+template<class T> class enable_shared_from_this;
+class enable_shared_from_raw;
+
+namespace movelib
+{
+
+ template< class T, class D > class unique_ptr;
+
+} // namespace movelib
+
+namespace detail
+{
+
+// sp_element, element_type
+
+template< class T > struct sp_element
+{
+ typedef T type;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T > struct sp_element< T[] >
+{
+ typedef T type;
+};
+
+#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
+
+template< class T, std::size_t N > struct sp_element< T[N] >
+{
+ typedef T type;
+};
+
+#endif
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+// sp_dereference, return type of operator*
+
+template< class T > struct sp_dereference
+{
+ typedef T & type;
+};
+
+template<> struct sp_dereference< void >
+{
+ typedef void type;
+};
+
+#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
+
+template<> struct sp_dereference< void const >
+{
+ typedef void type;
+};
+
+template<> struct sp_dereference< void volatile >
+{
+ typedef void type;
+};
+
+template<> struct sp_dereference< void const volatile >
+{
+ typedef void type;
+};
+
+#endif // !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T > struct sp_dereference< T[] >
+{
+ typedef void type;
+};
+
+#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
+
+template< class T, std::size_t N > struct sp_dereference< T[N] >
+{
+ typedef void type;
+};
+
+#endif
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+// sp_member_access, return type of operator->
+
+template< class T > struct sp_member_access
+{
+ typedef T * type;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T > struct sp_member_access< T[] >
+{
+ typedef void type;
+};
+
+#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
+
+template< class T, std::size_t N > struct sp_member_access< T[N] >
+{
+ typedef void type;
+};
+
+#endif
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+// sp_array_access, return type of operator[]
+
+template< class T > struct sp_array_access
+{
+ typedef void type;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T > struct sp_array_access< T[] >
+{
+ typedef T & type;
+};
+
+#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
+
+template< class T, std::size_t N > struct sp_array_access< T[N] >
+{
+ typedef T & type;
+};
+
+#endif
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+// sp_extent, for operator[] index check
+
+template< class T > struct sp_extent
+{
+ enum _vt { value = 0 };
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T, std::size_t N > struct sp_extent< T[N] >
+{
+ enum _vt { value = N };
+};
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+// enable_shared_from_this support
+
+template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx, Y const * py, boost::enable_shared_from_this< T > const * pe )
+{
+ if( pe != 0 )
+ {
+ pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
+ }
+}
+
+template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_raw const * pe );
+
+#ifdef _MANAGED
+
+// Avoid C4793, ... causes native code generation
+
+struct sp_any_pointer
+{
+ template<class T> sp_any_pointer( T* ) {}
+};
+
+inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
+{
+}
+
+#else // _MANAGED
+
+inline void sp_enable_shared_from_this( ... )
+{
+}
+
+#endif // _MANAGED
+
+#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
+
+// rvalue auto_ptr support based on a technique by Dave Abrahams
+
+template< class T, class R > struct sp_enable_if_auto_ptr
+{
+};
+
+template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
+{
+ typedef R type;
+};
+
+#endif
+
+// sp_assert_convertible
+
+template< class Y, class T > inline void sp_assert_convertible() BOOST_SP_NOEXCEPT
+{
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ // static_assert( sp_convertible< Y, T >::value );
+ typedef char tmp[ sp_convertible< Y, T >::value? 1: -1 ];
+ (void)sizeof( tmp );
+
+#else
+
+ T* p = static_cast< Y* >( 0 );
+ (void)p;
+
+#endif
+}
+
+// pointer constructor helper
+
+template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & pn )
+{
+ boost::detail::shared_count( p ).swap( pn );
+ boost::detail::sp_enable_shared_from_this( ppx, p, p );
+}
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
+{
+ sp_assert_convertible< Y[], T[] >();
+ boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
+}
+
+template< class T, std::size_t N, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
+{
+ sp_assert_convertible< Y[N], T[N] >();
+ boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
+}
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+// deleter constructor helper
+
+template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T > * ppx, Y * p )
+{
+ boost::detail::sp_enable_shared_from_this( ppx, p, p );
+}
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * /*p*/ )
+{
+ sp_assert_convertible< Y[], T[] >();
+}
+
+template< class T, std::size_t N, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * /*p*/ )
+{
+ sp_assert_convertible< Y[N], T[N] >();
+}
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+struct sp_internal_constructor_tag
+{
+};
+
+} // namespace detail
+
+
+//
+// shared_ptr
+//
+// An enhanced relative of scoped_ptr with reference counted copy semantics.
+// The object pointed to is deleted when the last shared_ptr pointing to it
+// is destroyed or reset.
+//
+
+template<class T> class shared_ptr
+{
+private:
+
+ // Borland 5.5.1 specific workaround
+ typedef shared_ptr<T> this_type;
+
+public:
+
+ typedef typename boost::detail::sp_element< T >::type element_type;
+
+ BOOST_CONSTEXPR shared_ptr() BOOST_SP_NOEXCEPT : px( 0 ), pn()
+ {
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ BOOST_CONSTEXPR shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn()
+ {
+ }
+
+#endif
+
+ BOOST_CONSTEXPR shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count const & pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( pn_ )
+ {
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ BOOST_CONSTEXPR shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count && pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( std::move( pn_ ) )
+ {
+ }
+
+#endif
+
+ template<class Y>
+ explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete
+ {
+ boost::detail::sp_pointer_construct( this, p, pn );
+ }
+
+ //
+ // Requirements: D's copy constructor must not throw
+ //
+ // shared_ptr will release p by calling d(p)
+ //
+
+ template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, d )
+ {
+ boost::detail::sp_deleter_construct( this, p );
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ template<class D> shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, d )
+ {
+ }
+
+#endif
+
+ // As above, but with allocator. A's copy constructor shall not throw.
+
+ template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
+ {
+ boost::detail::sp_deleter_construct( this, p );
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ template<class D, class A> shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( p, d, a )
+ {
+ }
+
+#endif
+
+// generated copy constructor, destructor are fine...
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+// ... except in C++0x, move disables the implicit copy
+
+ shared_ptr( shared_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
+ {
+ }
+
+#endif
+
+ template<class Y>
+ explicit shared_ptr( weak_ptr<Y> const & r ): pn( r.pn ) // may throw
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ // it is now safe to copy r.px, as pn(r.pn) did not throw
+ px = r.px;
+ }
+
+ template<class Y>
+ shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag )
+ BOOST_SP_NOEXCEPT : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() )
+ {
+ if( !pn.empty() )
+ {
+ px = r.px;
+ }
+ }
+
+ template<class Y>
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
+
+#else
+
+ shared_ptr( shared_ptr<Y> const & r )
+
+#endif
+ BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+ }
+
+ // aliasing
+ template< class Y >
+ shared_ptr( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn )
+ {
+ }
+
+#ifndef BOOST_NO_AUTO_PTR
+
+ template<class Y>
+ explicit shared_ptr( std::auto_ptr<Y> & r ): px(r.get()), pn()
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ Y * tmp = r.get();
+ pn = boost::detail::shared_count( r );
+
+ boost::detail::sp_deleter_construct( this, tmp );
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y>
+ shared_ptr( std::auto_ptr<Y> && r ): px(r.get()), pn()
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ Y * tmp = r.get();
+ pn = boost::detail::shared_count( r );
+
+ boost::detail::sp_deleter_construct( this, tmp );
+ }
+
+#elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+ template<class Ap>
+ explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
+ {
+ typedef typename Ap::element_type Y;
+
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ Y * tmp = r.get();
+ pn = boost::detail::shared_count( r );
+
+ boost::detail::sp_deleter_construct( this, tmp );
+ }
+
+#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+#endif // BOOST_NO_AUTO_PTR
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template< class Y, class D >
+ shared_ptr( std::unique_ptr< Y, D > && r ): px( r.get() ), pn()
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ typename std::unique_ptr< Y, D >::pointer tmp = r.get();
+
+ if( tmp != 0 )
+ {
+ pn = boost::detail::shared_count( r );
+ boost::detail::sp_deleter_construct( this, tmp );
+ }
+ }
+
+#endif
+
+ template< class Y, class D >
+ shared_ptr( boost::movelib::unique_ptr< Y, D > r ): px( r.get() ), pn()
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ typename boost::movelib::unique_ptr< Y, D >::pointer tmp = r.get();
+
+ if( tmp != 0 )
+ {
+ pn = boost::detail::shared_count( r );
+ boost::detail::sp_deleter_construct( this, tmp );
+ }
+ }
+
+ // assignment
+
+ shared_ptr & operator=( shared_ptr const & r ) BOOST_SP_NOEXCEPT
+ {
+ this_type(r).swap(*this);
+ return *this;
+ }
+
+#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
+
+ template<class Y>
+ shared_ptr & operator=(shared_ptr<Y> const & r) BOOST_SP_NOEXCEPT
+ {
+ this_type(r).swap(*this);
+ return *this;
+ }
+
+#endif
+
+#ifndef BOOST_NO_AUTO_PTR
+
+ template<class Y>
+ shared_ptr & operator=( std::auto_ptr<Y> & r )
+ {
+ this_type( r ).swap( *this );
+ return *this;
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y>
+ shared_ptr & operator=( std::auto_ptr<Y> && r )
+ {
+ this_type( static_cast< std::auto_ptr<Y> && >( r ) ).swap( *this );
+ return *this;
+ }
+
+#elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+ template<class Ap>
+ typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
+ {
+ this_type( r ).swap( *this );
+ return *this;
+ }
+
+#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+#endif // BOOST_NO_AUTO_PTR
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y, class D>
+ shared_ptr & operator=( std::unique_ptr<Y, D> && r )
+ {
+ this_type( static_cast< std::unique_ptr<Y, D> && >( r ) ).swap(*this);
+ return *this;
+ }
+
+#endif
+
+ template<class Y, class D>
+ shared_ptr & operator=( boost::movelib::unique_ptr<Y, D> r )
+ {
+ // this_type( static_cast< unique_ptr<Y, D> && >( r ) ).swap( *this );
+
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ typename boost::movelib::unique_ptr< Y, D >::pointer p = r.get();
+
+ shared_ptr tmp;
+
+ if( p != 0 )
+ {
+ tmp.px = p;
+ tmp.pn = boost::detail::shared_count( r );
+
+ boost::detail::sp_deleter_construct( &tmp, p );
+ }
+
+ tmp.swap( *this );
+
+ return *this;
+ }
+
+// Move support
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ shared_ptr( shared_ptr && r ) BOOST_SP_NOEXCEPT : px( r.px ), pn()
+ {
+ pn.swap( r.pn );
+ r.px = 0;
+ }
+
+ template<class Y>
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
+
+#else
+
+ shared_ptr( shared_ptr<Y> && r )
+
+#endif
+ BOOST_SP_NOEXCEPT : px( r.px ), pn()
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ pn.swap( r.pn );
+ r.px = 0;
+ }
+
+ shared_ptr & operator=( shared_ptr && r ) BOOST_SP_NOEXCEPT
+ {
+ this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
+ return *this;
+ }
+
+ template<class Y>
+ shared_ptr & operator=( shared_ptr<Y> && r ) BOOST_SP_NOEXCEPT
+ {
+ this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
+ return *this;
+ }
+
+ // aliasing move
+ template<class Y>
+ shared_ptr( shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn()
+ {
+ pn.swap( r.pn );
+ r.px = 0;
+ }
+
+#endif
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+ {
+ this_type().swap(*this);
+ return *this;
+ }
+
+#endif
+
+ void reset() BOOST_SP_NOEXCEPT
+ {
+ this_type().swap(*this);
+ }
+
+ template<class Y> void reset( Y * p ) // Y must be complete
+ {
+ BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
+ this_type( p ).swap( *this );
+ }
+
+ template<class Y, class D> void reset( Y * p, D d )
+ {
+ this_type( p, d ).swap( *this );
+ }
+
+ template<class Y, class D, class A> void reset( Y * p, D d, A a )
+ {
+ this_type( p, d, a ).swap( *this );
+ }
+
+ template<class Y> void reset( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT
+ {
+ this_type( r, p ).swap( *this );
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y> void reset( shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT
+ {
+ this_type( static_cast< shared_ptr<Y> && >( r ), p ).swap( *this );
+ }
+
+#endif
+
+ typename boost::detail::sp_dereference< T >::type operator* () const BOOST_SP_NOEXCEPT_WITH_ASSERT
+ {
+ BOOST_ASSERT( px != 0 );
+ return *px;
+ }
+
+ typename boost::detail::sp_member_access< T >::type operator-> () const BOOST_SP_NOEXCEPT_WITH_ASSERT
+ {
+ BOOST_ASSERT( px != 0 );
+ return px;
+ }
+
+ typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const BOOST_SP_NOEXCEPT_WITH_ASSERT
+ {
+ BOOST_ASSERT( px != 0 );
+ BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
+
+ return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
+ }
+
+ element_type * get() const BOOST_SP_NOEXCEPT
+ {
+ return px;
+ }
+
+// implicit conversion to "bool"
+#include <boost/smart_ptr/detail/operator_bool.hpp>
+
+ bool unique() const BOOST_SP_NOEXCEPT
+ {
+ return pn.unique();
+ }
+
+ long use_count() const BOOST_SP_NOEXCEPT
+ {
+ return pn.use_count();
+ }
+
+ void swap( shared_ptr & other ) BOOST_SP_NOEXCEPT
+ {
+ std::swap(px, other.px);
+ pn.swap(other.pn);
+ }
+
+ template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
+ {
+ return pn < rhs.pn;
+ }
+
+ template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
+ {
+ return pn < rhs.pn;
+ }
+
+ void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
+ {
+ return pn.get_deleter( ti );
+ }
+
+ void * _internal_get_local_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
+ {
+ return pn.get_local_deleter( ti );
+ }
+
+ void * _internal_get_untyped_deleter() const BOOST_SP_NOEXCEPT
+ {
+ return pn.get_untyped_deleter();
+ }
+
+ bool _internal_equiv( shared_ptr const & r ) const BOOST_SP_NOEXCEPT
+ {
+ return px == r.px && pn == r.pn;
+ }
+
+ boost::detail::shared_count _internal_count() const BOOST_NOEXCEPT
+ {
+ return pn;
+ }
+
+// Tasteless as this may seem, making all members public allows member templates
+// to work in the absence of member template friends. (Matthew Langston)
+
+#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+
+private:
+
+ template<class Y> friend class shared_ptr;
+ template<class Y> friend class weak_ptr;
+
+
+#endif
+
+ element_type * px; // contained pointer
+ boost::detail::shared_count pn; // reference counter
+
+}; // shared_ptr
+
+template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT
+{
+ return a.get() == b.get();
+}
+
+template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT
+{
+ return a.get() != b.get();
+}
+
+#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
+
+// Resolve the ambiguity between our op!= and the one in rel_ops
+
+template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) BOOST_SP_NOEXCEPT
+{
+ return a.get() != b.get();
+}
+
+#endif
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+template<class T> inline bool operator==( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator!=( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+#endif
+
+template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT
+{
+ return a.owner_before( b );
+}
+
+template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_SP_NOEXCEPT
+{
+ a.swap(b);
+}
+
+template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
+{
+ (void) static_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = static_cast< E* >( r.get() );
+ return shared_ptr<T>( r, p );
+}
+
+template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
+{
+ (void) const_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = const_cast< E* >( r.get() );
+ return shared_ptr<T>( r, p );
+}
+
+template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
+{
+ (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = dynamic_cast< E* >( r.get() );
+ return p? shared_ptr<T>( r, p ): shared_ptr<T>();
+}
+
+template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
+{
+ (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = reinterpret_cast< E* >( r.get() );
+ return shared_ptr<T>( r, p );
+}
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) static_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = static_cast< E* >( r.get() );
+ return shared_ptr<T>( std::move(r), p );
+}
+
+template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) const_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = const_cast< E* >( r.get() );
+ return shared_ptr<T>( std::move(r), p );
+}
+
+template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = dynamic_cast< E* >( r.get() );
+ return p? shared_ptr<T>( std::move(r), p ): shared_ptr<T>();
+}
+
+template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
+{
+ (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = reinterpret_cast< E* >( r.get() );
+ return shared_ptr<T>( std::move(r), p );
+}
+
+#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+// get_pointer() enables boost::mem_fn to recognize shared_ptr
+
+template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_SP_NOEXCEPT
+{
+ return p.get();
+}
+
+// operator<<
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
+
+template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
+{
+ os << p.get();
+ return os;
+}
+
+#else
+
+// in STLport's no-iostreams mode no iostream symbols can be used
+#ifndef _STLP_NO_IOSTREAMS
+
+# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
+// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
+using std::basic_ostream;
+template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
+# else
+template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
+# endif
+{
+ os << p.get();
+ return os;
+}
+
+#endif // _STLP_NO_IOSTREAMS
+
+#endif // __GNUC__ < 3
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+// get_deleter
+
+namespace detail
+{
+
+template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID(D)) );
+}
+
+template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT;
+template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT;
+
+class esft2_deleter_wrapper
+{
+private:
+
+ shared_ptr<void const volatile> deleter_;
+
+public:
+
+ esft2_deleter_wrapper()
+ {
+ }
+
+ template< class T > void set_deleter( shared_ptr<T> const & deleter ) BOOST_SP_NOEXCEPT
+ {
+ deleter_ = deleter;
+ }
+
+ template<typename D> D* get_deleter() const BOOST_SP_NOEXCEPT
+ {
+ return boost::detail::basic_get_deleter<D>( deleter_ );
+ }
+
+ template< class T> void operator()( T* ) BOOST_SP_NOEXCEPT_WITH_ASSERT
+ {
+ BOOST_ASSERT( deleter_.use_count() <= 1 );
+ deleter_.reset();
+ }
+};
+
+} // namespace detail
+
+template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ D * d = boost::detail::basic_get_deleter<D>( p );
+
+ if( d == 0 )
+ {
+ d = boost::detail::basic_get_local_deleter( d, p );
+ }
+
+ if( d == 0 )
+ {
+ boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p);
+// The following get_deleter method call is fully qualified because
+// older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>()
+ if(del_wrapper) d = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>();
+ }
+
+ return d;
+}
+
+// atomic access
+
+#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
+
+template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_SP_NOEXCEPT
+{
+ return false;
+}
+
+template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) BOOST_SP_NOEXCEPT
+{
+ boost::detail::spinlock_pool<2>::scoped_lock lock( p );
+ return *p;
+}
+
+template<class T, class M> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ M ) BOOST_SP_NOEXCEPT
+{
+ return atomic_load( p );
+}
+
+template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPT
+{
+ boost::detail::spinlock_pool<2>::scoped_lock lock( p );
+ p->swap( r );
+}
+
+template<class T, class M> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ M ) BOOST_SP_NOEXCEPT
+{
+ atomic_store( p, r ); // std::move( r )
+}
+
+template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPT
+{
+ boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
+
+ sp.lock();
+ p->swap( r );
+ sp.unlock();
+
+ return r; // return std::move( r )
+}
+
+template<class T, class M> shared_ptr<T> inline atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ M ) BOOST_SP_NOEXCEPT
+{
+ return atomic_exchange( p, r ); // std::move( r )
+}
+
+template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) BOOST_SP_NOEXCEPT
+{
+ boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
+
+ sp.lock();
+
+ if( p->_internal_equiv( *v ) )
+ {
+ p->swap( w );
+
+ sp.unlock();
+
+ return true;
+ }
+ else
+ {
+ shared_ptr<T> tmp( *p );
+
+ sp.unlock();
+
+ tmp.swap( *v );
+ return false;
+ }
+}
+
+template<class T, class M> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, /*memory_order success*/ M, /*memory_order failure*/ M ) BOOST_SP_NOEXCEPT
+{
+ return atomic_compare_exchange( p, v, w ); // std::move( w )
+}
+
+#endif // !defined(BOOST_SP_NO_ATOMIC_ACCESS)
+
+// hash_value
+
+template< class T > struct hash;
+
+template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return boost::hash< typename boost::shared_ptr<T>::element_type* >()( p.get() );
+}
+
+} // namespace boost
+
+#include <boost/smart_ptr/detail/local_sp_deleter.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID(local_sp_deleter<D>) ) );
+}
+
+template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
+{
+ return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID(local_sp_deleter<D>) ) );
+}
+
+} // namespace detail
+
+} // namespace boost
+
+#if defined( BOOST_SP_DISABLE_DEPRECATED )
+#pragma GCC diagnostic pop
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
diff --git a/include/boost/smart_ptr/weak_ptr.hpp b/include/boost/smart_ptr/weak_ptr.hpp
new file mode 100644
index 0000000..54d9ef3
--- /dev/null
+++ b/include/boost/smart_ptr/weak_ptr.hpp
@@ -0,0 +1,254 @@
+#ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
+#define BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
+
+//
+// weak_ptr.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+#include <memory> // boost.TR1 include order fix
+#include <boost/smart_ptr/detail/shared_count.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/detail/sp_noexcept.hpp>
+
+namespace boost
+{
+
+template<class T> class weak_ptr
+{
+private:
+
+ // Borland 5.5.1 specific workarounds
+ typedef weak_ptr<T> this_type;
+
+public:
+
+ typedef typename boost::detail::sp_element< T >::type element_type;
+
+ BOOST_CONSTEXPR weak_ptr() BOOST_SP_NOEXCEPT : px(0), pn()
+ {
+ }
+
+// generated copy constructor, assignment, destructor are fine...
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+// ... except in C++0x, move disables the implicit copy
+
+ weak_ptr( weak_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
+ {
+ }
+
+ weak_ptr & operator=( weak_ptr const & r ) BOOST_SP_NOEXCEPT
+ {
+ px = r.px;
+ pn = r.pn;
+ return *this;
+ }
+
+#endif
+
+//
+// The "obvious" converting constructor implementation:
+//
+// template<class Y>
+// weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn)
+// {
+// }
+//
+// has a serious problem.
+//
+// r.px may already have been invalidated. The px(r.px)
+// conversion may require access to *r.px (virtual inheritance).
+//
+// It is not possible to avoid spurious access violations since
+// in multithreaded programs r.px may be invalidated at any point.
+//
+
+ template<class Y>
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ weak_ptr( weak_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
+
+#else
+
+ weak_ptr( weak_ptr<Y> const & r )
+
+#endif
+ BOOST_SP_NOEXCEPT : px(r.lock().get()), pn(r.pn)
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y>
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ weak_ptr( weak_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
+
+#else
+
+ weak_ptr( weak_ptr<Y> && r )
+
+#endif
+ BOOST_SP_NOEXCEPT : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+ r.px = 0;
+ }
+
+ // for better efficiency in the T == Y case
+ weak_ptr( weak_ptr && r )
+ BOOST_SP_NOEXCEPT : px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) )
+ {
+ r.px = 0;
+ }
+
+ // for better efficiency in the T == Y case
+ weak_ptr & operator=( weak_ptr && r ) BOOST_SP_NOEXCEPT
+ {
+ this_type( static_cast< weak_ptr && >( r ) ).swap( *this );
+ return *this;
+ }
+
+
+#endif
+
+ template<class Y>
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ weak_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
+
+#else
+
+ weak_ptr( shared_ptr<Y> const & r )
+
+#endif
+ BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+ }
+
+#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
+
+ template<class Y>
+ weak_ptr & operator=( weak_ptr<Y> const & r ) BOOST_SP_NOEXCEPT
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ px = r.lock().get();
+ pn = r.pn;
+
+ return *this;
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y>
+ weak_ptr & operator=( weak_ptr<Y> && r ) BOOST_SP_NOEXCEPT
+ {
+ this_type( static_cast< weak_ptr<Y> && >( r ) ).swap( *this );
+ return *this;
+ }
+
+#endif
+
+ template<class Y>
+ weak_ptr & operator=( shared_ptr<Y> const & r ) BOOST_SP_NOEXCEPT
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ px = r.px;
+ pn = r.pn;
+
+ return *this;
+ }
+
+#endif
+
+ shared_ptr<T> lock() const BOOST_SP_NOEXCEPT
+ {
+ return shared_ptr<T>( *this, boost::detail::sp_nothrow_tag() );
+ }
+
+ long use_count() const BOOST_SP_NOEXCEPT
+ {
+ return pn.use_count();
+ }
+
+ bool expired() const BOOST_SP_NOEXCEPT
+ {
+ return pn.use_count() == 0;
+ }
+
+ bool _empty() const BOOST_SP_NOEXCEPT // extension, not in std::weak_ptr
+ {
+ return pn.empty();
+ }
+
+ void reset() BOOST_SP_NOEXCEPT
+ {
+ this_type().swap(*this);
+ }
+
+ void swap(this_type & other) BOOST_SP_NOEXCEPT
+ {
+ std::swap(px, other.px);
+ pn.swap(other.pn);
+ }
+
+ template<typename Y>
+ void _internal_aliasing_assign(weak_ptr<Y> const & r, element_type * px2) BOOST_SP_NOEXCEPT
+ {
+ px = px2;
+ pn = r.pn;
+ }
+
+ template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
+ {
+ return pn < rhs.pn;
+ }
+
+ template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
+ {
+ return pn < rhs.pn;
+ }
+
+// Tasteless as this may seem, making all members public allows member templates
+// to work in the absence of member template friends. (Matthew Langston)
+
+#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+
+private:
+
+ template<class Y> friend class weak_ptr;
+ template<class Y> friend class shared_ptr;
+
+#endif
+
+ element_type * px; // contained pointer
+ boost::detail::weak_count pn; // reference counter
+
+}; // weak_ptr
+
+template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) BOOST_SP_NOEXCEPT
+{
+ return a.owner_before( b );
+}
+
+template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) BOOST_SP_NOEXCEPT
+{
+ a.swap(b);
+}
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp
new file mode 100644
index 0000000..fa8574b
--- /dev/null
+++ b/include/boost/weak_ptr.hpp
@@ -0,0 +1,18 @@
+#ifndef BOOST_WEAK_PTR_HPP_INCLUDED
+#define BOOST_WEAK_PTR_HPP_INCLUDED
+
+//
+// weak_ptr.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// See http://www.boost.org/libs/smart_ptr/ for documentation.
+//
+
+#include <boost/smart_ptr/weak_ptr.hpp>
+
+#endif // #ifndef BOOST_WEAK_PTR_HPP_INCLUDED
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..7afe664
--- /dev/null
+++ b/index.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="refresh" content="0; URL=doc/html/smart_ptr.html">
+</head>
+<body>
+<p>
+Automatic redirection failed, please go to
+<a href="doc/html/smart_ptr.html">doc/html/smart_ptr.html</a>.
+</p>
+</body>
+</html>
+<!--
+ (C) Copyright Beman Dawes, 2001
+ Distributed under the Boost Software License, Version 1.0.
+ See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+-->
diff --git a/meta/libraries.json b/meta/libraries.json
new file mode 100644
index 0000000..8a027f7
--- /dev/null
+++ b/meta/libraries.json
@@ -0,0 +1,21 @@
+{
+ "key": "smart_ptr",
+ "name": "Smart Ptr",
+ "authors": [
+ "Greg Colvin",
+ "Beman Dawes",
+ "Peter Dimov",
+ "Darin Adler",
+ "Glen Fernandes"
+ ],
+ "description": "Smart pointer class templates.",
+ "std": [
+ "tr1"
+ ],
+ "category": [
+ "Memory"
+ ],
+ "maintainers": [
+ "Peter Dimov <pdimov -at- pdimov.com>"
+ ]
+}
diff --git a/test/Jamfile b/test/Jamfile
new file mode 100644
index 0000000..6cff91a
--- /dev/null
+++ b/test/Jamfile
@@ -0,0 +1,278 @@
+# Boost.SmartPtr Library test Jamfile
+#
+# Copyright (c) 2003-2018 Peter Dimov
+# Copyright (c) 2003 Dave Abrahams
+#
+# 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)
+
+# bring in rules for testing
+import testing ;
+
+# quick test (for CI)
+run quick.cpp ;
+
+# full test suite
+run smart_ptr_test.cpp ;
+run shared_ptr_basic_test.cpp : : : <toolset>gcc:<cxxflags>-Wno-non-virtual-dtor ;
+run shared_ptr_test.cpp : : : <toolset>gcc:<cxxflags>-Wno-non-virtual-dtor ;
+run weak_ptr_test.cpp ;
+run weak_ptr_move_test.cpp ;
+run shared_from_this_test.cpp : : : <toolset>gcc:<cxxflags>-Wno-non-virtual-dtor ;
+run get_deleter_test.cpp ;
+run intrusive_ptr_test.cpp ;
+run intrusive_ptr_move_test.cpp ;
+run intrusive_ref_counter_test.cpp ;
+run atomic_count_test.cpp ;
+run lw_mutex_test.cpp ;
+run lw_mutex_test.cpp : : : <define>BOOST_USE_WINDOWS_H : lw_mutex_test.win_h ;
+compile-fail shared_ptr_assign_fail.cpp ;
+compile-fail shared_ptr_delete_fail.cpp ;
+compile-fail shared_ptr_compare_fail.cpp ;
+run shared_ptr_alloc2_test.cpp ;
+run pointer_cast_test.cpp ;
+run cpp11_pointer_cast_test.cpp ;
+compile pointer_to_other_test.cpp ;
+run auto_ptr_rv_test.cpp ;
+run shared_ptr_alias_test.cpp ;
+run shared_ptr_rv_test.cpp ;
+run shared_ptr_rv_pointer_cast_test.cpp ;
+run shared_ptr_move_test.cpp ;
+run shared_ptr_alias_move_test.cpp ;
+run shared_ptr_reinterpret_pointer_cast_test.cpp ;
+compile-fail shared_ptr_pv_fail.cpp ;
+run sp_unary_addr_test.cpp ;
+compile-fail scoped_ptr_eq_fail.cpp ;
+compile-fail scoped_array_eq_fail.cpp ;
+run esft_regtest.cpp ;
+run yield_k_test.cpp ;
+run yield_k_test.cpp : : : <threading>multi : yield_k_test.mt ;
+run spinlock_test.cpp ;
+run spinlock_try_test.cpp ;
+run spinlock_try_test.cpp : : : <threading>multi : spinlock_try_test.mt ;
+run spinlock_pool_test.cpp : : :
+ # msvc-8.0, 9.0 optimizer codegen bug for `x % 41`
+ <toolset>msvc-8.0,<variant>release:<build>no
+ <toolset>msvc-9.0,<variant>release:<build>no ;
+
+run make_shared_test.cpp ;
+run make_shared_move_emulation_test.cpp ;
+run make_shared_perfect_forwarding_test.cpp ;
+run shared_ptr_convertible_test.cpp ;
+run wp_convertible_test.cpp ;
+run ip_convertible_test.cpp ;
+run allocate_shared_test.cpp ;
+run sp_atomic_test.cpp ;
+run esft_void_test.cpp ;
+run esft_second_ptr_test.cpp ;
+run make_shared_esft_test.cpp ;
+run allocate_shared_esft_test.cpp ;
+run sp_recursive_assign_test.cpp ;
+run sp_recursive_assign2_test.cpp ;
+run sp_recursive_assign_rv_test.cpp ;
+run sp_recursive_assign2_rv_test.cpp ;
+compile-fail auto_ptr_lv_fail.cpp : <toolset>gcc-4.4.7:<build>no ;
+run atomic_count_test2.cpp ;
+run sp_typeinfo_test.cpp ;
+compile make_shared_fp_test.cpp ;
+run sp_hash_test.cpp ;
+run get_deleter_array_test.cpp ;
+run ip_hash_test.cpp ;
+run owner_less_test.cpp ;
+run sp_unique_ptr_test.cpp ;
+run sp_array_test.cpp ;
+compile sp_array_cv_test.cpp ;
+run sp_convertible_test.cpp ;
+run sp_array_n_test.cpp ;
+run sp_array_cast_test.cpp ;
+run sp_zero_compare_test.cpp ;
+run sp_nullptr_test.cpp ;
+run sa_nullptr_test.cpp ;
+run shared_ptr_alloc3_test.cpp ;
+run shared_ptr_alloc11_test.cpp ;
+run shared_ptr_alloc_construct11_test.cpp ;
+run allocate_shared_alloc11_test.cpp ;
+run allocate_shared_construct11_test.cpp ;
+run sp_interlocked_test.cpp ;
+
+compile-fail array_fail_spa_sp_c.cpp ;
+compile-fail array_fail_sp_spa_c.cpp ;
+compile-fail array_fail_spa_spa_c.cpp ;
+compile-fail array_fail_spa_wp_c.cpp ;
+compile-fail array_fail_sp_wpa_c.cpp ;
+compile-fail array_fail_spa_wpa_c.cpp ;
+compile-fail array_fail_wpa_wp_c.cpp ;
+compile-fail array_fail_wp_wpa_c.cpp ;
+compile-fail array_fail_wpa_wpa_c.cpp ;
+compile-fail array_fail_ap_spa_c.cpp ;
+compile-fail array_fail_upa_sp_c.cpp ;
+compile-fail array_fail_up_spa_c.cpp ;
+
+compile-fail array_fail_spa_sp_mc.cpp ;
+compile-fail array_fail_sp_spa_mc.cpp ;
+compile-fail array_fail_spa_spa_mc.cpp ;
+compile-fail array_fail_spa_wp_mc.cpp ;
+compile-fail array_fail_sp_wpa_mc.cpp ;
+compile-fail array_fail_spa_wpa_mc.cpp ;
+compile-fail array_fail_wpa_wp_mc.cpp ;
+compile-fail array_fail_wp_wpa_mc.cpp ;
+compile-fail array_fail_wpa_wpa_mc.cpp ;
+compile-fail array_fail_ap_spa_mc.cpp ;
+compile-fail array_fail_upa_sp_mc.cpp ;
+compile-fail array_fail_up_spa_mc.cpp ;
+
+compile-fail array_fail_spa_sp_a.cpp ;
+compile-fail array_fail_sp_spa_a.cpp ;
+compile-fail array_fail_spa_spa_a.cpp ;
+compile-fail array_fail_spa_wp_a.cpp ;
+compile-fail array_fail_sp_wpa_a.cpp ;
+compile-fail array_fail_spa_wpa_a.cpp ;
+compile-fail array_fail_wpa_wp_a.cpp ;
+compile-fail array_fail_wp_wpa_a.cpp ;
+compile-fail array_fail_wpa_wpa_a.cpp ;
+compile-fail array_fail_ap_spa_a.cpp ;
+compile-fail array_fail_upa_sp_a.cpp ;
+compile-fail array_fail_up_spa_a.cpp ;
+
+compile-fail array_fail_spa_sp_ma.cpp ;
+compile-fail array_fail_sp_spa_ma.cpp ;
+compile-fail array_fail_spa_spa_ma.cpp ;
+compile-fail array_fail_spa_wp_ma.cpp ;
+compile-fail array_fail_sp_wpa_ma.cpp ;
+compile-fail array_fail_spa_wpa_ma.cpp ;
+compile-fail array_fail_wpa_wp_ma.cpp ;
+compile-fail array_fail_wp_wpa_ma.cpp ;
+compile-fail array_fail_wpa_wpa_ma.cpp ;
+compile-fail array_fail_ap_spa_ma.cpp ;
+compile-fail array_fail_upa_sp_ma.cpp ;
+compile-fail array_fail_up_spa_ma.cpp ;
+
+compile-fail array_fail_dereference.cpp ;
+compile-fail array_fail_member_access.cpp ;
+compile-fail array_fail_array_access.cpp ;
+
+run make_shared_array_test.cpp ;
+run make_shared_arrays_test.cpp ; # <cxxflags>-fno-deduce-init-list no longer needed for gcc-4.6
+run make_shared_array_throws_test.cpp ;
+run make_shared_array_esft_test.cpp ;
+run make_shared_array_noinit_test.cpp ;
+run make_shared_array_value_test.cpp ;
+run allocate_shared_array_test.cpp ;
+run allocate_shared_arrays_test.cpp ; # <cxxflags>-fno-deduce-init-list no longer needed for gcc-4.6
+run allocate_shared_array_throws_test.cpp ;
+run allocate_shared_array_esft_test.cpp ;
+run allocate_shared_array_noinit_test.cpp ;
+run allocate_shared_array_value_test.cpp ;
+run allocate_shared_array_construct_test.cpp ;
+
+run make_unique_test.cpp ;
+run make_unique_args_test.cpp ;
+run make_unique_value_test.cpp : : : <toolset>gcc-4.6:<cxxflags>-fno-deduce-init-list ;
+run make_unique_noinit_test.cpp ;
+run make_unique_throws_test.cpp ;
+run make_unique_array_test.cpp ;
+run make_unique_array_noinit_test.cpp ;
+run make_unique_array_throws_test.cpp ;
+
+run shared_from_raw_test.cpp ;
+run shared_from_raw_test2.cpp ;
+run shared_from_raw_test3.cpp ;
+run shared_from_raw_test4.cpp ;
+run shared_from_raw_test5.cpp ;
+run shared_from_raw_test6.cpp ;
+
+run weak_from_raw_test.cpp ;
+run weak_from_raw_test2.cpp ;
+run weak_from_raw_test3.cpp ;
+run weak_from_raw_test4.cpp ;
+run weak_from_raw_test5.cpp ;
+
+compile sp_explicit_inst_test.cpp ;
+
+run weak_from_this_test.cpp ;
+run weak_from_this_test2.cpp ;
+
+run sp_bml_unique_ptr_test.cpp ;
+
+run sp_hash_test2.cpp ;
+run sp_hash_test3.cpp ;
+
+run pointer_cast_test2.cpp ;
+
+compile-fail pointer_cast_st_fail.cpp ;
+compile-fail pointer_cast_st_fail2.cpp ;
+compile-fail pointer_cast_st_fail3.cpp ;
+
+compile-fail pointer_cast_co_fail.cpp ;
+compile-fail pointer_cast_co_fail2.cpp ;
+compile-fail pointer_cast_co_fail3.cpp ;
+
+compile-fail pointer_cast_dy_fail.cpp ;
+compile-fail pointer_cast_dy_fail2.cpp ;
+compile-fail pointer_cast_dy_fail3.cpp ;
+
+run sp_nothrow_test.cpp ;
+
+compile make_shared_msvc_test.cpp ;
+
+compile lwm_win32_cs_test.cpp ;
+
+run atomic_sp_test.cpp ;
+
+run sp_constexpr_test.cpp ;
+run sp_constexpr_test2.cpp ;
+
+run atomic_sp_constexpr_test.cpp ;
+
+run shared_ptr_fn_test.cpp ;
+
+run get_deleter_test2.cpp ;
+run get_deleter_test3.cpp ;
+run get_deleter_array_test2.cpp ;
+run get_deleter_array_test3.cpp ;
+
+run sp_convertible_test2.cpp ;
+
+run local_sp_test.cpp ;
+run lsp_array_test.cpp ;
+run lsp_array_n_test.cpp ;
+run lsp_array_cv_test.cpp ;
+run lsp_array_cast_test.cpp ;
+
+run get_local_deleter_test.cpp ;
+run get_local_deleter_test2.cpp ;
+run get_local_deleter_test3.cpp ;
+run get_local_deleter_array_test.cpp ;
+run get_local_deleter_array_test2.cpp ;
+
+run make_local_shared_test.cpp ;
+run make_local_shared_esft_test.cpp ;
+run allocate_local_shared_test.cpp ;
+run allocate_local_shared_esft_test.cpp ;
+
+run make_local_shared_array_test.cpp ;
+run make_local_shared_arrays_test.cpp : : : <toolset>gcc-4.6.3_0x:<cxxflags>-fno-deduce-init-list ;
+run make_local_shared_array_throws_test.cpp ;
+run make_local_shared_array_esft_test.cpp ;
+run make_local_shared_array_noinit_test.cpp ;
+run make_local_shared_array_value_test.cpp ;
+run allocate_local_shared_array_test.cpp ;
+run allocate_local_shared_arrays_test.cpp : : : <toolset>gcc-4.6.3_0x:<cxxflags>-fno-deduce-init-list ;
+run allocate_local_shared_array_throws_test.cpp ;
+run allocate_local_shared_array_esft_test.cpp ;
+run allocate_local_shared_array_noinit_test.cpp ;
+run allocate_local_shared_array_value_test.cpp ;
+run allocate_local_shared_array_construct_test.cpp ;
+
+run local_sp_fn_test.cpp ;
+run lsp_convertible_test.cpp ;
+run lsp_convertible_test2.cpp ;
+
+run make_shared_array_tmp_test.cpp ;
+
+run lw_thread_test.cpp : : : <threading>multi ;
+
+compile sp_windows_h_test.cpp ;
+compile spinlock_windows_h_test.cpp ;
+compile yield_k_windows_h_test.cpp ;
diff --git a/test/allocate_local_shared_array_construct_test.cpp b/test/allocate_local_shared_array_construct_test.cpp
new file mode 100644
index 0000000..0f8bc1b
--- /dev/null
+++ b/test/allocate_local_shared_array_construct_test.cpp
@@ -0,0 +1,165 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+ !defined(BOOST_NO_CXX11_ALLOCATOR)
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+
+struct allow { };
+
+template<class T = void>
+struct creator {
+ typedef T value_type;
+
+ template<class U>
+ struct rebind {
+ typedef creator<U> other;
+ };
+
+ creator() { }
+
+ template<class U>
+ creator(const creator<U>&) { }
+
+ T* allocate(std::size_t size) {
+ return static_cast<T*>(::operator new(sizeof(T) * size));
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ }
+
+ template<class U>
+ void construct(U* ptr) {
+ ::new(static_cast<void*>(ptr)) U(allow());
+ }
+
+ template<class U>
+ void destroy(U* ptr) {
+ ptr->~U();
+ }
+
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>&, const creator<U>&)
+{
+ return true;
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>&, const creator<U>&)
+{
+ return false;
+}
+
+class type {
+public:
+ static unsigned instances;
+
+ explicit type(allow) {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ {
+ boost::local_shared_ptr<type[]> result =
+ boost::allocate_local_shared<type[]>(creator<type>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[3]> result =
+ boost::allocate_local_shared<type[3]>(creator<type>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[][2]> result =
+ boost::allocate_local_shared<type[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[2][2]> result =
+ boost::allocate_local_shared<type[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[]> result =
+ boost::allocate_local_shared<const type[]>(creator<>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[3]> result =
+ boost::allocate_local_shared<const type[3]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[][2]> result =
+ boost::allocate_local_shared<const type[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[2][2]> result =
+ boost::allocate_local_shared<const type[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/allocate_local_shared_array_esft_test.cpp b/test/allocate_local_shared_array_esft_test.cpp
new file mode 100644
index 0000000..7138745
--- /dev/null
+++ b/test/allocate_local_shared_array_esft_test.cpp
@@ -0,0 +1,103 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/enable_shared_from_this.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+
+template<class T = void>
+struct creator {
+ typedef T value_type;
+
+ template<class U>
+ struct rebind {
+ typedef creator<U> other;
+ };
+
+ creator() { }
+
+ template<class U>
+ creator(const creator<U>&) { }
+
+ T* allocate(std::size_t size) {
+ return static_cast<T*>(::operator new(sizeof(T) * size));
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ }
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>&, const creator<U>&)
+{
+ return true;
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>&, const creator<U>&)
+{
+ return false;
+}
+
+class type
+ : public boost::enable_shared_from_this<type> {
+public:
+ static unsigned instances;
+
+ type() {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ BOOST_TEST(type::instances == 0);
+ {
+ boost::local_shared_ptr<type[]> result =
+ boost::allocate_local_shared<type[]>(creator<type>(), 3);
+ try {
+ result[0].shared_from_this();
+ BOOST_ERROR("shared_from_this did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 3);
+ }
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ boost::local_shared_ptr<type[]> result =
+ boost::allocate_local_shared_noinit<type[]>(creator<>(), 3);
+ try {
+ result[0].shared_from_this();
+ BOOST_ERROR("shared_from_this did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 3);
+ }
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/allocate_local_shared_array_noinit_test.cpp b/test/allocate_local_shared_array_noinit_test.cpp
new file mode 100644
index 0000000..e2e1619
--- /dev/null
+++ b/test/allocate_local_shared_array_noinit_test.cpp
@@ -0,0 +1,254 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/align/is_aligned.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+#include <boost/smart_ptr/weak_ptr.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+
+template<class T = void>
+struct creator {
+ typedef T value_type;
+
+ template<class U>
+ struct rebind {
+ typedef creator<U> other;
+ };
+
+ creator() { }
+
+ template<class U>
+ creator(const creator<U>&) { }
+
+ T* allocate(std::size_t size) {
+ return static_cast<T*>(::operator new(sizeof(T) * size));
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ }
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>&, const creator<U>&)
+{
+ return true;
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>&, const creator<U>&)
+{
+ return false;
+}
+
+class type {
+public:
+ static unsigned instances;
+
+ type()
+ : value_(0.0) {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+ void set(long double value) {
+ value_ = value;
+ }
+
+ long double get() const {
+ return value_;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+
+ long double value_;
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ {
+ boost::local_shared_ptr<int[]> result =
+ boost::allocate_local_shared_noinit<int[]>(creator<int>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<int[3]> result =
+ boost::allocate_local_shared_noinit<int[3]>(creator<int>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<int[][2]> result =
+ boost::allocate_local_shared_noinit<int[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<int[2][2]> result =
+ boost::allocate_local_shared_noinit<int[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<const int[]> result =
+ boost::allocate_local_shared_noinit<const int[]>(creator<>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<const int[3]> result =
+ boost::allocate_local_shared_noinit<const int[3]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<const int[][2]> result =
+ boost::allocate_local_shared_noinit<const int[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<const int[2][2]> result =
+ boost::allocate_local_shared_noinit<const int[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<type[]> result =
+ boost::allocate_local_shared_noinit<type[]>(creator<type>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[3]> result =
+ boost::allocate_local_shared_noinit<type[3]>(creator<type>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[3]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[][2]> result =
+ boost::allocate_local_shared_noinit<type[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<type[][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[2][2]> result =
+ boost::allocate_local_shared_noinit<type[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<type[2][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[]> result =
+ boost::allocate_local_shared_noinit<const type[]>(creator<>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<const type[]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[3]> result =
+ boost::allocate_local_shared_noinit<const type[3]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<const type[3]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[][2]> result =
+ boost::allocate_local_shared_noinit<const
+ type[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<const type[][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[2][2]> result =
+ boost::allocate_local_shared_noinit<const type[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<const type[2][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/allocate_local_shared_array_test.cpp b/test/allocate_local_shared_array_test.cpp
new file mode 100644
index 0000000..34f3d42
--- /dev/null
+++ b/test/allocate_local_shared_array_test.cpp
@@ -0,0 +1,275 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/align/is_aligned.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+#include <boost/smart_ptr/weak_ptr.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+
+template<class T = void>
+struct creator {
+ typedef T value_type;
+
+ template<class U>
+ struct rebind {
+ typedef creator<U> other;
+ };
+
+ creator() { }
+
+ template<class U>
+ creator(const creator<U>&) { }
+
+ T* allocate(std::size_t size) {
+ return static_cast<T*>(::operator new(sizeof(T) * size));
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ }
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>&, const creator<U>&)
+{
+ return true;
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>&, const creator<U>&)
+{
+ return false;
+}
+
+class type {
+public:
+ static unsigned instances;
+
+ type()
+ : value_(0.0) {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+ void set(long double value) {
+ value_ = value;
+ }
+
+ long double get() const {
+ return value_;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+
+ long double value_;
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ {
+ boost::local_shared_ptr<int[]> result =
+ boost::allocate_local_shared<int[]>(creator<int>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::local_shared_ptr<int[3]> result =
+ boost::allocate_local_shared<int[3]>(creator<int>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::local_shared_ptr<int[][2]> result =
+ boost::allocate_local_shared<int[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::local_shared_ptr<int[2][2]> result =
+ boost::allocate_local_shared<int[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::local_shared_ptr<const int[]> result =
+ boost::allocate_local_shared<const int[]>(creator<>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::local_shared_ptr<const int[3]> result =
+ boost::allocate_local_shared<const int[3]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::local_shared_ptr<const int[][2]> result =
+ boost::allocate_local_shared<const int[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::local_shared_ptr<const int[2][2]> result =
+ boost::allocate_local_shared<const int[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::local_shared_ptr<type[]> result =
+ boost::allocate_local_shared<type[]>(creator<type>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[]> w1 = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[3]> result =
+ boost::allocate_local_shared<type[3]>(creator<type>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[3]> w1 = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[][2]> result =
+ boost::allocate_local_shared<type[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[2][2]> result =
+ boost::allocate_local_shared<type[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[]> result =
+ boost::allocate_local_shared<const type[]>(creator<>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[3]> result =
+ boost::allocate_local_shared<const type[3]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[][2]> result =
+ boost::allocate_local_shared<const type[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[2][2]> result =
+ boost::allocate_local_shared<const type[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/allocate_local_shared_array_throws_test.cpp b/test/allocate_local_shared_array_throws_test.cpp
new file mode 100644
index 0000000..78ae6b6
--- /dev/null
+++ b/test/allocate_local_shared_array_throws_test.cpp
@@ -0,0 +1,130 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+
+template<class T = void>
+struct creator {
+ typedef T value_type;
+
+ template<class U>
+ struct rebind {
+ typedef creator<U> other;
+ };
+
+ creator() { }
+
+ template<class U>
+ creator(const creator<U>&) { }
+
+ T* allocate(std::size_t size) {
+ return static_cast<T*>(::operator new(sizeof(T) * size));
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ }
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>&, const creator<U>&)
+{
+ return true;
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>&, const creator<U>&)
+{
+ return false;
+}
+
+class type {
+public:
+ static unsigned instances;
+
+ type() {
+ if (instances == 5) {
+ throw true;
+ }
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ try {
+ boost::allocate_local_shared<type[]>(creator<type>(), 6);
+ BOOST_ERROR("allocate_local_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::allocate_local_shared<type[][2]>(creator<type>(), 3);
+ BOOST_ERROR("allocate_local_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::allocate_local_shared<type[6]>(creator<>());
+ BOOST_ERROR("allocate_local_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::allocate_local_shared<type[3][2]>(creator<>());
+ BOOST_ERROR("allocate_local_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::allocate_local_shared_noinit<type[]>(creator<>(), 6);
+ BOOST_ERROR("allocate_local_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::allocate_local_shared_noinit<type[][2]>(creator<>(), 3);
+ BOOST_ERROR("allocate_local_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::allocate_local_shared_noinit<type[6]>(creator<>());
+ BOOST_ERROR("allocate_local_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::allocate_local_shared_noinit<type[3][2]>(creator<>());
+ BOOST_ERROR("allocate_local_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/allocate_local_shared_array_value_test.cpp b/test/allocate_local_shared_array_value_test.cpp
new file mode 100644
index 0000000..7d9c35f
--- /dev/null
+++ b/test/allocate_local_shared_array_value_test.cpp
@@ -0,0 +1,92 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+
+template<class T = void>
+struct creator {
+ typedef T value_type;
+
+ template<class U>
+ struct rebind {
+ typedef creator<U> other;
+ };
+
+ creator() { }
+
+ template<class U>
+ creator(const creator<U>&) { }
+
+ T* allocate(std::size_t size) {
+ return static_cast<T*>(::operator new(sizeof(T) * size));
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ }
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>&, const creator<U>&)
+{
+ return true;
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>&, const creator<U>&)
+{
+ return false;
+}
+
+int main()
+{
+ {
+ boost::local_shared_ptr<int[]> result =
+ boost::allocate_local_shared<int[]>(creator<int>(), 4, 1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ {
+ boost::local_shared_ptr<int[4]> result =
+ boost::allocate_local_shared<int[4]>(creator<int>(), 1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ {
+ boost::local_shared_ptr<const int[]> result =
+ boost::allocate_local_shared<const int[]>(creator<>(), 4, 1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ {
+ boost::local_shared_ptr<const int[4]> result =
+ boost::allocate_local_shared<const int[4]>(creator<>(), 1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/allocate_local_shared_arrays_test.cpp b/test/allocate_local_shared_arrays_test.cpp
new file mode 100644
index 0000000..d45a686
--- /dev/null
+++ b/test/allocate_local_shared_arrays_test.cpp
@@ -0,0 +1,93 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+ !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+
+template<class T = void>
+struct creator {
+ typedef T value_type;
+
+ template<class U>
+ struct rebind {
+ typedef creator<U> other;
+ };
+
+ creator() { }
+
+ template<class U>
+ creator(const creator<U>&) { }
+
+ T* allocate(std::size_t size) {
+ return static_cast<T*>(::operator new(sizeof(T) * size));
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ }
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>&, const creator<U>&)
+{
+ return true;
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>&, const creator<U>&)
+{
+ return false;
+}
+
+int main()
+{
+ {
+ boost::local_shared_ptr<int[][2]> result =
+ boost::allocate_local_shared<int[][2]>(creator<int>(), 2, {0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ {
+ boost::local_shared_ptr<int[2][2]> result =
+ boost::allocate_local_shared<int[2][2]>(creator<int>(), {0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ {
+ boost::local_shared_ptr<const int[][2]> result =
+ boost::allocate_local_shared<const int[][2]>(creator<>(), 2, {0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ {
+ boost::local_shared_ptr<const int[2][2]> result =
+ boost::allocate_local_shared<const int[2][2]>(creator<>(), {0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/allocate_local_shared_esft_test.cpp b/test/allocate_local_shared_esft_test.cpp
new file mode 100644
index 0000000..65349c5
--- /dev/null
+++ b/test/allocate_local_shared_esft_test.cpp
@@ -0,0 +1,298 @@
+// allocate_local_shared_esft_test.cpp
+//
+// Copyright 2007-2009, 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
+
+#include <boost/config.hpp>
+
+#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) || defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES )
+
+int main()
+{
+}
+
+#else
+
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <memory>
+
+class X: public boost::enable_shared_from_this<X>
+{
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+
+public:
+
+ static int instances;
+
+ explicit X( int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0 )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+};
+
+int X::instances = 0;
+
+int main()
+{
+ BOOST_TEST_EQ( X::instances, 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>() );
+ BOOST_TEST_EQ( X::instances, 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST_EQ( px, qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST_EQ( X::instances, 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST_EQ( X::instances, 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_local_shared_noinit< X >( std::allocator<void>() );
+ BOOST_TEST_EQ( X::instances, 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST_EQ( px, qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST_EQ( X::instances, 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST_EQ( X::instances, 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1 );
+ BOOST_TEST_EQ( X::instances, 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST_EQ( px, qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST_EQ( X::instances, 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST_EQ( X::instances, 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2 );
+ BOOST_TEST_EQ( X::instances, 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST_EQ( px, qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST_EQ( X::instances, 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST_EQ( X::instances, 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3 );
+ BOOST_TEST_EQ( X::instances, 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST_EQ( px, qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST_EQ( X::instances, 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST_EQ( X::instances, 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4 );
+ BOOST_TEST_EQ( X::instances, 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST_EQ( px, qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST_EQ( X::instances, 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST_EQ( X::instances, 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5 );
+ BOOST_TEST_EQ( X::instances, 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST_EQ( px, qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST_EQ( X::instances, 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST_EQ( X::instances, 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6 );
+ BOOST_TEST_EQ( X::instances, 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST_EQ( px, qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST_EQ( X::instances, 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST_EQ( X::instances, 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
+ BOOST_TEST_EQ( X::instances, 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST_EQ( px, qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST_EQ( X::instances, 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST_EQ( X::instances, 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
+ BOOST_TEST_EQ( X::instances, 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST_EQ( px, qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST_EQ( X::instances, 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST_EQ( X::instances, 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
+ BOOST_TEST_EQ( X::instances, 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST_EQ( px, qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST_EQ( X::instances, 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST_EQ( X::instances, 0 );
+
+ return boost::report_errors();
+}
+
+#endif
diff --git a/test/allocate_local_shared_test.cpp b/test/allocate_local_shared_test.cpp
new file mode 100644
index 0000000..fa53dc0
--- /dev/null
+++ b/test/allocate_local_shared_test.cpp
@@ -0,0 +1,235 @@
+// allocate_local_shared_test.cpp
+//
+// Copyright 2007-2009, 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
+
+#include <boost/config.hpp>
+
+#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) || defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES )
+
+int main()
+{
+}
+
+#else
+
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <cstddef>
+
+class X
+{
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+
+ void * operator new( std::size_t n )
+ {
+ // lack of this definition causes link errors on Comeau C++
+ BOOST_ERROR( "private X::new called" );
+ return ::operator new( n );
+ }
+
+ void operator delete( void * p )
+ {
+ // lack of this definition causes link errors on MSVC
+ BOOST_ERROR( "private X::delete called" );
+ ::operator delete( p );
+ }
+
+public:
+
+ static int instances;
+
+ int v;
+
+ explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+};
+
+int X::instances = 0;
+
+int main()
+{
+ {
+ boost::local_shared_ptr< int > pi = boost::allocate_local_shared< int >( std::allocator<int>() );
+
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( *pi == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< int > pi = boost::allocate_local_shared_noinit< int >( std::allocator<int>() );
+
+ BOOST_TEST( pi.get() != 0 );
+ }
+
+ {
+ boost::local_shared_ptr< int > pi = boost::allocate_local_shared< int >( std::allocator<int>(), 5 );
+
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( *pi == 5 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>() );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 0 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::allocate_local_shared_noinit< X >( std::allocator<void>() );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 0 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ return boost::report_errors();
+}
+
+#endif
diff --git a/test/allocate_shared_alloc11_test.cpp b/test/allocate_shared_alloc11_test.cpp
new file mode 100644
index 0000000..bf2a402
--- /dev/null
+++ b/test/allocate_shared_alloc11_test.cpp
@@ -0,0 +1,241 @@
+// allocate_shared_alloc11_test.cpp
+//
+// allocate_shared with a minimal C++11 allocator
+//
+// Copyright 2007-2009, 2014 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/config.hpp>
+#include <cstddef>
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+template< class T > class cxx11_allocator
+{
+public:
+
+ typedef T value_type;
+
+ cxx11_allocator()
+ {
+ }
+
+ template< class Y > cxx11_allocator( cxx11_allocator<Y> const & )
+ {
+ }
+
+ T * allocate( std::size_t n )
+ {
+ return static_cast< T* >( ::operator new( n * sizeof( T ) ) );
+ }
+
+ void deallocate( T * p, std::size_t n )
+ {
+ ::operator delete( p );
+ }
+};
+
+class X
+{
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+
+ void * operator new( std::size_t n )
+ {
+ BOOST_ERROR( "private X::new called" );
+ return ::operator new( n );
+ }
+
+ void operator delete( void * p )
+ {
+ BOOST_ERROR( "private X::delete called" );
+ ::operator delete( p );
+ }
+
+public:
+
+ static int instances;
+
+ int v;
+
+ explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+};
+
+int X::instances = 0;
+
+int main()
+{
+ {
+ boost::shared_ptr< int > pi = boost::allocate_shared< int >( cxx11_allocator<int>() );
+
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( *pi == 0 );
+ }
+
+ {
+ boost::shared_ptr< int > pi = boost::allocate_shared< int >( cxx11_allocator<int>(), 5 );
+
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( *pi == 5 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>() );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 0 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ return boost::report_errors();
+}
+
+#else // !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+int main()
+{
+ return 0;
+}
+
+#endif
diff --git a/test/allocate_shared_array_construct_test.cpp b/test/allocate_shared_array_construct_test.cpp
new file mode 100644
index 0000000..ef0dc95
--- /dev/null
+++ b/test/allocate_shared_array_construct_test.cpp
@@ -0,0 +1,163 @@
+/*
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+struct allow { };
+
+template<class T = void>
+struct creator {
+ typedef T value_type;
+
+ template<class U>
+ struct rebind {
+ typedef creator<U> other;
+ };
+
+ creator() { }
+
+ template<class U>
+ creator(const creator<U>&) { }
+
+ T* allocate(std::size_t size) {
+ return static_cast<T*>(::operator new(sizeof(T) * size));
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ }
+
+ template<class U>
+ void construct(U* ptr) {
+ ::new(static_cast<void*>(ptr)) U(allow());
+ }
+
+ template<class U>
+ void destroy(U* ptr) {
+ ptr->~U();
+ }
+
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>&, const creator<U>&)
+{
+ return true;
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>&, const creator<U>&)
+{
+ return false;
+}
+
+class type {
+public:
+ static unsigned instances;
+
+ explicit type(allow) {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ {
+ boost::shared_ptr<type[]> result =
+ boost::allocate_shared<type[]>(creator<type>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[3]> result =
+ boost::allocate_shared<type[3]>(creator<type>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[][2]> result =
+ boost::allocate_shared<type[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[2][2]> result =
+ boost::allocate_shared<type[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[]> result =
+ boost::allocate_shared<const type[]>(creator<>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[3]> result =
+ boost::allocate_shared<const type[3]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[][2]> result =
+ boost::allocate_shared<const type[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[2][2]> result =
+ boost::allocate_shared<const type[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/allocate_shared_array_esft_test.cpp b/test/allocate_shared_array_esft_test.cpp
new file mode 100644
index 0000000..1e0afaf
--- /dev/null
+++ b/test/allocate_shared_array_esft_test.cpp
@@ -0,0 +1,94 @@
+/*
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/enable_shared_from_this.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+template<class T = void>
+struct creator {
+ typedef T value_type;
+
+ template<class U>
+ struct rebind {
+ typedef creator<U> other;
+ };
+
+ creator() { }
+
+ template<class U>
+ creator(const creator<U>&) { }
+
+ T* allocate(std::size_t size) {
+ return static_cast<T*>(::operator new(sizeof(T) * size));
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ }
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>&, const creator<U>&)
+{
+ return true;
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>&, const creator<U>&)
+{
+ return false;
+}
+
+class type
+ : public boost::enable_shared_from_this<type> {
+public:
+ static unsigned instances;
+
+ type() {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ BOOST_TEST(type::instances == 0);
+ {
+ boost::shared_ptr<type[]> result =
+ boost::allocate_shared<type[]>(creator<type>(), 3);
+ try {
+ result[0].shared_from_this();
+ BOOST_ERROR("shared_from_this did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 3);
+ }
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ boost::shared_ptr<type[]> result =
+ boost::allocate_shared_noinit<type[]>(creator<>(), 3);
+ try {
+ result[0].shared_from_this();
+ BOOST_ERROR("shared_from_this did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 3);
+ }
+ }
+ return boost::report_errors();
+}
diff --git a/test/allocate_shared_array_noinit_test.cpp b/test/allocate_shared_array_noinit_test.cpp
new file mode 100644
index 0000000..910d8f7
--- /dev/null
+++ b/test/allocate_shared_array_noinit_test.cpp
@@ -0,0 +1,245 @@
+/*
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/align/is_aligned.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/smart_ptr/weak_ptr.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+
+template<class T = void>
+struct creator {
+ typedef T value_type;
+
+ template<class U>
+ struct rebind {
+ typedef creator<U> other;
+ };
+
+ creator() { }
+
+ template<class U>
+ creator(const creator<U>&) { }
+
+ T* allocate(std::size_t size) {
+ return static_cast<T*>(::operator new(sizeof(T) * size));
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ }
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>&, const creator<U>&)
+{
+ return true;
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>&, const creator<U>&)
+{
+ return false;
+}
+
+class type {
+public:
+ static unsigned instances;
+
+ type()
+ : value_(0.0) {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+ void set(long double value) {
+ value_ = value;
+ }
+
+ long double get() const {
+ return value_;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+
+ long double value_;
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ {
+ boost::shared_ptr<int[]> result =
+ boost::allocate_shared_noinit<int[]>(creator<int>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<int[3]> result =
+ boost::allocate_shared_noinit<int[3]>(creator<int>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<int[][2]> result =
+ boost::allocate_shared_noinit<int[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<int[2][2]> result =
+ boost::allocate_shared_noinit<int[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<const int[]> result =
+ boost::allocate_shared_noinit<const int[]>(creator<>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<const int[3]> result =
+ boost::allocate_shared_noinit<const int[3]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<const int[][2]> result =
+ boost::allocate_shared_noinit<const int[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<const int[2][2]> result =
+ boost::allocate_shared_noinit<const int[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<type[]> result =
+ boost::allocate_shared_noinit<type[]>(creator<type>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[3]> result =
+ boost::allocate_shared_noinit<type[3]>(creator<type>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[3]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[][2]> result =
+ boost::allocate_shared_noinit<type[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<type[][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[2][2]> result =
+ boost::allocate_shared_noinit<type[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<type[2][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[]> result =
+ boost::allocate_shared_noinit<const type[]>(creator<>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<const type[]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[3]> result =
+ boost::allocate_shared_noinit<const type[3]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<const type[3]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[][2]> result =
+ boost::allocate_shared_noinit<const
+ type[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<const type[][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[2][2]> result =
+ boost::allocate_shared_noinit<const type[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<const type[2][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
diff --git a/test/allocate_shared_array_test.cpp b/test/allocate_shared_array_test.cpp
new file mode 100644
index 0000000..d2854f9
--- /dev/null
+++ b/test/allocate_shared_array_test.cpp
@@ -0,0 +1,266 @@
+/*
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/align/is_aligned.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/smart_ptr/weak_ptr.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+
+template<class T = void>
+struct creator {
+ typedef T value_type;
+
+ template<class U>
+ struct rebind {
+ typedef creator<U> other;
+ };
+
+ creator() { }
+
+ template<class U>
+ creator(const creator<U>&) { }
+
+ T* allocate(std::size_t size) {
+ return static_cast<T*>(::operator new(sizeof(T) * size));
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ }
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>&, const creator<U>&)
+{
+ return true;
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>&, const creator<U>&)
+{
+ return false;
+}
+
+class type {
+public:
+ static unsigned instances;
+
+ type()
+ : value_(0.0) {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+ void set(long double value) {
+ value_ = value;
+ }
+
+ long double get() const {
+ return value_;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+
+ long double value_;
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ {
+ boost::shared_ptr<int[]> result =
+ boost::allocate_shared<int[]>(creator<int>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::shared_ptr<int[3]> result =
+ boost::allocate_shared<int[3]>(creator<int>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::shared_ptr<int[][2]> result =
+ boost::allocate_shared<int[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::shared_ptr<int[2][2]> result =
+ boost::allocate_shared<int[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::shared_ptr<const int[]> result =
+ boost::allocate_shared<const int[]>(creator<>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::shared_ptr<const int[3]> result =
+ boost::allocate_shared<const int[3]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::shared_ptr<const int[][2]> result =
+ boost::allocate_shared<const int[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::shared_ptr<const int[2][2]> result =
+ boost::allocate_shared<const int[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::shared_ptr<type[]> result =
+ boost::allocate_shared<type[]>(creator<type>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[]> w1 = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[3]> result =
+ boost::allocate_shared<type[3]>(creator<type>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[3]> w1 = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[][2]> result =
+ boost::allocate_shared<type[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[2][2]> result =
+ boost::allocate_shared<type[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[]> result =
+ boost::allocate_shared<const type[]>(creator<>(), 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[3]> result =
+ boost::allocate_shared<const type[3]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[][2]> result =
+ boost::allocate_shared<const type[][2]>(creator<>(), 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[2][2]> result =
+ boost::allocate_shared<const type[2][2]>(creator<>());
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
diff --git a/test/allocate_shared_array_throws_test.cpp b/test/allocate_shared_array_throws_test.cpp
new file mode 100644
index 0000000..dd674bb
--- /dev/null
+++ b/test/allocate_shared_array_throws_test.cpp
@@ -0,0 +1,121 @@
+/*
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+template<class T = void>
+struct creator {
+ typedef T value_type;
+
+ template<class U>
+ struct rebind {
+ typedef creator<U> other;
+ };
+
+ creator() { }
+
+ template<class U>
+ creator(const creator<U>&) { }
+
+ T* allocate(std::size_t size) {
+ return static_cast<T*>(::operator new(sizeof(T) * size));
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ }
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>&, const creator<U>&)
+{
+ return true;
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>&, const creator<U>&)
+{
+ return false;
+}
+
+class type {
+public:
+ static unsigned instances;
+
+ type() {
+ if (instances == 5) {
+ throw true;
+ }
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ try {
+ boost::allocate_shared<type[]>(creator<type>(), 6);
+ BOOST_ERROR("allocate_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::allocate_shared<type[][2]>(creator<type>(), 3);
+ BOOST_ERROR("allocate_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::allocate_shared<type[6]>(creator<>());
+ BOOST_ERROR("allocate_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::allocate_shared<type[3][2]>(creator<>());
+ BOOST_ERROR("allocate_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::allocate_shared_noinit<type[]>(creator<>(), 6);
+ BOOST_ERROR("allocate_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::allocate_shared_noinit<type[][2]>(creator<>(), 3);
+ BOOST_ERROR("allocate_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::allocate_shared_noinit<type[6]>(creator<>());
+ BOOST_ERROR("allocate_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::allocate_shared_noinit<type[3][2]>(creator<>());
+ BOOST_ERROR("allocate_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
diff --git a/test/allocate_shared_array_value_test.cpp b/test/allocate_shared_array_value_test.cpp
new file mode 100644
index 0000000..c0d67b9
--- /dev/null
+++ b/test/allocate_shared_array_value_test.cpp
@@ -0,0 +1,83 @@
+/*
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+template<class T = void>
+struct creator {
+ typedef T value_type;
+
+ template<class U>
+ struct rebind {
+ typedef creator<U> other;
+ };
+
+ creator() { }
+
+ template<class U>
+ creator(const creator<U>&) { }
+
+ T* allocate(std::size_t size) {
+ return static_cast<T*>(::operator new(sizeof(T) * size));
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ }
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>&, const creator<U>&)
+{
+ return true;
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>&, const creator<U>&)
+{
+ return false;
+}
+
+int main()
+{
+ {
+ boost::shared_ptr<int[]> result =
+ boost::allocate_shared<int[]>(creator<int>(), 4, 1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ {
+ boost::shared_ptr<int[4]> result =
+ boost::allocate_shared<int[4]>(creator<int>(), 1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ {
+ boost::shared_ptr<const int[]> result =
+ boost::allocate_shared<const int[]>(creator<>(), 4, 1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ {
+ boost::shared_ptr<const int[4]> result =
+ boost::allocate_shared<const int[4]>(creator<>(), 1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ return boost::report_errors();
+}
diff --git a/test/allocate_shared_arrays_test.cpp b/test/allocate_shared_arrays_test.cpp
new file mode 100644
index 0000000..a23930c
--- /dev/null
+++ b/test/allocate_shared_arrays_test.cpp
@@ -0,0 +1,91 @@
+/*
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+template<class T = void>
+struct creator {
+ typedef T value_type;
+
+ template<class U>
+ struct rebind {
+ typedef creator<U> other;
+ };
+
+ creator() { }
+
+ template<class U>
+ creator(const creator<U>&) { }
+
+ T* allocate(std::size_t size) {
+ return static_cast<T*>(::operator new(sizeof(T) * size));
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ }
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>&, const creator<U>&)
+{
+ return true;
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>&, const creator<U>&)
+{
+ return false;
+}
+
+int main()
+{
+ {
+ boost::shared_ptr<int[][2]> result =
+ boost::allocate_shared<int[][2]>(creator<int>(), 2, {0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ {
+ boost::shared_ptr<int[2][2]> result =
+ boost::allocate_shared<int[2][2]>(creator<int>(), {0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ {
+ boost::shared_ptr<const int[][2]> result =
+ boost::allocate_shared<const int[][2]>(creator<>(), 2, {0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ {
+ boost::shared_ptr<const int[2][2]> result =
+ boost::allocate_shared<const int[2][2]>(creator<>(), {0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/allocate_shared_construct11_test.cpp b/test/allocate_shared_construct11_test.cpp
new file mode 100644
index 0000000..131b4cb
--- /dev/null
+++ b/test/allocate_shared_construct11_test.cpp
@@ -0,0 +1,240 @@
+// allocate_shared_construct11_test.cpp
+//
+// Test whether allocate_shared uses construct/destroy in C++11
+//
+// Copyright 2007-2009, 2014 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <cstddef>
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+template< class T > class cxx11_allocator
+{
+public:
+
+ typedef T value_type;
+
+ cxx11_allocator()
+ {
+ }
+
+ template< class Y > cxx11_allocator( cxx11_allocator<Y> const & )
+ {
+ }
+
+ T * allocate( std::size_t n )
+ {
+ return static_cast< T* >( ::operator new( n * sizeof( T ) ) );
+ }
+
+ void deallocate( T * p, std::size_t n )
+ {
+ ::operator delete( p );
+ }
+
+ template<class... Args> void construct( T * p, Args&&... args )
+ {
+ ::new( static_cast< void* >( p ) ) T( std::forward<Args>( args )... );
+ }
+
+ void destroy( T * p )
+ {
+ p->~T();
+ }
+};
+
+class X
+{
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+
+ void * operator new( std::size_t n )
+ {
+ BOOST_ERROR( "private X::new called" );
+ return ::operator new( n );
+ }
+
+ void operator delete( void * p )
+ {
+ BOOST_ERROR( "private X::delete called" );
+ ::operator delete( p );
+ }
+
+public:
+
+ static int instances;
+
+ int v;
+
+protected:
+
+ explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+ friend class cxx11_allocator<X>;
+};
+
+int X::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>() );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 0 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ return boost::report_errors();
+}
+
+#else // !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+int main()
+{
+ return 0;
+}
+
+#endif
diff --git a/test/allocate_shared_esft_test.cpp b/test/allocate_shared_esft_test.cpp
new file mode 100644
index 0000000..7902313
--- /dev/null
+++ b/test/allocate_shared_esft_test.cpp
@@ -0,0 +1,286 @@
+// allocate_shared_esft_test.cpp
+//
+// Copyright 2007-2009 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <memory>
+
+class X: public boost::enable_shared_from_this<X>
+{
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+
+public:
+
+ static int instances;
+
+ explicit X( int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0 )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+};
+
+int X::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>() );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_shared_noinit< X >( std::allocator<void>() );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ return boost::report_errors();
+}
diff --git a/test/allocate_shared_test.cpp b/test/allocate_shared_test.cpp
new file mode 100644
index 0000000..31dcc7b
--- /dev/null
+++ b/test/allocate_shared_test.cpp
@@ -0,0 +1,223 @@
+// allocate_shared_test.cpp
+//
+// Copyright 2007-2009 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <cstddef>
+
+class X
+{
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+
+ void * operator new( std::size_t n )
+ {
+ // lack of this definition causes link errors on Comeau C++
+ BOOST_ERROR( "private X::new called" );
+ return ::operator new( n );
+ }
+
+ void operator delete( void * p )
+ {
+ // lack of this definition causes link errors on MSVC
+ BOOST_ERROR( "private X::delete called" );
+ ::operator delete( p );
+ }
+
+public:
+
+ static int instances;
+
+ int v;
+
+ explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+};
+
+int X::instances = 0;
+
+int main()
+{
+ {
+ boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator<int>() );
+
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( *pi == 0 );
+ }
+
+ {
+ boost::shared_ptr< int > pi = boost::allocate_shared_noinit< int >( std::allocator<int>() );
+
+ BOOST_TEST( pi.get() != 0 );
+ }
+
+ {
+ boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator<int>(), 5 );
+
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( *pi == 5 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>() );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 0 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared_noinit< X >( std::allocator<void>() );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 0 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/array_fail_ap_spa_a.cpp b/test/array_fail_ap_spa_a.cpp
new file mode 100644
index 0000000..0524827
--- /dev/null
+++ b/test/array_fail_ap_spa_a.cpp
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+
+struct X
+{
+};
+
+int main()
+{
+ std::auto_ptr<X> px;
+ boost::shared_ptr<X[]> px2; px2 = px;
+}
diff --git a/test/array_fail_ap_spa_c.cpp b/test/array_fail_ap_spa_c.cpp
new file mode 100644
index 0000000..bc76316
--- /dev/null
+++ b/test/array_fail_ap_spa_c.cpp
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+
+struct X
+{
+};
+
+int main()
+{
+ std::auto_ptr<X> px;
+ boost::shared_ptr<X[]> px2( px );
+}
diff --git a/test/array_fail_ap_spa_ma.cpp b/test/array_fail_ap_spa_ma.cpp
new file mode 100644
index 0000000..e26a548
--- /dev/null
+++ b/test/array_fail_ap_spa_ma.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X[]> px2; px2 = std::auto_ptr<X>();
+}
diff --git a/test/array_fail_ap_spa_mc.cpp b/test/array_fail_ap_spa_mc.cpp
new file mode 100644
index 0000000..d53eeff
--- /dev/null
+++ b/test/array_fail_ap_spa_mc.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X[]> px2(( std::auto_ptr<X>() ));
+}
diff --git a/test/array_fail_array_access.cpp b/test/array_fail_array_access.cpp
new file mode 100644
index 0000000..4f4e3f8
--- /dev/null
+++ b/test/array_fail_array_access.cpp
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+template<class T> void f( T & /*t*/ )
+{
+}
+
+int main()
+{
+ boost::shared_ptr<X> px( new X );
+ f( px[ 0 ] );
+}
diff --git a/test/array_fail_dereference.cpp b/test/array_fail_dereference.cpp
new file mode 100644
index 0000000..081d5b4
--- /dev/null
+++ b/test/array_fail_dereference.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X[]> px( new X[ 1 ] );
+ *px;
+}
diff --git a/test/array_fail_member_access.cpp b/test/array_fail_member_access.cpp
new file mode 100644
index 0000000..8051ad1
--- /dev/null
+++ b/test/array_fail_member_access.cpp
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+ int m;
+};
+
+int main()
+{
+ boost::shared_ptr<X[]> px( new X[ 1 ] );
+ px->m = 0;
+}
diff --git a/test/array_fail_sp_spa_a.cpp b/test/array_fail_sp_spa_a.cpp
new file mode 100644
index 0000000..e1e2bb6
--- /dev/null
+++ b/test/array_fail_sp_spa_a.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X> px;
+ boost::shared_ptr<X[]> px2; px2 = px;
+}
diff --git a/test/array_fail_sp_spa_c.cpp b/test/array_fail_sp_spa_c.cpp
new file mode 100644
index 0000000..c65df88
--- /dev/null
+++ b/test/array_fail_sp_spa_c.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X> px;
+ boost::shared_ptr<X[]> px2( px );
+}
diff --git a/test/array_fail_sp_spa_ma.cpp b/test/array_fail_sp_spa_ma.cpp
new file mode 100644
index 0000000..a1253a0
--- /dev/null
+++ b/test/array_fail_sp_spa_ma.cpp
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X[]> px2; px2 = boost::shared_ptr<X>();
+}
diff --git a/test/array_fail_sp_spa_mc.cpp b/test/array_fail_sp_spa_mc.cpp
new file mode 100644
index 0000000..75c014c
--- /dev/null
+++ b/test/array_fail_sp_spa_mc.cpp
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X[]> px2(( boost::shared_ptr<X>() ));
+}
diff --git a/test/array_fail_sp_wpa_a.cpp b/test/array_fail_sp_wpa_a.cpp
new file mode 100644
index 0000000..8b88512
--- /dev/null
+++ b/test/array_fail_sp_wpa_a.cpp
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X> px;
+ boost::weak_ptr<X[]> px2; px2 = px;
+}
diff --git a/test/array_fail_sp_wpa_c.cpp b/test/array_fail_sp_wpa_c.cpp
new file mode 100644
index 0000000..fc7cd5b
--- /dev/null
+++ b/test/array_fail_sp_wpa_c.cpp
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X> px;
+ boost::weak_ptr<X[]> px2( px );
+}
diff --git a/test/array_fail_sp_wpa_ma.cpp b/test/array_fail_sp_wpa_ma.cpp
new file mode 100644
index 0000000..578e10b
--- /dev/null
+++ b/test/array_fail_sp_wpa_ma.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X[]> px2; px2 = boost::shared_ptr<X>();
+}
diff --git a/test/array_fail_sp_wpa_mc.cpp b/test/array_fail_sp_wpa_mc.cpp
new file mode 100644
index 0000000..ca62eaf
--- /dev/null
+++ b/test/array_fail_sp_wpa_mc.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X[]> px2(( boost::shared_ptr<X>() ));
+}
diff --git a/test/array_fail_spa_sp_a.cpp b/test/array_fail_spa_sp_a.cpp
new file mode 100644
index 0000000..4d6d323
--- /dev/null
+++ b/test/array_fail_spa_sp_a.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X[]> px;
+ boost::shared_ptr<X> px2; px2 = px;
+}
diff --git a/test/array_fail_spa_sp_c.cpp b/test/array_fail_spa_sp_c.cpp
new file mode 100644
index 0000000..9015483
--- /dev/null
+++ b/test/array_fail_spa_sp_c.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X[]> px;
+ boost::shared_ptr<X> px2( px );
+}
diff --git a/test/array_fail_spa_sp_ma.cpp b/test/array_fail_spa_sp_ma.cpp
new file mode 100644
index 0000000..6511887
--- /dev/null
+++ b/test/array_fail_spa_sp_ma.cpp
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X> px2; px2 = boost::shared_ptr<X[]>();
+}
diff --git a/test/array_fail_spa_sp_mc.cpp b/test/array_fail_spa_sp_mc.cpp
new file mode 100644
index 0000000..46f6e30
--- /dev/null
+++ b/test/array_fail_spa_sp_mc.cpp
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X> px2(( boost::shared_ptr<X[]>() ));
+}
diff --git a/test/array_fail_spa_spa_a.cpp b/test/array_fail_spa_spa_a.cpp
new file mode 100644
index 0000000..edb248d
--- /dev/null
+++ b/test/array_fail_spa_spa_a.cpp
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+struct Y: public X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<Y[]> px;
+ boost::shared_ptr<X[]> px2; px2 = px;
+}
diff --git a/test/array_fail_spa_spa_c.cpp b/test/array_fail_spa_spa_c.cpp
new file mode 100644
index 0000000..a1833ee
--- /dev/null
+++ b/test/array_fail_spa_spa_c.cpp
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+struct Y: public X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<Y[]> px;
+ boost::shared_ptr<X[]> px2( px );
+}
diff --git a/test/array_fail_spa_spa_ma.cpp b/test/array_fail_spa_spa_ma.cpp
new file mode 100644
index 0000000..8c81693
--- /dev/null
+++ b/test/array_fail_spa_spa_ma.cpp
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+struct Y: public X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X[]> px2; px2 = boost::shared_ptr<Y[]>();
+}
diff --git a/test/array_fail_spa_spa_mc.cpp b/test/array_fail_spa_spa_mc.cpp
new file mode 100644
index 0000000..606d937
--- /dev/null
+++ b/test/array_fail_spa_spa_mc.cpp
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+struct Y: public X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X[]> px2(( boost::shared_ptr<Y[]>() ));
+}
diff --git a/test/array_fail_spa_wp_a.cpp b/test/array_fail_spa_wp_a.cpp
new file mode 100644
index 0000000..14c122e
--- /dev/null
+++ b/test/array_fail_spa_wp_a.cpp
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X[]> px;
+ boost::weak_ptr<X> px2; px2 = px;
+}
diff --git a/test/array_fail_spa_wp_c.cpp b/test/array_fail_spa_wp_c.cpp
new file mode 100644
index 0000000..9c22a5b
--- /dev/null
+++ b/test/array_fail_spa_wp_c.cpp
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X[]> px;
+ boost::weak_ptr<X> px2( px );
+}
diff --git a/test/array_fail_spa_wp_ma.cpp b/test/array_fail_spa_wp_ma.cpp
new file mode 100644
index 0000000..49c1eb0
--- /dev/null
+++ b/test/array_fail_spa_wp_ma.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X> px2; px2 = boost::shared_ptr<X[]>();
+}
diff --git a/test/array_fail_spa_wp_mc.cpp b/test/array_fail_spa_wp_mc.cpp
new file mode 100644
index 0000000..738946c
--- /dev/null
+++ b/test/array_fail_spa_wp_mc.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X> px2(( boost::shared_ptr<X[]>() ));
+}
diff --git a/test/array_fail_spa_wpa_a.cpp b/test/array_fail_spa_wpa_a.cpp
new file mode 100644
index 0000000..9c65f1c
--- /dev/null
+++ b/test/array_fail_spa_wpa_a.cpp
@@ -0,0 +1,24 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+struct Y: public X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<Y[]> px;
+ boost::weak_ptr<X[]> px2; px2 = px;
+}
diff --git a/test/array_fail_spa_wpa_c.cpp b/test/array_fail_spa_wpa_c.cpp
new file mode 100644
index 0000000..ff2ae22
--- /dev/null
+++ b/test/array_fail_spa_wpa_c.cpp
@@ -0,0 +1,24 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+struct Y: public X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<Y[]> px;
+ boost::weak_ptr<X[]> px2( px );
+}
diff --git a/test/array_fail_spa_wpa_ma.cpp b/test/array_fail_spa_wpa_ma.cpp
new file mode 100644
index 0000000..cb2725e
--- /dev/null
+++ b/test/array_fail_spa_wpa_ma.cpp
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+struct Y: public X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X[]> px2; px2 = boost::shared_ptr<Y[]>();
+}
diff --git a/test/array_fail_spa_wpa_mc.cpp b/test/array_fail_spa_wpa_mc.cpp
new file mode 100644
index 0000000..9b07933
--- /dev/null
+++ b/test/array_fail_spa_wpa_mc.cpp
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+struct Y: public X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X[]> px2(( boost::shared_ptr<Y[]>() ));
+}
diff --git a/test/array_fail_up_spa_a.cpp b/test/array_fail_up_spa_a.cpp
new file mode 100644
index 0000000..8b9f246
--- /dev/null
+++ b/test/array_fail_up_spa_a.cpp
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+
+struct X
+{
+};
+
+int main()
+{
+ std::unique_ptr<X> px;
+ boost::shared_ptr<X[]> px2; px2 = px;
+}
diff --git a/test/array_fail_up_spa_c.cpp b/test/array_fail_up_spa_c.cpp
new file mode 100644
index 0000000..1bbc5c0
--- /dev/null
+++ b/test/array_fail_up_spa_c.cpp
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+
+struct X
+{
+};
+
+int main()
+{
+ std::unique_ptr<X> px;
+ boost::shared_ptr<X[]> px2( px );
+}
diff --git a/test/array_fail_up_spa_ma.cpp b/test/array_fail_up_spa_ma.cpp
new file mode 100644
index 0000000..fcd612d
--- /dev/null
+++ b/test/array_fail_up_spa_ma.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X[]> px2; px2 = std::unique_ptr<X>();
+}
diff --git a/test/array_fail_up_spa_mc.cpp b/test/array_fail_up_spa_mc.cpp
new file mode 100644
index 0000000..6a20d6e
--- /dev/null
+++ b/test/array_fail_up_spa_mc.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X[]> px2(( std::unique_ptr<X>() ));
+}
diff --git a/test/array_fail_upa_sp_a.cpp b/test/array_fail_upa_sp_a.cpp
new file mode 100644
index 0000000..4d87fdd
--- /dev/null
+++ b/test/array_fail_upa_sp_a.cpp
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+
+struct X
+{
+};
+
+int main()
+{
+ std::unique_ptr<X[]> px;
+ boost::shared_ptr<X> px2; px2 = px;
+}
diff --git a/test/array_fail_upa_sp_c.cpp b/test/array_fail_upa_sp_c.cpp
new file mode 100644
index 0000000..259fda0
--- /dev/null
+++ b/test/array_fail_upa_sp_c.cpp
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+
+struct X
+{
+};
+
+int main()
+{
+ std::unique_ptr<X[]> px;
+ boost::shared_ptr<X> px2( px );
+}
diff --git a/test/array_fail_upa_sp_ma.cpp b/test/array_fail_upa_sp_ma.cpp
new file mode 100644
index 0000000..1b2a2b2
--- /dev/null
+++ b/test/array_fail_upa_sp_ma.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X> px2; px2 = std::unique_ptr<X[]>();
+}
diff --git a/test/array_fail_upa_sp_mc.cpp b/test/array_fail_upa_sp_mc.cpp
new file mode 100644
index 0000000..d314a01
--- /dev/null
+++ b/test/array_fail_upa_sp_mc.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X> px2(( std::unique_ptr<X[]>() ));
+}
diff --git a/test/array_fail_wp_wpa_a.cpp b/test/array_fail_wp_wpa_a.cpp
new file mode 100644
index 0000000..ea82eb9
--- /dev/null
+++ b/test/array_fail_wp_wpa_a.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X> px;
+ boost::weak_ptr<X[]> px2; px2 = px;
+}
diff --git a/test/array_fail_wp_wpa_c.cpp b/test/array_fail_wp_wpa_c.cpp
new file mode 100644
index 0000000..9f5609c
--- /dev/null
+++ b/test/array_fail_wp_wpa_c.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X> px;
+ boost::weak_ptr<X[]> px2( px );
+}
diff --git a/test/array_fail_wp_wpa_ma.cpp b/test/array_fail_wp_wpa_ma.cpp
new file mode 100644
index 0000000..79af4d7
--- /dev/null
+++ b/test/array_fail_wp_wpa_ma.cpp
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X[]> px2; px2 = boost::weak_ptr<X>();
+}
diff --git a/test/array_fail_wp_wpa_mc.cpp b/test/array_fail_wp_wpa_mc.cpp
new file mode 100644
index 0000000..18a9d8a
--- /dev/null
+++ b/test/array_fail_wp_wpa_mc.cpp
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X[]> px2(( boost::weak_ptr<X>() ));
+}
diff --git a/test/array_fail_wpa_wp_a.cpp b/test/array_fail_wpa_wp_a.cpp
new file mode 100644
index 0000000..19d0026
--- /dev/null
+++ b/test/array_fail_wpa_wp_a.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X[]> px;
+ boost::weak_ptr<X> px2; px2 = px;
+}
diff --git a/test/array_fail_wpa_wp_c.cpp b/test/array_fail_wpa_wp_c.cpp
new file mode 100644
index 0000000..d4b75dd
--- /dev/null
+++ b/test/array_fail_wpa_wp_c.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X[]> px;
+ boost::weak_ptr<X> px2( px );
+}
diff --git a/test/array_fail_wpa_wp_ma.cpp b/test/array_fail_wpa_wp_ma.cpp
new file mode 100644
index 0000000..5c33c8b
--- /dev/null
+++ b/test/array_fail_wpa_wp_ma.cpp
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X> px2; px2 = boost::weak_ptr<X[]>();
+}
diff --git a/test/array_fail_wpa_wp_mc.cpp b/test/array_fail_wpa_wp_mc.cpp
new file mode 100644
index 0000000..8375e6b
--- /dev/null
+++ b/test/array_fail_wpa_wp_mc.cpp
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X> px2(( boost::weak_ptr<X[]>() ));
+}
diff --git a/test/array_fail_wpa_wpa_a.cpp b/test/array_fail_wpa_wpa_a.cpp
new file mode 100644
index 0000000..29aeaa6
--- /dev/null
+++ b/test/array_fail_wpa_wpa_a.cpp
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+struct Y: public X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<Y[]> px;
+ boost::weak_ptr<X[]> px2; px2 = px;
+}
diff --git a/test/array_fail_wpa_wpa_c.cpp b/test/array_fail_wpa_wpa_c.cpp
new file mode 100644
index 0000000..98a574e
--- /dev/null
+++ b/test/array_fail_wpa_wpa_c.cpp
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+struct Y: public X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<Y[]> px;
+ boost::weak_ptr<X[]> px2( px );
+}
diff --git a/test/array_fail_wpa_wpa_ma.cpp b/test/array_fail_wpa_wpa_ma.cpp
new file mode 100644
index 0000000..eb638de
--- /dev/null
+++ b/test/array_fail_wpa_wpa_ma.cpp
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+struct Y: public X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X[]> px2; px2 = boost::weak_ptr<Y[]>();
+}
diff --git a/test/array_fail_wpa_wpa_mc.cpp b/test/array_fail_wpa_wpa_mc.cpp
new file mode 100644
index 0000000..77d4f75
--- /dev/null
+++ b/test/array_fail_wpa_wpa_mc.cpp
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/weak_ptr.hpp>
+
+struct X
+{
+};
+
+struct Y: public X
+{
+};
+
+int main()
+{
+ boost::weak_ptr<X[]> px2(( boost::weak_ptr<Y[]>() ));
+}
diff --git a/test/atomic_count_test.cpp b/test/atomic_count_test.cpp
new file mode 100644
index 0000000..ecc24c0
--- /dev/null
+++ b/test/atomic_count_test.cpp
@@ -0,0 +1,40 @@
+//
+// atomic_count_test.cpp
+//
+// Copyright 2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/detail/atomic_count.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ boost::detail::atomic_count n( 4 );
+
+ BOOST_TEST( n == 4L );
+
+ ++n;
+
+ BOOST_TEST( n == 5L );
+ BOOST_TEST( --n != 0L );
+
+ boost::detail::atomic_count m( 0 );
+
+ BOOST_TEST( m == 0 );
+
+ ++m;
+
+ BOOST_TEST( m == 1 );
+
+ ++m;
+
+ BOOST_TEST( m == 2 );
+ BOOST_TEST( --m != 0 );
+ BOOST_TEST( --m == 0 );
+
+ return boost::report_errors();
+}
diff --git a/test/atomic_count_test2.cpp b/test/atomic_count_test2.cpp
new file mode 100644
index 0000000..7e6dd97
--- /dev/null
+++ b/test/atomic_count_test2.cpp
@@ -0,0 +1,55 @@
+//
+// atomic_count_test2.cpp
+//
+// Copyright 2009 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
+//
+
+#include <boost/detail/atomic_count.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ boost::detail::atomic_count n( 4 );
+
+ BOOST_TEST( n == 4 );
+
+ BOOST_TEST( ++n == 5 );
+ BOOST_TEST( ++n == 6 );
+
+ BOOST_TEST( n == 6 );
+
+ BOOST_TEST( --n == 5 );
+ BOOST_TEST( --n == 4 );
+
+ BOOST_TEST( n == 4 );
+
+ boost::detail::atomic_count m( 0 );
+
+ BOOST_TEST( m == 0 );
+
+ BOOST_TEST( ++m == 1 );
+ BOOST_TEST( ++m == 2 );
+
+ BOOST_TEST( m == 2 );
+
+ BOOST_TEST( --m == 1 );
+ BOOST_TEST( --m == 0 );
+
+ BOOST_TEST( m == 0 );
+
+ BOOST_TEST( --m == -1 );
+ BOOST_TEST( --m == -2 );
+
+ BOOST_TEST( m == -2 );
+
+ BOOST_TEST( ++m == -1 );
+ BOOST_TEST( ++m == 0 );
+
+ BOOST_TEST( m == 0 );
+
+ return boost::report_errors();
+}
diff --git a/test/atomic_sp_constexpr_test.cpp b/test/atomic_sp_constexpr_test.cpp
new file mode 100644
index 0000000..3807deb
--- /dev/null
+++ b/test/atomic_sp_constexpr_test.cpp
@@ -0,0 +1,77 @@
+//
+// atomic_sp_constexpr_test.cpp
+//
+// Copyright 2017, 2018 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
+//
+
+#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
+#include <boost/config/pragma_message.hpp>
+#include <boost/config/helper_macros.hpp>
+
+#if defined( BOOST_NO_CXX11_CONSTEXPR )
+
+BOOST_PRAGMA_MESSAGE("Skipping test due to BOOST_NO_CXX11_CONSTEXPR")
+int main() {}
+
+#elif BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+
+// MSVC does not implement static initialization for constexpr
+BOOST_PRAGMA_MESSAGE("Skipping test due to BOOST_MSVC < 1920")
+int main() {}
+
+#elif defined(__clang__) && defined( BOOST_NO_CXX14_CONSTEXPR )
+
+// Clang only implements static initialization for constexpr in C++14 mode
+BOOST_PRAGMA_MESSAGE("Skipping test due to __clang__ and BOOST_NO_CXX14_CONSTEXPR")
+int main() {}
+
+#elif defined( _LIBCPP_VERSION ) && ( _LIBCPP_VERSION < 6000 )
+
+// in libc++, atomic_flag has a non-constexpr constructor from bool
+BOOST_PRAGMA_MESSAGE("Skipping test due to _LIBCPP_VERSION " BOOST_STRINGIZE(_LIBCPP_VERSION))
+int main() {}
+
+#elif defined( BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX )
+
+BOOST_PRAGMA_MESSAGE("Skipping test due to BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX")
+int main() {}
+
+#else
+
+#include <boost/smart_ptr/atomic_shared_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+struct X
+{
+};
+
+struct Z
+{
+ Z();
+};
+
+static Z z;
+
+static boost::atomic_shared_ptr<X> p1;
+
+Z::Z()
+{
+ p1 = boost::shared_ptr<X>( new X );
+}
+
+int main()
+{
+ boost::shared_ptr<X> p2 = p1;
+
+ BOOST_TEST( p2.get() != 0 );
+ BOOST_TEST_EQ( p2.use_count(), 2 );
+
+ return boost::report_errors();
+}
+
+#endif
diff --git a/test/atomic_sp_test.cpp b/test/atomic_sp_test.cpp
new file mode 100644
index 0000000..1b0b839
--- /dev/null
+++ b/test/atomic_sp_test.cpp
@@ -0,0 +1,325 @@
+#include <boost/config.hpp>
+
+// atomic_sp_test.cpp
+//
+// Copyright 2008, 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
+
+
+#include <boost/smart_ptr/atomic_shared_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/memory_order.hpp>
+
+//
+
+struct X
+{
+};
+
+#define BOOST_TEST_SP_EQ( p, q ) BOOST_TEST( p == q && !( p < q ) && !( q < p ) )
+
+int main()
+{
+ // default constructor
+
+ {
+ boost::atomic_shared_ptr<X> apx;
+
+ boost::shared_ptr<X> p2 = apx.load();
+
+ BOOST_TEST_EQ( p2.get(), (X*)0 );
+ BOOST_TEST_EQ( p2.use_count(), 0 );
+ }
+
+ // shared_ptr constructor
+
+ {
+ boost::shared_ptr<X> px( new X );
+ boost::atomic_shared_ptr<X> apx( px );
+
+ boost::shared_ptr<X> p2 = apx.load();
+
+ BOOST_TEST_EQ( px, p2 );
+ BOOST_TEST_EQ( px.use_count(), 3 );
+ BOOST_TEST_EQ( p2.use_count(), 3 );
+ }
+
+ // shared_ptr assignment
+
+ {
+ boost::shared_ptr<X> px0( new X );
+ boost::atomic_shared_ptr<X> apx( px0 );
+
+ boost::shared_ptr<X> px( new X );
+ apx = px;
+
+ boost::shared_ptr<X> p2 = apx.load();
+
+ BOOST_TEST_EQ( px, p2 );
+ BOOST_TEST_EQ( px.use_count(), 3 );
+ BOOST_TEST_EQ( p2.use_count(), 3 );
+ }
+
+ // load, w/ mo
+
+ {
+ boost::shared_ptr<X> px( new X );
+ boost::atomic_shared_ptr<X> apx( px );
+
+ boost::shared_ptr<X> p2 = apx.load( boost::memory_order_acquire );
+
+ BOOST_TEST_EQ( px, p2 );
+ BOOST_TEST_EQ( px.use_count(), 3 );
+ BOOST_TEST_EQ( p2.use_count(), 3 );
+ }
+
+ // operator shared_ptr
+
+ {
+ boost::shared_ptr<X> px( new X );
+ boost::atomic_shared_ptr<X> apx( px );
+
+ boost::shared_ptr<X> p2 = apx;
+
+ BOOST_TEST_EQ( px, p2 );
+ BOOST_TEST_EQ( px.use_count(), 3 );
+ BOOST_TEST_EQ( p2.use_count(), 3 );
+ }
+
+ // store
+
+ {
+ boost::shared_ptr<X> px0( new X );
+ boost::atomic_shared_ptr<X> apx( px0 );
+
+ boost::shared_ptr<X> px( new X );
+ apx.store( px );
+
+ boost::shared_ptr<X> p2 = apx.load();
+
+ BOOST_TEST_EQ( px, p2 );
+ BOOST_TEST_EQ( px.use_count(), 3 );
+ BOOST_TEST_EQ( p2.use_count(), 3 );
+ }
+
+ // store, w/ mo
+
+ {
+ boost::shared_ptr<X> px0( new X );
+ boost::atomic_shared_ptr<X> apx( px0 );
+
+ boost::shared_ptr<X> px( new X );
+ apx.store( px, boost::memory_order_release );
+
+ boost::shared_ptr<X> p2 = apx.load();
+
+ BOOST_TEST_EQ( px, p2 );
+ BOOST_TEST_EQ( px.use_count(), 3 );
+ BOOST_TEST_EQ( p2.use_count(), 3 );
+ }
+
+ // exchange
+
+ {
+ boost::shared_ptr<X> px0( new X );
+ boost::atomic_shared_ptr<X> apx( px0 );
+
+ boost::shared_ptr<X> px( new X );
+ boost::shared_ptr<X> p1 = apx.exchange( px );
+
+ BOOST_TEST_EQ( px0, p1 );
+ BOOST_TEST_EQ( px0.use_count(), 2 );
+ BOOST_TEST_EQ( p1.use_count(), 2 );
+
+ boost::shared_ptr<X> p2 = apx.load();
+
+ BOOST_TEST_EQ( px, p2 );
+ BOOST_TEST_EQ( px.use_count(), 3 );
+ BOOST_TEST_EQ( p2.use_count(), 3 );
+ }
+
+ // exchange, w/ mo
+
+ {
+ boost::shared_ptr<X> px0( new X );
+ boost::atomic_shared_ptr<X> apx( px0 );
+
+ boost::shared_ptr<X> px( new X );
+ boost::shared_ptr<X> p1 = apx.exchange( px, boost::memory_order_acq_rel );
+
+ BOOST_TEST_EQ( px0, p1 );
+ BOOST_TEST_EQ( px0.use_count(), 2 );
+ BOOST_TEST_EQ( p1.use_count(), 2 );
+
+ boost::shared_ptr<X> p2 = apx.load();
+
+ BOOST_TEST_EQ( px, p2 );
+ BOOST_TEST_EQ( px.use_count(), 3 );
+ BOOST_TEST_EQ( p2.use_count(), 3 );
+ }
+
+ // compare_exchange_weak
+
+ {
+ boost::shared_ptr<X> px( new X );
+ boost::atomic_shared_ptr<X> apx( px );
+
+ boost::shared_ptr<X> px2( new X );
+ boost::shared_ptr<X> cmp;
+
+ bool r = apx.compare_exchange_weak( cmp, px2 );
+ BOOST_TEST( !r );
+ BOOST_TEST_SP_EQ( apx.load(), px );
+ BOOST_TEST_SP_EQ( cmp, px );
+
+ r = apx.compare_exchange_weak( cmp, px2 );
+ BOOST_TEST( r );
+ BOOST_TEST_SP_EQ( apx.load(), px2 );
+ }
+
+ // compare_exchange_weak, w/ mo
+
+ {
+ boost::shared_ptr<X> px( new X );
+ boost::atomic_shared_ptr<X> apx( px );
+
+ boost::shared_ptr<X> px2( new X );
+ boost::shared_ptr<X> cmp;
+
+ bool r = apx.compare_exchange_weak( cmp, px2, boost::memory_order_seq_cst, boost::memory_order_seq_cst );
+ BOOST_TEST( !r );
+ BOOST_TEST_SP_EQ( apx.load(), px );
+ BOOST_TEST_SP_EQ( cmp, px );
+
+ r = apx.compare_exchange_weak( cmp, px2, boost::memory_order_seq_cst, boost::memory_order_seq_cst );
+ BOOST_TEST( r );
+ BOOST_TEST_SP_EQ( apx.load(), px2 );
+ }
+
+ // compare_exchange_weak, rv
+
+ {
+ boost::shared_ptr<X> px( new X );
+ boost::atomic_shared_ptr<X> apx( px );
+
+ boost::shared_ptr<X> cmp;
+
+ bool r = apx.compare_exchange_weak( cmp, boost::shared_ptr<X>() );
+
+ BOOST_TEST( !r );
+ BOOST_TEST_SP_EQ( apx.load(), px );
+ BOOST_TEST_SP_EQ( cmp, px );
+
+ r = apx.compare_exchange_weak( cmp, boost::shared_ptr<X>() );
+
+ BOOST_TEST( r );
+ BOOST_TEST( apx.load().get() == 0 );
+ BOOST_TEST( apx.load().use_count() == 0 );
+ }
+
+ // compare_exchange_weak, rv, w/ mo
+
+ {
+ boost::shared_ptr<X> px( new X );
+ boost::atomic_shared_ptr<X> apx( px );
+
+ boost::shared_ptr<X> cmp;
+
+ bool r = apx.compare_exchange_weak( cmp, boost::shared_ptr<X>(), boost::memory_order_seq_cst, boost::memory_order_seq_cst );
+
+ BOOST_TEST( !r );
+ BOOST_TEST_SP_EQ( apx.load(), px );
+ BOOST_TEST_SP_EQ( cmp, px );
+
+ r = apx.compare_exchange_weak( cmp, boost::shared_ptr<X>(), boost::memory_order_seq_cst, boost::memory_order_seq_cst );
+
+ BOOST_TEST( r );
+ BOOST_TEST( apx.load().get() == 0 );
+ BOOST_TEST( apx.load().use_count() == 0 );
+ }
+
+ // compare_exchange_strong
+
+ {
+ boost::shared_ptr<X> px( new X );
+ boost::atomic_shared_ptr<X> apx( px );
+
+ boost::shared_ptr<X> px2( new X );
+ boost::shared_ptr<X> cmp;
+
+ bool r = apx.compare_exchange_strong( cmp, px2 );
+ BOOST_TEST( !r );
+ BOOST_TEST_SP_EQ( apx.load(), px );
+ BOOST_TEST_SP_EQ( cmp, px );
+
+ r = apx.compare_exchange_strong( cmp, px2 );
+ BOOST_TEST( r );
+ BOOST_TEST_SP_EQ( apx.load(), px2 );
+ }
+
+ // compare_exchange_strong, w/ mo
+
+ {
+ boost::shared_ptr<X> px( new X );
+ boost::atomic_shared_ptr<X> apx( px );
+
+ boost::shared_ptr<X> px2( new X );
+ boost::shared_ptr<X> cmp;
+
+ bool r = apx.compare_exchange_strong( cmp, px2, boost::memory_order_seq_cst, boost::memory_order_seq_cst );
+ BOOST_TEST( !r );
+ BOOST_TEST_SP_EQ( apx.load(), px );
+ BOOST_TEST_SP_EQ( cmp, px );
+
+ r = apx.compare_exchange_strong( cmp, px2, boost::memory_order_seq_cst, boost::memory_order_seq_cst );
+ BOOST_TEST( r );
+ BOOST_TEST_SP_EQ( apx.load(), px2 );
+ }
+
+ // compare_exchange_strong, rv
+
+ {
+ boost::shared_ptr<X> px( new X );
+ boost::atomic_shared_ptr<X> apx( px );
+
+ boost::shared_ptr<X> cmp;
+
+ bool r = apx.compare_exchange_strong( cmp, boost::shared_ptr<X>() );
+
+ BOOST_TEST( !r );
+ BOOST_TEST_SP_EQ( apx.load(), px );
+ BOOST_TEST_SP_EQ( cmp, px );
+
+ r = apx.compare_exchange_strong( cmp, boost::shared_ptr<X>() );
+
+ BOOST_TEST( r );
+ BOOST_TEST( apx.load().get() == 0 );
+ BOOST_TEST( apx.load().use_count() == 0 );
+ }
+
+ // compare_exchange_strong, rv, w/ mo
+
+ {
+ boost::shared_ptr<X> px( new X );
+ boost::atomic_shared_ptr<X> apx( px );
+
+ boost::shared_ptr<X> cmp;
+
+ bool r = apx.compare_exchange_strong( cmp, boost::shared_ptr<X>(), boost::memory_order_seq_cst, boost::memory_order_seq_cst );
+
+ BOOST_TEST( !r );
+ BOOST_TEST_SP_EQ( apx.load(), px );
+ BOOST_TEST_SP_EQ( cmp, px );
+
+ r = apx.compare_exchange_strong( cmp, boost::shared_ptr<X>(), boost::memory_order_seq_cst, boost::memory_order_seq_cst );
+
+ BOOST_TEST( r );
+ BOOST_TEST( apx.load().get() == 0 );
+ BOOST_TEST( apx.load().use_count() == 0 );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/auto_ptr_lv_fail.cpp b/test/auto_ptr_lv_fail.cpp
new file mode 100644
index 0000000..b86832e
--- /dev/null
+++ b/test/auto_ptr_lv_fail.cpp
@@ -0,0 +1,32 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#endif
+
+//
+// auto_ptr_lv_fail.cpp - a negative test for converting an auto_ptr to shared_ptr
+//
+// Copyright 2009 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <memory>
+
+void f( boost::shared_ptr<int> )
+{
+}
+
+int main()
+{
+ std::auto_ptr<int> p;
+ f( p ); // must fail
+ return 0;
+}
diff --git a/test/auto_ptr_rv_test.cpp b/test/auto_ptr_rv_test.cpp
new file mode 100644
index 0000000..5123439
--- /dev/null
+++ b/test/auto_ptr_rv_test.cpp
@@ -0,0 +1,123 @@
+#include <boost/config.hpp>
+
+//
+// auto_ptr_rv_test.cpp
+//
+// Copyright (c) 2006 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
+//
+
+#if defined( BOOST_NO_AUTO_PTR )
+
+int main()
+{
+}
+
+#else
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <memory>
+
+struct X
+{
+ static long instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+ static std::auto_ptr<X> create()
+ {
+ return std::auto_ptr<X>( new X );
+ }
+
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+};
+
+long X::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X> p( X::create() );
+ BOOST_TEST( X::instances == 1 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+
+ p.reset();
+ BOOST_TEST( X::instances == 0 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X const> p( X::create() );
+ BOOST_TEST( X::instances == 1 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+
+ p.reset();
+ BOOST_TEST( X::instances == 0 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<void> p( X::create() );
+ BOOST_TEST( X::instances == 1 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+
+ p.reset();
+ BOOST_TEST( X::instances == 0 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<void const> p( X::create() );
+ BOOST_TEST( X::instances == 1 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+
+ p.reset();
+ BOOST_TEST( X::instances == 0 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ return boost::report_errors();
+}
+
+#endif // #if defined( BOOST_NO_AUTO_PTR )
diff --git a/test/collector_test.cpp b/test/collector_test.cpp
new file mode 100644
index 0000000..062b557
--- /dev/null
+++ b/test/collector_test.cpp
@@ -0,0 +1,99 @@
+//
+// collector_test.cpp
+//
+// Copyright (c) 2003 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/shared_ptr.hpp>
+#include <vector>
+#include <iostream>
+#include <cstdlib>
+#include <ctime>
+
+// sp_collector.cpp exported functions
+
+std::size_t find_unreachable_objects(bool report);
+void free_unreachable_objects();
+
+struct X
+{
+ void* fill[32];
+ boost::shared_ptr<X> p;
+};
+
+void report()
+{
+ std::cout << "Calling find_unreachable_objects:\n";
+
+ std::clock_t t = std::clock();
+
+ std::size_t n = find_unreachable_objects(false);
+
+ t = std::clock() - t;
+
+ std::cout << n << " unreachable objects.\n";
+ std::cout << " " << static_cast<double>(t) / CLOCKS_PER_SEC << " seconds.\n";
+}
+
+void free()
+{
+ std::cout << "Calling free_unreachable_objects:\n";
+
+ std::clock_t t = std::clock();
+
+ free_unreachable_objects();
+
+ t = std::clock() - t;
+
+ std::cout << " " << static_cast<double>(t) / CLOCKS_PER_SEC << " seconds.\n";
+}
+
+int main()
+{
+ std::vector< boost::shared_ptr<X> > v1, v2;
+
+ int const n = 256 * 1024;
+
+ std::cout << "Filling v1 and v2\n";
+
+ for(int i = 0; i < n; ++i)
+ {
+ v1.push_back(boost::shared_ptr<X>(new X));
+ v2.push_back(boost::shared_ptr<X>(new X));
+ }
+
+ report();
+
+ std::cout << "Creating the cycles\n";
+
+ for(int i = 0; i < n - 1; ++i)
+ {
+ v2[i]->p = v2[i+1];
+ }
+
+ v2[n-1]->p = v2[0];
+
+ report();
+
+ std::cout << "Resizing v2 to size of 1\n";
+
+ v2.resize(1);
+ report();
+
+ std::cout << "Clearing v2\n";
+
+ v2.clear();
+ report();
+
+ std::cout << "Clearing v1\n";
+
+ v1.clear();
+ report();
+
+ free();
+ report();
+}
diff --git a/test/cpp11_pointer_cast_test.cpp b/test/cpp11_pointer_cast_test.cpp
new file mode 100644
index 0000000..a9361c3
--- /dev/null
+++ b/test/cpp11_pointer_cast_test.cpp
@@ -0,0 +1,224 @@
+//
+// cpp11_pointer_cast_test.cpp - a test for boost/pointer_cast.hpp with std::shared_ptr and std::unique_ptr
+//
+// Copyright (c) 2016 Karolin Varner
+//
+// 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)
+//
+
+#include <boost/pointer_cast.hpp>
+
+#include <boost/config.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/get_pointer.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <memory>
+#include <utility>
+#include <functional>
+
+#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) \
+ || defined( BOOST_NO_CXX11_HDR_FUNCTIONAL ) \
+ || defined( BOOST_NO_CXX11_HDR_UTILITY ) \
+ || defined( BOOST_NO_CXX11_LAMBDAS ) \
+ || defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+// We expect all the features or none of the features to be
+// available, since we should be on C++11
+int main() { return 0; }
+
+#else
+
+namespace
+{
+
+// Let's create these inheritance relationship:
+//
+// base base2
+// | |
+// derived
+// |
+// derived_derived
+//
+
+class base
+{
+ public:
+ virtual ~base(){}
+ int filler [5];
+};
+
+class base2
+{
+public:
+
+ virtual ~base2(){}
+ int filler [5];
+};
+
+class derived
+ : public base, public base2
+{
+ int filler [5];
+};
+
+class derived_derived
+ : public derived
+{
+ int filler [5];
+};
+
+// And now some simple check functions
+
+#if !defined( BOOST_NO_RTTI )
+
+template <class BasePtr>
+bool check_dynamic_pointer_cast(const BasePtr &ptr)
+{
+ //Check that dynamic_pointer_cast versus dynamic_cast
+ return
+ //Correct cast with dynamic_pointer_cast
+ boost::get_pointer(boost::dynamic_pointer_cast<derived>(ptr)) ==
+ //Correct cast with dynamic_cast
+ dynamic_cast<derived*>(boost::get_pointer(ptr))
+ &&
+ //Incorrect cast with dynamic_pointer_cast
+ boost::get_pointer(boost::dynamic_pointer_cast<derived_derived>(ptr)) ==
+ //Incorrect cast with dynamic_cast
+ dynamic_cast<derived_derived*>(boost::get_pointer(ptr));
+}
+
+#endif
+
+template <class BasePtr>
+bool check_static_pointer_cast(const BasePtr &ptr)
+{
+ return
+ //Cast base -> derived -> base2 using static_pointer_cast
+ boost::get_pointer(
+ boost::static_pointer_cast<base2>(
+ boost::static_pointer_cast<derived>(ptr))) ==
+ //Now the same with static_cast
+ static_cast<base2*>(static_cast<derived*>(boost::get_pointer(ptr)));
+}
+
+template <class BasePtr>
+bool check_const_pointer_cast(const BasePtr &ptr)
+{
+ return
+ //Unconst and const again using const_pointer_cast
+ boost::get_pointer(
+ boost::const_pointer_cast<const base>
+ (boost::const_pointer_cast<base>(ptr))) ==
+ //Now the same with const_cast
+ const_cast<const base*>(const_cast<base*>(boost::get_pointer(ptr)));
+}
+
+template <class BasePtr>
+void check_all_copy_casts(const BasePtr &ptr)
+{
+#if !defined( BOOST_NO_RTTI )
+ BOOST_TEST( check_dynamic_pointer_cast( ptr ) );
+#endif
+ BOOST_TEST( check_static_pointer_cast( ptr ) );
+ BOOST_TEST( check_const_pointer_cast( ptr ) );
+}
+
+
+#if !defined( BOOST_NO_RTTI )
+
+template <class BasePtr>
+bool check_dynamic_moving_pointer_cast(std::function<BasePtr()> f)
+{
+ BasePtr smart1 = f(), smart2 = f();
+ derived* expect1 = dynamic_cast<derived*>(boost::get_pointer(smart1));
+ derived_derived* expect2 = dynamic_cast<derived_derived*>(boost::get_pointer(smart2));
+ //Check that dynamic_pointer_cast versus dynamic_cast
+ return
+ //Correct cast with dynamic_pointer_cast
+ boost::get_pointer(boost::dynamic_pointer_cast<derived>( std::move(smart1) )) == expect1
+ &&
+ //Incorrect cast with dynamic_pointer_cast
+ boost::get_pointer(boost::dynamic_pointer_cast<derived_derived>( std::move(smart2) )) == expect2;
+}
+
+#endif
+
+template <class BasePtr>
+bool check_static_moving_pointer_cast(std::function<BasePtr()> f)
+{
+ BasePtr smart = f();
+ base2 *expect = static_cast<base2*>(static_cast<derived*>(boost::get_pointer(smart)));
+
+ return
+ //Cast base -> derived -> base2 using static_pointer_cast
+ boost::get_pointer(
+ boost::static_pointer_cast<base2>(
+ boost::static_pointer_cast<derived>( std::move(smart) ))) ==
+ //Now the same with static_cast
+ expect;
+}
+
+template <class BasePtr>
+bool check_const_moving_pointer_cast(std::function<BasePtr()> f)
+{
+ BasePtr smart = f();
+ const base *expect = const_cast<const base*>(const_cast<base*>(boost::get_pointer(smart)));
+ return
+ //Unconst and const again using const_pointer_cast
+ boost::get_pointer(
+ boost::const_pointer_cast<const base>
+ (boost::const_pointer_cast<base>( std::move(smart) ))) ==
+ //Now the same with const_cast
+ expect;
+}
+
+template <class BasePtr>
+void check_all_moving_casts(std::function<BasePtr()> f) {
+#if !defined( BOOST_NO_RTTI )
+ BOOST_TEST( check_dynamic_moving_pointer_cast( f ) );
+#endif
+ BOOST_TEST( check_static_moving_pointer_cast( f ) );
+ BOOST_TEST( check_const_moving_pointer_cast( f ) );
+}
+
+}
+
+int main()
+{
+
+ std::shared_ptr<base> std_shared(new derived);
+ boost::shared_ptr<base> boost_shared(new derived);
+ base *plain = boost_shared.get();
+
+ // plain & boost::shared_ptr moving pointer_cast checks; there
+ // is no specific handleing for those types at the moment; this
+ // test just makes sure they won't break when std::move() is used
+ // in generic code
+
+ check_all_moving_casts<boost::shared_ptr<base>>([&boost_shared]() {
+ return boost_shared;
+ });
+
+ check_all_moving_casts<base*>([plain]() {
+ return plain;
+ });
+
+ // std::shared_ptr casts
+
+ check_all_copy_casts(std_shared);
+ check_all_moving_casts<std::shared_ptr<base>>([&std_shared]() {
+ return std_shared;
+ });
+
+ // std::unique_ptr casts
+
+ check_all_moving_casts<std::unique_ptr<base>>([]() {
+ return std::unique_ptr<base>(new derived);
+ });
+
+ return boost::report_errors();
+}
+#endif
diff --git a/test/esft_regtest.cpp b/test/esft_regtest.cpp
new file mode 100644
index 0000000..baa5ef2
--- /dev/null
+++ b/test/esft_regtest.cpp
@@ -0,0 +1,226 @@
+//
+// esft_regtest.cpp
+//
+// A regression test for enable_shared_from_this
+//
+// Copyright (c) 2008 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)
+//
+
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/config.hpp>
+#include <memory>
+#include <string>
+
+class X: public boost::enable_shared_from_this< X >
+{
+private:
+
+ int destroyed_;
+ int deleted_;
+ int expected_;
+
+private:
+
+ X( X const& );
+ X& operator=( X const& );
+
+public:
+
+ static int instances;
+
+public:
+
+ explicit X( int expected ): destroyed_( 0 ), deleted_( 0 ), expected_( expected )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ BOOST_TEST( deleted_ == expected_ );
+ BOOST_TEST( destroyed_ == 0 );
+ ++destroyed_;
+ --instances;
+ }
+
+ typedef void (*deleter_type)( X* );
+
+ static void deleter( X * px )
+ {
+ ++px->deleted_;
+ }
+
+ static void deleter2( X * px )
+ {
+ ++px->deleted_;
+ delete px;
+ }
+};
+
+int X::instances = 0;
+
+void test()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ X x( 0 );
+ BOOST_TEST( X::instances == 1 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+#if !defined( BOOST_NO_AUTO_PTR )
+
+ {
+ std::auto_ptr<X> px( new X( 0 ) );
+ BOOST_TEST( X::instances == 1 );
+ }
+
+#endif
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X> px( new X( 0 ) );
+ BOOST_TEST( X::instances == 1 );
+
+ boost::weak_ptr<X> wp( px );
+ BOOST_TEST( !wp.expired() );
+
+ px.reset();
+
+ BOOST_TEST( wp.expired() );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ X x( 1 );
+ boost::shared_ptr<X> px( &x, X::deleter );
+ BOOST_TEST( X::instances == 1 );
+
+ X::deleter_type * pd = boost::get_deleter<X::deleter_type>( px );
+ BOOST_TEST( pd != 0 && *pd == X::deleter );
+
+ boost::weak_ptr<X> wp( px );
+ BOOST_TEST( !wp.expired() );
+
+ px.reset();
+
+ BOOST_TEST( wp.expired() );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X> px( new X( 1 ), X::deleter2 );
+ BOOST_TEST( X::instances == 1 );
+
+ X::deleter_type * pd = boost::get_deleter<X::deleter_type>( px );
+ BOOST_TEST( pd != 0 && *pd == X::deleter2 );
+
+ boost::weak_ptr<X> wp( px );
+ BOOST_TEST( !wp.expired() );
+
+ px.reset();
+
+ BOOST_TEST( wp.expired() );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+struct V: public boost::enable_shared_from_this<V>
+{
+ virtual ~V() {}
+ std::string m_;
+};
+
+struct V2
+{
+ virtual ~V2() {}
+ std::string m2_;
+};
+
+struct W: V2, V
+{
+};
+
+void test2()
+{
+ boost::shared_ptr<W> p( new W );
+}
+
+void test3()
+{
+ V * p = new W;
+ boost::shared_ptr<void> pv( p );
+ BOOST_TEST( pv.get() == p );
+ BOOST_TEST( pv.use_count() == 1 );
+}
+
+struct null_deleter
+{
+ void operator()( void const* ) const {}
+};
+
+void test4()
+{
+ boost::shared_ptr<V> pv( new V );
+ boost::shared_ptr<V> pv2( pv.get(), null_deleter() );
+ BOOST_TEST( pv2.get() == pv.get() );
+ BOOST_TEST( pv2.use_count() == 1 );
+}
+
+void test5()
+{
+ V v;
+
+ boost::shared_ptr<V> p1( &v, null_deleter() );
+ BOOST_TEST( p1.get() == &v );
+ BOOST_TEST( p1.use_count() == 1 );
+
+ try
+ {
+ p1->shared_from_this();
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "p1->shared_from_this() failed" );
+ }
+
+ p1.reset();
+
+ boost::shared_ptr<V> p2( &v, null_deleter() );
+ BOOST_TEST( p2.get() == &v );
+ BOOST_TEST( p2.use_count() == 1 );
+
+ try
+ {
+ p2->shared_from_this();
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "p2->shared_from_this() failed" );
+ }
+}
+
+int main()
+{
+ test();
+ test2();
+ test3();
+ test4();
+ test5();
+
+ return boost::report_errors();
+}
diff --git a/test/esft_second_ptr_test.cpp b/test/esft_second_ptr_test.cpp
new file mode 100644
index 0000000..0600667
--- /dev/null
+++ b/test/esft_second_ptr_test.cpp
@@ -0,0 +1,51 @@
+//
+// esft_second_ptr_test.cpp
+//
+// This test has been extracted from a real
+// scenario that occurs in Boost.Python
+//
+// Copyright 2009 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
+//
+
+
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X: public boost::enable_shared_from_this<X>
+{
+};
+
+void null_deleter( void const* )
+{
+}
+
+int main()
+{
+ boost::shared_ptr<X> px( new X );
+
+ {
+ boost::shared_ptr<X> px2( px.get(), null_deleter );
+ BOOST_TEST( px == px2 );
+ }
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/esft_void_test.cpp b/test/esft_void_test.cpp
new file mode 100644
index 0000000..b28c669
--- /dev/null
+++ b/test/esft_void_test.cpp
@@ -0,0 +1,41 @@
+//
+// esft_void_test.cpp
+//
+// Copyright 2009 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
+//
+
+
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X: public boost::enable_shared_from_this<X>
+{
+};
+
+int main()
+{
+ boost::shared_ptr< void const volatile > pv( new X );
+ boost::shared_ptr< void > pv2 = boost::const_pointer_cast< void >( pv );
+ boost::shared_ptr< X > px = boost::static_pointer_cast< X >( pv2 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/get_deleter_array_test.cpp b/test/get_deleter_array_test.cpp
new file mode 100644
index 0000000..f6d2500
--- /dev/null
+++ b/test/get_deleter_array_test.cpp
@@ -0,0 +1,95 @@
+//
+// get_deleter_array_test.cpp
+//
+// Copyright (c) 2002, 2011 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)
+//
+
+#include <boost/shared_array.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+struct deleter
+{
+ int data;
+
+ deleter(): data(0)
+ {
+ }
+
+ void operator()(void *)
+ {
+ BOOST_TEST(data == 17041);
+ }
+};
+
+struct deleter2
+{
+};
+
+struct X
+{
+};
+
+int main()
+{
+ {
+ boost::shared_array<X> p;
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ boost::shared_array<X> p(new X[1]);
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ X x[1];
+ boost::shared_array<X> p(x, deleter());
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+
+ deleter * q = boost::get_deleter<deleter>(p);
+
+ BOOST_TEST(q != 0);
+ BOOST_TEST(q->data == 0);
+
+ q->data = 17041;
+
+ deleter const * r = boost::get_deleter<deleter const>(p);
+
+ BOOST_TEST(r == q);
+ BOOST_TEST(r->data == 17041);
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/get_deleter_array_test2.cpp b/test/get_deleter_array_test2.cpp
new file mode 100644
index 0000000..473aac2
--- /dev/null
+++ b/test/get_deleter_array_test2.cpp
@@ -0,0 +1,151 @@
+//
+// get_deleter_array_test2.cpp
+//
+// Copyright 2002, 2011, 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)
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+struct deleter
+{
+ int data;
+
+ deleter(): data(0)
+ {
+ }
+
+ void operator()(void *)
+ {
+ BOOST_TEST(data == 17041);
+ }
+};
+
+struct deleter2
+{
+};
+
+struct X
+{
+};
+
+int main()
+{
+ {
+ boost::shared_ptr<X[]> p;
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ boost::shared_ptr<X[1]> p;
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ boost::shared_ptr<X[]> p(new X[1]);
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ boost::shared_ptr<X[1]> p(new X[1]);
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ X x[1];
+ boost::shared_ptr<X[]> p(x, deleter());
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+
+ deleter * q = boost::get_deleter<deleter>(p);
+
+ BOOST_TEST(q != 0);
+ BOOST_TEST(q->data == 0);
+
+ q->data = 17041;
+
+ deleter const * r = boost::get_deleter<deleter const>(p);
+
+ BOOST_TEST(r == q);
+ BOOST_TEST(r->data == 17041);
+ }
+
+ {
+ X x[1];
+ boost::shared_ptr<X[1]> p(x, deleter());
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+
+ deleter * q = boost::get_deleter<deleter>(p);
+
+ BOOST_TEST(q != 0);
+ BOOST_TEST(q->data == 0);
+
+ q->data = 17041;
+
+ deleter const * r = boost::get_deleter<deleter const>(p);
+
+ BOOST_TEST(r == q);
+ BOOST_TEST(r->data == 17041);
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/get_deleter_array_test3.cpp b/test/get_deleter_array_test3.cpp
new file mode 100644
index 0000000..7a33eea
--- /dev/null
+++ b/test/get_deleter_array_test3.cpp
@@ -0,0 +1,62 @@
+//
+// get_deleter_test3.cpp
+//
+// 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)
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+struct deleter
+{
+};
+
+struct deleter2;
+
+struct X
+{
+};
+
+int main()
+{
+ {
+ boost::shared_ptr<X[]> p = boost::make_shared<X[]>( 1 );
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ boost::shared_ptr<X[1]> p = boost::make_shared<X[1]>();
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ return boost::report_errors();
+}
+
+struct deleter2
+{
+};
diff --git a/test/get_deleter_test.cpp b/test/get_deleter_test.cpp
new file mode 100644
index 0000000..8bed379
--- /dev/null
+++ b/test/get_deleter_test.cpp
@@ -0,0 +1,95 @@
+//
+// get_deleter_test.cpp
+//
+// Copyright (c) 2002 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)
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+struct deleter
+{
+ int data;
+
+ deleter(): data(0)
+ {
+ }
+
+ void operator()(void *)
+ {
+ BOOST_TEST(data == 17041);
+ }
+};
+
+struct deleter2
+{
+};
+
+struct X
+{
+};
+
+int main()
+{
+ {
+ boost::shared_ptr<X> p;
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ boost::shared_ptr<X> p(new X);
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ X x;
+ boost::shared_ptr<X> p(&x, deleter());
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+
+ deleter * q = boost::get_deleter<deleter>(p);
+
+ BOOST_TEST(q != 0);
+ BOOST_TEST(q->data == 0);
+
+ q->data = 17041;
+
+ deleter const * r = boost::get_deleter<deleter const>(p);
+
+ BOOST_TEST(r == q);
+ BOOST_TEST(r->data == 17041);
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/get_deleter_test2.cpp b/test/get_deleter_test2.cpp
new file mode 100644
index 0000000..4ddc65e
--- /dev/null
+++ b/test/get_deleter_test2.cpp
@@ -0,0 +1,37 @@
+//
+// get_deleter_test2.cpp
+//
+// 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)
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+struct deleter;
+
+struct X
+{
+};
+
+static void test_get_deleter( boost::shared_ptr<X> const & p )
+{
+ BOOST_TEST( boost::get_deleter<deleter>( p ) != 0 );
+}
+
+struct deleter
+{
+ void operator()( X const * p ) { delete p; }
+};
+
+int main()
+{
+ boost::shared_ptr<X> p( new X, deleter() );
+
+ test_get_deleter( p );
+
+ return boost::report_errors();
+}
diff --git a/test/get_deleter_test3.cpp b/test/get_deleter_test3.cpp
new file mode 100644
index 0000000..c42643b
--- /dev/null
+++ b/test/get_deleter_test3.cpp
@@ -0,0 +1,47 @@
+//
+// get_deleter_test3.cpp
+//
+// 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)
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+struct deleter
+{
+};
+
+struct deleter2;
+
+struct X
+{
+};
+
+int main()
+{
+ {
+ boost::shared_ptr<X> p = boost::make_shared<X>();
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ return boost::report_errors();
+}
+
+struct deleter2
+{
+};
diff --git a/test/get_local_deleter_array_test.cpp b/test/get_local_deleter_array_test.cpp
new file mode 100644
index 0000000..3a8351b
--- /dev/null
+++ b/test/get_local_deleter_array_test.cpp
@@ -0,0 +1,151 @@
+//
+// get_local_deleter_array_test2.cpp
+//
+// Copyright 2002, 2011, 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)
+//
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+struct deleter
+{
+ int data;
+
+ deleter(): data(0)
+ {
+ }
+
+ void operator()(void *)
+ {
+ BOOST_TEST(data == 17041);
+ }
+};
+
+struct deleter2
+{
+};
+
+struct X
+{
+};
+
+int main()
+{
+ {
+ boost::local_shared_ptr<X[]> p;
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ boost::local_shared_ptr<X[1]> p;
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ boost::local_shared_ptr<X[]> p(new X[1]);
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ boost::local_shared_ptr<X[1]> p(new X[1]);
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ X x[1];
+ boost::local_shared_ptr<X[]> p(x, deleter());
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+
+ deleter * q = boost::get_deleter<deleter>(p);
+
+ BOOST_TEST(q != 0);
+ BOOST_TEST(q->data == 0);
+
+ q->data = 17041;
+
+ deleter const * r = boost::get_deleter<deleter const>(p);
+
+ BOOST_TEST(r == q);
+ BOOST_TEST(r->data == 17041);
+ }
+
+ {
+ X x[1];
+ boost::local_shared_ptr<X[1]> p(x, deleter());
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+
+ deleter * q = boost::get_deleter<deleter>(p);
+
+ BOOST_TEST(q != 0);
+ BOOST_TEST(q->data == 0);
+
+ q->data = 17041;
+
+ deleter const * r = boost::get_deleter<deleter const>(p);
+
+ BOOST_TEST(r == q);
+ BOOST_TEST(r->data == 17041);
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/get_local_deleter_array_test2.cpp b/test/get_local_deleter_array_test2.cpp
new file mode 100644
index 0000000..999fffe
--- /dev/null
+++ b/test/get_local_deleter_array_test2.cpp
@@ -0,0 +1,74 @@
+//
+// get_local_deleter_test2.cpp
+//
+// 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)
+//
+
+#include <boost/config.hpp>
+
+#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) || defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES )
+
+int main()
+{
+}
+
+#else
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+struct deleter
+{
+};
+
+struct deleter2;
+
+struct X
+{
+};
+
+int main()
+{
+ {
+ boost::local_shared_ptr<X[]> p = boost::make_local_shared<X[]>( 1 );
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ boost::local_shared_ptr<X[1]> p = boost::make_local_shared<X[1]>();
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ return boost::report_errors();
+}
+
+struct deleter2
+{
+};
+
+#endif
diff --git a/test/get_local_deleter_test.cpp b/test/get_local_deleter_test.cpp
new file mode 100644
index 0000000..8c45af7
--- /dev/null
+++ b/test/get_local_deleter_test.cpp
@@ -0,0 +1,95 @@
+//
+// get_local_deleter_test.cpp
+//
+// 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)
+//
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+struct deleter
+{
+ int data;
+
+ deleter(): data(0)
+ {
+ }
+
+ void operator()(void *)
+ {
+ BOOST_TEST(data == 17041);
+ }
+};
+
+struct deleter2
+{
+};
+
+struct X
+{
+};
+
+int main()
+{
+ {
+ boost::local_shared_ptr<X> p;
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ boost::local_shared_ptr<X> p(new X);
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ {
+ X x;
+ boost::local_shared_ptr<X> p(&x, deleter());
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+
+ deleter * q = boost::get_deleter<deleter>(p);
+
+ BOOST_TEST(q != 0);
+ BOOST_TEST(q->data == 0);
+
+ q->data = 17041;
+
+ deleter const * r = boost::get_deleter<deleter const>(p);
+
+ BOOST_TEST(r == q);
+ BOOST_TEST(r->data == 17041);
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/get_local_deleter_test2.cpp b/test/get_local_deleter_test2.cpp
new file mode 100644
index 0000000..a0023a9
--- /dev/null
+++ b/test/get_local_deleter_test2.cpp
@@ -0,0 +1,43 @@
+//
+// get_local_deleter_test2.cpp
+//
+// 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)
+//
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+struct deleter;
+
+struct X
+{
+};
+
+static void test_lsp_get_deleter( boost::local_shared_ptr<X> const & p )
+{
+ BOOST_TEST( boost::get_deleter<deleter>( p ) != 0 );
+}
+
+static void test_sp_get_deleter( boost::shared_ptr<X> const & p )
+{
+ BOOST_TEST( boost::get_deleter<deleter>( p ) != 0 );
+}
+
+struct deleter
+{
+ void operator()( X const * p ) { delete p; }
+};
+
+int main()
+{
+ boost::local_shared_ptr<X> p( new X, deleter() );
+
+ test_lsp_get_deleter( p );
+ test_sp_get_deleter( p );
+
+ return boost::report_errors();
+}
diff --git a/test/get_local_deleter_test3.cpp b/test/get_local_deleter_test3.cpp
new file mode 100644
index 0000000..655c7fc
--- /dev/null
+++ b/test/get_local_deleter_test3.cpp
@@ -0,0 +1,59 @@
+//
+// get_local_deleter_test3.cpp
+//
+// 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)
+//
+
+#include <boost/config.hpp>
+
+#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) || defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES )
+
+int main()
+{
+}
+
+#else
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+struct deleter
+{
+};
+
+struct deleter2;
+
+struct X
+{
+};
+
+int main()
+{
+ {
+ boost::local_shared_ptr<X> p = boost::make_local_shared<X>();
+
+ BOOST_TEST(boost::get_deleter<void>(p) == 0);
+ BOOST_TEST(boost::get_deleter<void const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int>(p) == 0);
+ BOOST_TEST(boost::get_deleter<int const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X>(p) == 0);
+ BOOST_TEST(boost::get_deleter<X const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
+ BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
+ }
+
+ return boost::report_errors();
+}
+
+struct deleter2
+{
+};
+
+#endif
diff --git a/test/intrusive_ptr_move_test.cpp b/test/intrusive_ptr_move_test.cpp
new file mode 100644
index 0000000..2f2f652
--- /dev/null
+++ b/test/intrusive_ptr_move_test.cpp
@@ -0,0 +1,222 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#pragma warning(disable: 4355) // 'this' : used in base member initializer list
+#pragma warning(disable: 4511) // copy constructor could not be generated
+#pragma warning(disable: 4512) // assignment operator could not be generated
+
+#if (BOOST_MSVC >= 1310)
+#pragma warning(disable: 4675) // resolved overload found with Koenig lookup
+#endif
+
+#endif
+
+//
+// intrusive_ptr_move_test.cpp
+//
+// Copyright (c) 2002-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/detail/atomic_count.hpp>
+#include <boost/config.hpp>
+#include <utility>
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+namespace N
+{
+
+class base
+{
+private:
+
+ boost::detail::atomic_count use_count_;
+
+ base(base const &);
+ base & operator=(base const &);
+
+protected:
+
+ base(): use_count_(0)
+ {
+ ++instances;
+ }
+
+ virtual ~base()
+ {
+ --instances;
+ }
+
+public:
+
+ static long instances;
+
+ long use_count() const
+ {
+ return use_count_;
+ }
+
+#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+
+ inline friend void intrusive_ptr_add_ref(base * p)
+ {
+ ++p->use_count_;
+ }
+
+ inline friend void intrusive_ptr_release(base * p)
+ {
+ if(--p->use_count_ == 0) delete p;
+ }
+
+#else
+
+ void add_ref()
+ {
+ ++use_count_;
+ }
+
+ void release()
+ {
+ if(--use_count_ == 0) delete this;
+ }
+
+#endif
+};
+
+long base::instances = 0;
+
+} // namespace N
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+
+namespace boost
+{
+
+inline void intrusive_ptr_add_ref(N::base * p)
+{
+ p->add_ref();
+}
+
+inline void intrusive_ptr_release(N::base * p)
+{
+ p->release();
+}
+
+} // namespace boost
+
+#endif
+
+//
+
+struct X: public virtual N::base
+{
+};
+
+struct Y: public X
+{
+};
+
+int main()
+{
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ boost::intrusive_ptr<X> p( new X );
+ BOOST_TEST( N::base::instances == 1 );
+
+ boost::intrusive_ptr<X> p2( std::move( p ) );
+ BOOST_TEST( N::base::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ p2.reset();
+ BOOST_TEST( N::base::instances == 0 );
+ }
+
+ {
+ boost::intrusive_ptr<Y> p( new Y );
+ BOOST_TEST( N::base::instances == 1 );
+
+ boost::intrusive_ptr<X> p2( std::move( p ) );
+ BOOST_TEST( N::base::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ p2.reset();
+ BOOST_TEST( N::base::instances == 0 );
+ }
+
+ {
+ boost::intrusive_ptr<X> p( new X );
+ BOOST_TEST( N::base::instances == 1 );
+
+ boost::intrusive_ptr<X> p2;
+ p2 = std::move( p );
+ BOOST_TEST( N::base::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ p2.reset();
+ BOOST_TEST( N::base::instances == 0 );
+ }
+
+ {
+ boost::intrusive_ptr<X> p( new X );
+ BOOST_TEST( N::base::instances == 1 );
+
+ boost::intrusive_ptr<X> p2( new X );
+ BOOST_TEST( N::base::instances == 2 );
+ p2 = std::move( p );
+ BOOST_TEST( N::base::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ p2.reset();
+ BOOST_TEST( N::base::instances == 0 );
+ }
+
+ {
+ boost::intrusive_ptr<Y> p( new Y );
+ BOOST_TEST( N::base::instances == 1 );
+
+ boost::intrusive_ptr<X> p2;
+ p2 = std::move( p );
+ BOOST_TEST( N::base::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ p2.reset();
+ BOOST_TEST( N::base::instances == 0 );
+ }
+
+ {
+ boost::intrusive_ptr<Y> p( new Y );
+ BOOST_TEST( N::base::instances == 1 );
+
+ boost::intrusive_ptr<X> p2( new X );
+ BOOST_TEST( N::base::instances == 2 );
+ p2 = std::move( p );
+ BOOST_TEST( N::base::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ p2.reset();
+ BOOST_TEST( N::base::instances == 0 );
+ }
+
+ return boost::report_errors();
+}
+
+#else // defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+int main()
+{
+ return 0;
+}
+
+#endif
diff --git a/test/intrusive_ptr_test.cpp b/test/intrusive_ptr_test.cpp
new file mode 100644
index 0000000..b46ddf30
--- /dev/null
+++ b/test/intrusive_ptr_test.cpp
@@ -0,0 +1,788 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#pragma warning(disable: 4355) // 'this' : used in base member initializer list
+#pragma warning(disable: 4511) // copy constructor could not be generated
+#pragma warning(disable: 4512) // assignment operator could not be generated
+
+#if (BOOST_MSVC >= 1310)
+#pragma warning(disable: 4675) // resolved overload found with Koenig lookup
+#endif
+
+#endif
+
+//
+// intrusive_ptr_test.cpp
+//
+// Copyright (c) 2002-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/detail/atomic_count.hpp>
+#include <boost/config.hpp>
+#include <algorithm>
+#include <functional>
+
+//
+
+namespace N
+{
+
+class base
+{
+private:
+
+ boost::detail::atomic_count use_count_;
+
+ base(base const &);
+ base & operator=(base const &);
+
+protected:
+
+ base(): use_count_(0)
+ {
+ ++instances;
+ }
+
+ virtual ~base()
+ {
+ --instances;
+ }
+
+public:
+
+ static long instances;
+
+ long use_count() const
+ {
+ return use_count_;
+ }
+
+#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+
+ inline friend void intrusive_ptr_add_ref(base * p)
+ {
+ ++p->use_count_;
+ }
+
+ inline friend void intrusive_ptr_release(base * p)
+ {
+ if(--p->use_count_ == 0) delete p;
+ }
+
+#else
+
+ void add_ref()
+ {
+ ++use_count_;
+ }
+
+ void release()
+ {
+ if(--use_count_ == 0) delete this;
+ }
+
+#endif
+};
+
+long base::instances = 0;
+
+} // namespace N
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+
+namespace boost
+{
+
+inline void intrusive_ptr_add_ref(N::base * p)
+{
+ p->add_ref();
+}
+
+inline void intrusive_ptr_release(N::base * p)
+{
+ p->release();
+}
+
+} // namespace boost
+
+#endif
+
+//
+
+struct X: public virtual N::base
+{
+};
+
+struct Y: public X
+{
+};
+
+//
+
+namespace n_element_type
+{
+
+void f(X &)
+{
+}
+
+void test()
+{
+ typedef boost::intrusive_ptr<X>::element_type T;
+ T t;
+ f(t);
+}
+
+} // namespace n_element_type
+
+namespace n_constructors
+{
+
+void default_constructor()
+{
+ boost::intrusive_ptr<X> px;
+ BOOST_TEST(px.get() == 0);
+}
+
+void pointer_constructor()
+{
+ {
+ boost::intrusive_ptr<X> px(0);
+ BOOST_TEST(px.get() == 0);
+ }
+
+ {
+ boost::intrusive_ptr<X> px(0, false);
+ BOOST_TEST(px.get() == 0);
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ X * p = new X;
+ BOOST_TEST(p->use_count() == 0);
+
+ BOOST_TEST( N::base::instances == 1 );
+
+ boost::intrusive_ptr<X> px(p);
+ BOOST_TEST(px.get() == p);
+ BOOST_TEST(px->use_count() == 1);
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ X * p = new X;
+ BOOST_TEST(p->use_count() == 0);
+
+ BOOST_TEST( N::base::instances == 1 );
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+ using boost::intrusive_ptr_add_ref;
+#endif
+ intrusive_ptr_add_ref(p);
+ BOOST_TEST(p->use_count() == 1);
+
+ boost::intrusive_ptr<X> px(p, false);
+ BOOST_TEST(px.get() == p);
+ BOOST_TEST(px->use_count() == 1);
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+}
+
+void copy_constructor()
+{
+ {
+ boost::intrusive_ptr<X> px;
+ boost::intrusive_ptr<X> px2(px);
+ BOOST_TEST(px2.get() == px.get());
+ }
+
+ {
+ boost::intrusive_ptr<Y> py;
+ boost::intrusive_ptr<X> px(py);
+ BOOST_TEST(px.get() == py.get());
+ }
+
+ {
+ boost::intrusive_ptr<X> px(0);
+ boost::intrusive_ptr<X> px2(px);
+ BOOST_TEST(px2.get() == px.get());
+ }
+
+ {
+ boost::intrusive_ptr<Y> py(0);
+ boost::intrusive_ptr<X> px(py);
+ BOOST_TEST(px.get() == py.get());
+ }
+
+ {
+ boost::intrusive_ptr<X> px(0, false);
+ boost::intrusive_ptr<X> px2(px);
+ BOOST_TEST(px2.get() == px.get());
+ }
+
+ {
+ boost::intrusive_ptr<Y> py(0, false);
+ boost::intrusive_ptr<X> px(py);
+ BOOST_TEST(px.get() == py.get());
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ boost::intrusive_ptr<X> px(new X);
+ boost::intrusive_ptr<X> px2(px);
+ BOOST_TEST( px2.get() == px.get() );
+
+ BOOST_TEST( N::base::instances == 1 );
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ boost::intrusive_ptr<Y> py(new Y);
+ boost::intrusive_ptr<X> px(py);
+ BOOST_TEST( px.get() == py.get() );
+
+ BOOST_TEST( N::base::instances == 1 );
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+}
+
+void test()
+{
+ default_constructor();
+ pointer_constructor();
+ copy_constructor();
+}
+
+} // namespace n_constructors
+
+namespace n_destructor
+{
+
+void test()
+{
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ boost::intrusive_ptr<X> px(new X);
+ BOOST_TEST(px->use_count() == 1);
+
+ BOOST_TEST( N::base::instances == 1 );
+
+ {
+ boost::intrusive_ptr<X> px2(px);
+ BOOST_TEST(px->use_count() == 2);
+ }
+
+ BOOST_TEST(px->use_count() == 1);
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+}
+
+} // namespace n_destructor
+
+namespace n_assignment
+{
+
+void copy_assignment()
+{
+}
+
+void conversion_assignment()
+{
+}
+
+void pointer_assignment()
+{
+}
+
+void test()
+{
+ copy_assignment();
+ conversion_assignment();
+ pointer_assignment();
+}
+
+} // namespace n_assignment
+
+namespace n_reset
+{
+
+void test()
+{
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ boost::intrusive_ptr<X> px;
+ BOOST_TEST( px.get() == 0 );
+
+ px.reset();
+ BOOST_TEST( px.get() == 0 );
+
+ X * p = new X;
+ BOOST_TEST( p->use_count() == 0 );
+ BOOST_TEST( N::base::instances == 1 );
+
+ px.reset( p );
+ BOOST_TEST( px.get() == p );
+ BOOST_TEST( px->use_count() == 1 );
+
+ px.reset();
+ BOOST_TEST( px.get() == 0 );
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ boost::intrusive_ptr<X> px( new X );
+ BOOST_TEST( N::base::instances == 1 );
+
+ px.reset( 0 );
+ BOOST_TEST( px.get() == 0 );
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ boost::intrusive_ptr<X> px( new X );
+ BOOST_TEST( N::base::instances == 1 );
+
+ px.reset( 0, false );
+ BOOST_TEST( px.get() == 0 );
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ boost::intrusive_ptr<X> px( new X );
+ BOOST_TEST( N::base::instances == 1 );
+
+ px.reset( 0, true );
+ BOOST_TEST( px.get() == 0 );
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ X * p = new X;
+ BOOST_TEST( p->use_count() == 0 );
+
+ BOOST_TEST( N::base::instances == 1 );
+
+ boost::intrusive_ptr<X> px;
+ BOOST_TEST( px.get() == 0 );
+
+ px.reset( p, true );
+ BOOST_TEST( px.get() == p );
+ BOOST_TEST( px->use_count() == 1 );
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ X * p = new X;
+ BOOST_TEST( p->use_count() == 0 );
+
+ BOOST_TEST( N::base::instances == 1 );
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+ using boost::intrusive_ptr_add_ref;
+#endif
+ intrusive_ptr_add_ref( p );
+ BOOST_TEST( p->use_count() == 1 );
+
+ boost::intrusive_ptr<X> px;
+ BOOST_TEST( px.get() == 0 );
+
+ px.reset( p, false );
+ BOOST_TEST( px.get() == p );
+ BOOST_TEST( px->use_count() == 1 );
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ boost::intrusive_ptr<X> px( new X );
+ BOOST_TEST( px.get() != 0 );
+ BOOST_TEST( px->use_count() == 1 );
+
+ BOOST_TEST( N::base::instances == 1 );
+
+ X * p = new X;
+ BOOST_TEST( p->use_count() == 0 );
+
+ BOOST_TEST( N::base::instances == 2 );
+
+ px.reset( p );
+ BOOST_TEST( px.get() == p );
+ BOOST_TEST( px->use_count() == 1 );
+
+ BOOST_TEST( N::base::instances == 1 );
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ boost::intrusive_ptr<X> px( new X );
+ BOOST_TEST( px.get() != 0 );
+ BOOST_TEST( px->use_count() == 1 );
+
+ BOOST_TEST( N::base::instances == 1 );
+
+ X * p = new X;
+ BOOST_TEST( p->use_count() == 0 );
+
+ BOOST_TEST( N::base::instances == 2 );
+
+ px.reset( p, true );
+ BOOST_TEST( px.get() == p );
+ BOOST_TEST( px->use_count() == 1 );
+
+ BOOST_TEST( N::base::instances == 1 );
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+
+ {
+ boost::intrusive_ptr<X> px( new X );
+ BOOST_TEST( px.get() != 0 );
+ BOOST_TEST( px->use_count() == 1 );
+
+ BOOST_TEST( N::base::instances == 1 );
+
+ X * p = new X;
+ BOOST_TEST( p->use_count() == 0 );
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+ using boost::intrusive_ptr_add_ref;
+#endif
+ intrusive_ptr_add_ref( p );
+ BOOST_TEST( p->use_count() == 1 );
+
+ BOOST_TEST( N::base::instances == 2 );
+
+ px.reset( p, false );
+ BOOST_TEST( px.get() == p );
+ BOOST_TEST( px->use_count() == 1 );
+
+ BOOST_TEST( N::base::instances == 1 );
+ }
+
+ BOOST_TEST( N::base::instances == 0 );
+}
+
+} // namespace n_reset
+
+namespace n_access
+{
+
+void test()
+{
+ {
+ boost::intrusive_ptr<X> px;
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+ using boost::get_pointer;
+#endif
+
+ BOOST_TEST(get_pointer(px) == px.get());
+ }
+
+ {
+ boost::intrusive_ptr<X> px(0);
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+ using boost::get_pointer;
+#endif
+
+ BOOST_TEST(get_pointer(px) == px.get());
+ }
+
+ {
+ boost::intrusive_ptr<X> px(new X);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(&*px == px.get());
+ BOOST_TEST(px.operator ->() == px.get());
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+ using boost::get_pointer;
+#endif
+
+ BOOST_TEST(get_pointer(px) == px.get());
+ }
+
+ {
+ boost::intrusive_ptr<X> px;
+ X* detached = px.detach();
+ BOOST_TEST( px.get() == 0 );
+ BOOST_TEST( detached == 0 );
+ }
+
+ {
+ X * p = new X;
+ BOOST_TEST( p->use_count() == 0 );
+
+ boost::intrusive_ptr<X> px( p );
+ BOOST_TEST( px.get() == p );
+ BOOST_TEST( px->use_count() == 1 );
+
+ X * detached = px.detach();
+ BOOST_TEST( px.get() == 0 );
+
+ BOOST_TEST( detached == p );
+ BOOST_TEST( detached->use_count() == 1 );
+
+ delete detached;
+ }
+}
+
+} // namespace n_access
+
+namespace n_swap
+{
+
+void test()
+{
+ {
+ boost::intrusive_ptr<X> px;
+ boost::intrusive_ptr<X> px2;
+
+ px.swap(px2);
+
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px2.get() == 0);
+
+ using std::swap;
+ swap(px, px2);
+
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px2.get() == 0);
+ }
+
+ {
+ X * p = new X;
+ boost::intrusive_ptr<X> px;
+ boost::intrusive_ptr<X> px2(p);
+ boost::intrusive_ptr<X> px3(px2);
+
+ px.swap(px2);
+
+ BOOST_TEST(px.get() == p);
+ BOOST_TEST(px->use_count() == 2);
+ BOOST_TEST(px2.get() == 0);
+ BOOST_TEST(px3.get() == p);
+ BOOST_TEST(px3->use_count() == 2);
+
+ using std::swap;
+ swap(px, px2);
+
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px2.get() == p);
+ BOOST_TEST(px2->use_count() == 2);
+ BOOST_TEST(px3.get() == p);
+ BOOST_TEST(px3->use_count() == 2);
+ }
+
+ {
+ X * p1 = new X;
+ X * p2 = new X;
+ boost::intrusive_ptr<X> px(p1);
+ boost::intrusive_ptr<X> px2(p2);
+ boost::intrusive_ptr<X> px3(px2);
+
+ px.swap(px2);
+
+ BOOST_TEST(px.get() == p2);
+ BOOST_TEST(px->use_count() == 2);
+ BOOST_TEST(px2.get() == p1);
+ BOOST_TEST(px2->use_count() == 1);
+ BOOST_TEST(px3.get() == p2);
+ BOOST_TEST(px3->use_count() == 2);
+
+ using std::swap;
+ swap(px, px2);
+
+ BOOST_TEST(px.get() == p1);
+ BOOST_TEST(px->use_count() == 1);
+ BOOST_TEST(px2.get() == p2);
+ BOOST_TEST(px2->use_count() == 2);
+ BOOST_TEST(px3.get() == p2);
+ BOOST_TEST(px3->use_count() == 2);
+ }
+}
+
+} // namespace n_swap
+
+namespace n_comparison
+{
+
+template<class T, class U> void test2(boost::intrusive_ptr<T> const & p, boost::intrusive_ptr<U> const & q)
+{
+ BOOST_TEST((p == q) == (p.get() == q.get()));
+ BOOST_TEST((p != q) == (p.get() != q.get()));
+}
+
+template<class T> void test3(boost::intrusive_ptr<T> const & p, boost::intrusive_ptr<T> const & q)
+{
+ BOOST_TEST((p == q) == (p.get() == q.get()));
+ BOOST_TEST((p.get() == q) == (p.get() == q.get()));
+ BOOST_TEST((p == q.get()) == (p.get() == q.get()));
+ BOOST_TEST((p != q) == (p.get() != q.get()));
+ BOOST_TEST((p.get() != q) == (p.get() != q.get()));
+ BOOST_TEST((p != q.get()) == (p.get() != q.get()));
+
+ // 'less' moved here as a g++ 2.9x parse error workaround
+ std::less<T*> less;
+ BOOST_TEST((p < q) == less(p.get(), q.get()));
+}
+
+void test()
+{
+ {
+ boost::intrusive_ptr<X> px;
+ test3(px, px);
+
+ boost::intrusive_ptr<X> px2;
+ test3(px, px2);
+
+ boost::intrusive_ptr<X> px3(px);
+ test3(px3, px3);
+ test3(px, px3);
+ }
+
+ {
+ boost::intrusive_ptr<X> px;
+
+ boost::intrusive_ptr<X> px2(new X);
+ test3(px, px2);
+ test3(px2, px2);
+
+ boost::intrusive_ptr<X> px3(new X);
+ test3(px2, px3);
+
+ boost::intrusive_ptr<X> px4(px2);
+ test3(px2, px4);
+ test3(px4, px4);
+ }
+
+ {
+ boost::intrusive_ptr<X> px(new X);
+
+ boost::intrusive_ptr<Y> py(new Y);
+ test2(px, py);
+
+ boost::intrusive_ptr<X> px2(py);
+ test2(px2, py);
+ test3(px, px2);
+ test3(px2, px2);
+ }
+}
+
+} // namespace n_comparison
+
+namespace n_static_cast
+{
+
+void test()
+{
+}
+
+} // namespace n_static_cast
+
+namespace n_dynamic_cast
+{
+
+void test()
+{
+}
+
+} // namespace n_dynamic_cast
+
+namespace n_transitive
+{
+
+struct X: public N::base
+{
+ boost::intrusive_ptr<X> next;
+};
+
+void test()
+{
+ boost::intrusive_ptr<X> p(new X);
+ p->next = boost::intrusive_ptr<X>(new X);
+ BOOST_TEST(!p->next->next);
+ p = p->next;
+ BOOST_TEST(!p->next);
+}
+
+} // namespace n_transitive
+
+namespace n_report_1
+{
+
+class foo: public N::base
+{
+public:
+
+ foo(): m_self(this)
+ {
+ }
+
+ void suicide()
+ {
+ m_self = 0;
+ }
+
+private:
+
+ boost::intrusive_ptr<foo> m_self;
+};
+
+void test()
+{
+ foo * foo_ptr = new foo;
+ foo_ptr->suicide();
+}
+
+} // namespace n_report_1
+
+int main()
+{
+ n_element_type::test();
+ n_constructors::test();
+ n_destructor::test();
+ n_assignment::test();
+ n_reset::test();
+ n_access::test();
+ n_swap::test();
+ n_comparison::test();
+ n_static_cast::test();
+ n_dynamic_cast::test();
+
+ n_transitive::test();
+ n_report_1::test();
+
+ return boost::report_errors();
+}
diff --git a/test/intrusive_ref_counter_test.cpp b/test/intrusive_ref_counter_test.cpp
new file mode 100644
index 0000000..53d0bd3
--- /dev/null
+++ b/test/intrusive_ref_counter_test.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright Andrey Semashev 2013.
+ * 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)
+ */
+/*!
+ * \file intrusive_ref_counter_test.cpp
+ * \author Andrey Semashev
+ * \date 31.08.2013
+ *
+ * This file contains tests for the \c intrusive_ref_counter base class.
+ */
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#pragma warning(disable: 4355) // 'this' : used in base member initializer list
+#pragma warning(disable: 4511) // copy constructor could not be generated
+#pragma warning(disable: 4512) // assignment operator could not be generated
+
+#if (BOOST_MSVC >= 1310)
+#pragma warning(disable: 4675) // resolved overload found with Koenig lookup
+#endif
+
+#endif
+
+#include <cstddef>
+#include <boost/smart_ptr/intrusive_ref_counter.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+namespace N1 {
+
+class my_class :
+ public boost::intrusive_ref_counter< my_class >
+{
+public:
+ static unsigned int destructor_count;
+
+ ~my_class()
+ {
+ ++destructor_count;
+ }
+};
+
+unsigned int my_class::destructor_count = 0;
+
+} // namespace N1
+
+namespace N2 {
+
+class my_class :
+ public boost::intrusive_ref_counter< my_class, boost::thread_unsafe_counter >
+{
+public:
+ static unsigned int destructor_count;
+
+ ~my_class()
+ {
+ ++destructor_count;
+ }
+};
+
+unsigned int my_class::destructor_count = 0;
+
+} // namespace N2
+
+namespace N3 {
+
+struct root :
+ public boost::intrusive_ref_counter< root >
+{
+ virtual ~root() {}
+};
+
+} // namespace N3
+
+namespace N4 {
+
+struct X :
+ public virtual N3::root
+{
+};
+
+} // namespace N4
+
+namespace N5 {
+
+struct Y :
+ public virtual N3::root
+{
+};
+
+} // namespace N5
+
+namespace N6 {
+
+struct Z :
+ public N4::X,
+ public N5::Y
+{
+ static unsigned int destructor_count;
+
+ ~Z()
+ {
+ ++destructor_count;
+ }
+};
+
+unsigned int Z::destructor_count = 0;
+
+} // namespace N6
+
+
+int main()
+{
+ // The test check that ADL works
+ {
+ boost::intrusive_ptr< N1::my_class > p = new N1::my_class();
+ p = NULL;
+ BOOST_TEST(N1::my_class::destructor_count == 1);
+ }
+ {
+ boost::intrusive_ptr< N2::my_class > p = new N2::my_class();
+ p = NULL;
+ BOOST_TEST(N2::my_class::destructor_count == 1);
+ }
+ {
+ N1::my_class* p = new N1::my_class();
+ intrusive_ptr_add_ref(p);
+ intrusive_ptr_release(p);
+ BOOST_TEST(N1::my_class::destructor_count == 2);
+ }
+
+ // The test checks that destroying through the base class works
+ {
+ boost::intrusive_ptr< N6::Z > p1 = new N6::Z();
+ BOOST_TEST(p1->use_count() == 1);
+ BOOST_TEST(N6::Z::destructor_count == 0);
+ boost::intrusive_ptr< N3::root > p2 = p1;
+ BOOST_TEST(p1->use_count() == 2);
+ BOOST_TEST(N6::Z::destructor_count == 0);
+ p1 = NULL;
+ BOOST_TEST(N6::Z::destructor_count == 0);
+ p2 = NULL;
+ BOOST_TEST(N6::Z::destructor_count == 1);
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/ip_convertible_test.cpp b/test/ip_convertible_test.cpp
new file mode 100644
index 0000000..081f7b0
--- /dev/null
+++ b/test/ip_convertible_test.cpp
@@ -0,0 +1,54 @@
+#include <boost/config.hpp>
+
+// wp_convertible_test.cpp
+//
+// Copyright (c) 2008 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+//
+
+struct W
+{
+};
+
+void intrusive_ptr_add_ref( W* )
+{
+}
+
+void intrusive_ptr_release( W* )
+{
+}
+
+struct X: public virtual W
+{
+};
+
+struct Y: public virtual W
+{
+};
+
+struct Z: public X
+{
+};
+
+int f( boost::intrusive_ptr<X> )
+{
+ return 1;
+}
+
+int f( boost::intrusive_ptr<Y> )
+{
+ return 2;
+}
+
+int main()
+{
+ BOOST_TEST( 1 == f( boost::intrusive_ptr<Z>() ) );
+ return boost::report_errors();
+}
diff --git a/test/ip_hash_test.cpp b/test/ip_hash_test.cpp
new file mode 100644
index 0000000..be38b3d
--- /dev/null
+++ b/test/ip_hash_test.cpp
@@ -0,0 +1,75 @@
+//
+// ip_hash_test.cpp
+//
+// Copyright 2011 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
+//
+
+#include <boost/intrusive_ptr.hpp>
+#include <boost/functional/hash.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+class base
+{
+private:
+
+ int use_count_;
+
+ base(base const &);
+ base & operator=(base const &);
+
+protected:
+
+ base(): use_count_(0)
+ {
+ }
+
+ virtual ~base()
+ {
+ }
+
+public:
+
+ long use_count() const
+ {
+ return use_count_;
+ }
+
+ inline friend void intrusive_ptr_add_ref(base * p)
+ {
+ ++p->use_count_;
+ }
+
+ inline friend void intrusive_ptr_release(base * p)
+ {
+ if(--p->use_count_ == 0) delete p;
+ }
+};
+
+struct X: public base
+{
+};
+
+int main()
+{
+ boost::hash< boost::intrusive_ptr<X> > hasher;
+
+ boost::intrusive_ptr<X> p1, p2( p1 ), p3( new X ), p4( p3 ), p5( new X );
+
+ BOOST_TEST_EQ( p1, p2 );
+ BOOST_TEST_EQ( hasher( p1 ), hasher( p2 ) );
+
+ BOOST_TEST_NE( p1, p3 );
+ BOOST_TEST_NE( hasher( p1 ), hasher( p3 ) );
+
+ BOOST_TEST_EQ( p3, p4 );
+ BOOST_TEST_EQ( hasher( p3 ), hasher( p4 ) );
+
+ BOOST_TEST_NE( p3, p5 );
+ BOOST_TEST_NE( hasher( p3 ), hasher( p5 ) );
+
+ return boost::report_errors();
+}
diff --git a/test/local_sp_fn_test.cpp b/test/local_sp_fn_test.cpp
new file mode 100644
index 0000000..f2a355a
--- /dev/null
+++ b/test/local_sp_fn_test.cpp
@@ -0,0 +1,43 @@
+//
+// local_sp_fn_test.cpp
+//
+// 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
+//
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+static void f()
+{
+}
+
+struct null_deleter
+{
+ template<class Y> void operator()( Y* ) {}
+};
+
+int main()
+{
+ boost::local_shared_ptr<void()> pf( f, null_deleter() );
+
+ BOOST_TEST( pf.get() == f );
+ BOOST_TEST_EQ( pf.local_use_count(), 1 );
+ BOOST_TEST( boost::get_deleter<null_deleter>( pf ) != 0 );
+
+ boost::weak_ptr<void()> wp( pf );
+
+ BOOST_TEST( wp.lock().get() == f );
+ BOOST_TEST_EQ( wp.use_count(), 1 );
+
+ pf.reset();
+
+ BOOST_TEST( wp.lock().get() == 0 );
+ BOOST_TEST_EQ( wp.use_count(), 0 );
+
+ return boost::report_errors();
+}
diff --git a/test/local_sp_test.cpp b/test/local_sp_test.cpp
new file mode 100644
index 0000000..dc0e316
--- /dev/null
+++ b/test/local_sp_test.cpp
@@ -0,0 +1,2531 @@
+//
+// local_sp_test.cpp
+//
+// Copyright 2002, 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
+//
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/smart_ptr/weak_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+struct X
+{
+ static long instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+};
+
+long X::instances = 0;
+
+class incomplete;
+
+// default constructor
+
+static void default_constructor()
+{
+ {
+ boost::local_shared_ptr<int> p;
+
+ BOOST_TEST_EQ( p.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p.local_use_count(), 0 );
+ }
+
+ {
+ boost::local_shared_ptr<void> p;
+
+ BOOST_TEST_EQ( p.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p.local_use_count(), 0 );
+ }
+
+ {
+ boost::local_shared_ptr<incomplete> p;
+
+ BOOST_TEST_EQ( p.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p.local_use_count(), 0 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::local_shared_ptr<X> p;
+
+ BOOST_TEST( X::instances == 0 );
+
+ BOOST_TEST_EQ( p.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p.local_use_count(), 0 );
+ }
+}
+
+// nullptr_constructor
+
+static void nullptr_constructor()
+{
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ {
+ boost::local_shared_ptr<int> p( nullptr );
+
+ BOOST_TEST_EQ( p.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p.local_use_count(), 0 );
+ }
+
+ {
+ boost::local_shared_ptr<void> p( nullptr );
+
+ BOOST_TEST_EQ( p.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p.local_use_count(), 0 );
+ }
+
+ {
+ boost::local_shared_ptr<incomplete> p( nullptr );
+
+ BOOST_TEST_EQ( p.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p.local_use_count(), 0 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::local_shared_ptr<X> p( nullptr );
+
+ BOOST_TEST( X::instances == 0 );
+
+
+ BOOST_TEST_EQ( p.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p.local_use_count(), 0 );
+ }
+
+#endif
+}
+
+// pointer constructor
+
+template<class T, class U> static void pc0_test_()
+{
+ boost::local_shared_ptr<T> p( static_cast<U*>( 0 ) );
+
+ BOOST_TEST( p? false: true );
+ BOOST_TEST( !p );
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.local_use_count() == 1 );
+}
+
+template<class T> static void pc0_test()
+{
+ pc0_test_<T, T>();
+ pc0_test_<T const, T const>();
+ pc0_test_<T volatile, T volatile>();
+ pc0_test_<T const volatile, T const volatile>();
+
+ pc0_test_<T const, T>();
+ pc0_test_<T volatile, T>();
+ pc0_test_<T const volatile, T>();
+
+ pc0_test_<void, T>();
+ pc0_test_<void const, T>();
+ pc0_test_<void volatile, T>();
+ pc0_test_<void const volatile, T>();
+}
+
+template<class T, class U> static void pc1_test_()
+{
+ boost::local_shared_ptr<T> p( new U() );
+
+ BOOST_TEST( p? true: false );
+ BOOST_TEST( !!p );
+ BOOST_TEST( p.get() != 0 );
+ BOOST_TEST( p.local_use_count() == 1 );
+}
+
+template<class T> static void pc1_test()
+{
+ pc1_test_<T, T>();
+ pc1_test_<T const, T const>();
+ pc1_test_<T volatile, T volatile>();
+ pc1_test_<T const volatile, T const volatile>();
+
+ pc1_test_<T const, T>();
+ pc1_test_<T volatile, T>();
+ pc1_test_<T const volatile, T>();
+
+ pc1_test_<void, T>();
+ pc1_test_<void const, T>();
+ pc1_test_<void volatile, T>();
+ pc1_test_<void const volatile, T>();
+}
+
+static void pointer_constructor()
+{
+ pc0_test<int>();
+ pc0_test<X>();
+
+ pc1_test<int>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ pc1_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+// deleter constructor
+
+int m = 0;
+
+void deleter2( int * p )
+{
+ BOOST_TEST( p == &m );
+ ++*p;
+}
+
+template<class T> static void deleter2_test_()
+{
+ {
+ m = 0;
+ boost::local_shared_ptr<T> p( &m, deleter2 );
+
+ BOOST_TEST( p? true: false );
+ BOOST_TEST( !!p );
+ BOOST_TEST( p.get() == &m );
+ BOOST_TEST( p.local_use_count() == 1 );
+ }
+
+ BOOST_TEST( m == 1 );
+}
+
+static void deleter_constructor()
+{
+ deleter2_test_<int>();
+ deleter2_test_<int const>();
+ deleter2_test_<int volatile>();
+ deleter2_test_<int const volatile>();
+
+ deleter2_test_<void>();
+ deleter2_test_<void const>();
+ deleter2_test_<void volatile>();
+ deleter2_test_<void const volatile>();
+}
+
+// nullptr_deleter_constructor
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+void deleter3( boost::detail::sp_nullptr_t )
+{
+ ++m;
+}
+
+template<class T> static void deleter3_test_()
+{
+ {
+ m = 0;
+ boost::local_shared_ptr<T> p( nullptr, deleter3 );
+
+ BOOST_TEST( !p );
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.local_use_count() == 1 );
+ }
+
+ BOOST_TEST( m == 1 );
+}
+
+static void nullptr_deleter_constructor()
+{
+ deleter3_test_<int>();
+ deleter3_test_<int const>();
+ deleter3_test_<int volatile>();
+ deleter3_test_<int const volatile>();
+
+ deleter3_test_<void>();
+ deleter3_test_<void const>();
+ deleter3_test_<void volatile>();
+ deleter3_test_<void const volatile>();
+}
+
+#else
+
+static void nullptr_deleter_constructor()
+{
+}
+
+#endif
+
+// allocator constructor
+
+template<class T> static void allocator_test_()
+{
+ {
+ m = 0;
+ boost::local_shared_ptr<T> p( &m, deleter2, std::allocator<void>() );
+
+ BOOST_TEST( p? true: false );
+ BOOST_TEST( !!p );
+ BOOST_TEST( p.get() == &m );
+ BOOST_TEST( p.local_use_count() == 1 );
+ }
+
+ BOOST_TEST( m == 1 );
+}
+
+static void allocator_constructor()
+{
+ allocator_test_<int>();
+ allocator_test_<int const>();
+ allocator_test_<int volatile>();
+ allocator_test_<int const volatile>();
+
+ allocator_test_<void>();
+ allocator_test_<void const>();
+ allocator_test_<void volatile>();
+ allocator_test_<void const volatile>();
+}
+
+// nullptr_allocator_constructor
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+template<class T> static void allocator3_test_()
+{
+ {
+ m = 0;
+ boost::local_shared_ptr<T> p( nullptr, deleter3, std::allocator<void>() );
+
+ BOOST_TEST( !p );
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.local_use_count() == 1 );
+ }
+
+ BOOST_TEST( m == 1 );
+}
+
+static void nullptr_allocator_constructor()
+{
+ allocator3_test_<int>();
+ allocator3_test_<int const>();
+ allocator3_test_<int volatile>();
+ allocator3_test_<int const volatile>();
+
+ allocator3_test_<void>();
+ allocator3_test_<void const>();
+ allocator3_test_<void volatile>();
+ allocator3_test_<void const volatile>();
+}
+
+#else
+
+static void nullptr_allocator_constructor()
+{
+}
+
+#endif
+
+// copy constructor
+
+template<class T> static void empty_copy_test()
+{
+ boost::local_shared_ptr<T> p1;
+
+ BOOST_TEST_EQ( p1.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p1.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T> p2( p1 );
+
+ BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p2.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T const> p3( p1 );
+
+ BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p3.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void> p4( p1 );
+
+ BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p4.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void const> p5( p3 );
+
+ BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p5.local_use_count(), 0 );
+}
+
+template<class T, class U> static void test_nonempty_copy( boost::local_shared_ptr<U> const & p1 )
+{
+ long k = p1.local_use_count();
+
+ {
+ boost::local_shared_ptr<T> p2( p1 );
+
+ BOOST_TEST( p2.get() == p1.get() );
+ BOOST_TEST( p2.local_use_count() == p1.local_use_count() );
+ BOOST_TEST( p2.local_use_count() == k + 1 );
+ }
+
+ BOOST_TEST( p1.local_use_count() == k );
+}
+
+template<class T> static void null_copy_test()
+{
+ boost::local_shared_ptr<T> p1( static_cast<T*>(0) );
+
+ test_nonempty_copy<T>( p1 );
+ test_nonempty_copy<T const>( p1 );
+ test_nonempty_copy<T volatile>( p1 );
+ test_nonempty_copy<T const volatile>( p1 );
+ test_nonempty_copy<void>( p1 );
+ test_nonempty_copy<void const>( p1 );
+ test_nonempty_copy<void volatile>( p1 );
+ test_nonempty_copy<void const volatile>( p1 );
+}
+
+template<class T> static void new_copy_test()
+{
+ boost::local_shared_ptr<T> p1( new T() );
+
+ test_nonempty_copy<T>( p1 );
+ test_nonempty_copy<T const>( p1 );
+ test_nonempty_copy<T volatile>( p1 );
+ test_nonempty_copy<T const volatile>( p1 );
+ test_nonempty_copy<void>( p1 );
+ test_nonempty_copy<void const>( p1 );
+ test_nonempty_copy<void volatile>( p1 );
+ test_nonempty_copy<void const volatile>( p1 );
+}
+
+static void copy_constructor()
+{
+ empty_copy_test<int>();
+ empty_copy_test<incomplete>();
+ empty_copy_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ null_copy_test<int>();
+ null_copy_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_copy_test<int>();
+ new_copy_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+// move constructor
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+template<class T> static void empty_move_test()
+{
+ boost::local_shared_ptr<T> p2(( boost::local_shared_ptr<T>() ));
+
+ BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p2.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T const> p3(( boost::local_shared_ptr<T>() ));
+
+ BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p3.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void> p4(( boost::local_shared_ptr<T>() ));
+
+ BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p4.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void const> p5( std::move(p3) );
+
+ BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p5.local_use_count(), 0 );
+}
+
+template<class T, class U> static void test_nonempty_move( boost::local_shared_ptr<U> && p1 )
+{
+ U* q = p1.get();
+ long k = p1.local_use_count();
+
+ boost::local_shared_ptr<T> p2( std::move(p1) );
+
+ BOOST_TEST( p2.get() == q );
+ BOOST_TEST( p2.local_use_count() == k );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST( p1.local_use_count() == 0 );
+}
+
+template<class T> static void null_move_test()
+{
+ test_nonempty_move<T>( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move<T const>( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move<T volatile>( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move<T const volatile>( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move<void>( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move<void const>( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move<void volatile>( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move<void const volatile>( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+}
+
+template<class T> static void new_move_test()
+{
+ test_nonempty_move<T>( boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move<T const>( boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move<T volatile>( boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move<T const volatile>( boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move<void>( boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move<void const>( boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move<void volatile>( boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move<void const volatile>( boost::local_shared_ptr<T>( new T() ) );
+}
+
+static void move_constructor()
+{
+ empty_move_test<int>();
+ empty_move_test<incomplete>();
+ empty_move_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ null_move_test<int>();
+ null_move_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_move_test<int>();
+ new_move_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+#else
+
+static void move_constructor()
+{
+}
+
+#endif
+
+// aliasing constructor
+
+template<class T, class U> void test_aliasing_( boost::local_shared_ptr<T> const & p1, U * p2 )
+{
+ boost::local_shared_ptr<U> p3( p1, p2 );
+
+ BOOST_TEST( p3.get() == p2 );
+ BOOST_TEST( p3.local_use_count() == p1.local_use_count() );
+ BOOST_TEST( !p3.owner_before( p1 ) && !p1.owner_before( p3 ) );
+}
+
+template<class T, class U> void test_01_aliasing_()
+{
+ U u;
+ boost::local_shared_ptr<T> p1;
+
+ test_aliasing_( p1, &u );
+}
+
+template<class T, class U> void test_01_aliasing()
+{
+ test_01_aliasing_<T, U>();
+ test_01_aliasing_<T const, U>();
+ test_01_aliasing_<T volatile, U>();
+ test_01_aliasing_<T const volatile, U>();
+
+ test_01_aliasing_<T, U volatile>();
+ test_01_aliasing_<T const, U volatile>();
+ test_01_aliasing_<T volatile, U volatile>();
+ test_01_aliasing_<T const volatile, U volatile>();
+}
+
+template<class T, class U> void test_10_aliasing_()
+{
+ boost::local_shared_ptr<T> p1( new T() );
+ test_aliasing_( p1, static_cast<U*>(0) );
+}
+
+template<class T, class U> void test_10_aliasing()
+{
+ test_10_aliasing_<T, U>();
+ test_10_aliasing_<T const, U>();
+ test_10_aliasing_<T volatile, U>();
+ test_10_aliasing_<T const volatile, U>();
+
+ test_10_aliasing_<T, U const>();
+ test_10_aliasing_<T const, U const>();
+ test_10_aliasing_<T volatile, U const>();
+ test_10_aliasing_<T const volatile, U const>();
+
+ test_10_aliasing_<T, U volatile>();
+ test_10_aliasing_<T const, U volatile>();
+ test_10_aliasing_<T volatile, U volatile>();
+ test_10_aliasing_<T const volatile, U volatile>();
+
+ test_10_aliasing_<T, U const volatile>();
+ test_10_aliasing_<T const, U const volatile>();
+ test_10_aliasing_<T volatile, U const volatile>();
+ test_10_aliasing_<T const volatile, U const volatile>();
+}
+
+template<class T, class U> void test_11_aliasing_()
+{
+ U u;
+ boost::local_shared_ptr<T> p1( new T() );
+
+ test_aliasing_( p1, &u );
+}
+
+template<class T, class U> void test_11_aliasing()
+{
+ test_11_aliasing_<T, U>();
+ test_11_aliasing_<T const, U>();
+ test_11_aliasing_<T volatile, U>();
+ test_11_aliasing_<T const volatile, U>();
+
+ test_11_aliasing_<T, U volatile>();
+ test_11_aliasing_<T const, U volatile>();
+ test_11_aliasing_<T volatile, U volatile>();
+ test_11_aliasing_<T const volatile, U volatile>();
+}
+
+static void aliasing_constructor()
+{
+ test_01_aliasing<int, int>();
+ test_10_aliasing<int, int>();
+ test_11_aliasing<int, int>();
+
+ test_01_aliasing<void, int>();
+
+ test_10_aliasing<int, void>();
+
+ test_10_aliasing<int, incomplete>();
+
+ test_01_aliasing<X, X>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_10_aliasing<X, X>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_11_aliasing<X, X>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_01_aliasing<int, X>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_10_aliasing<int, X>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_11_aliasing<int, X>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_01_aliasing<X, int>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_10_aliasing<X, int>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_11_aliasing<X, int>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_01_aliasing<void, X>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_10_aliasing<X, void>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_10_aliasing<X, incomplete>();
+ BOOST_TEST( X::instances == 0 );
+}
+
+// shared_ptr copy constructor
+
+template<class T> static void empty_shared_ptr_copy_test()
+{
+ boost::shared_ptr<T> p1;
+
+ boost::local_shared_ptr<T> p2( p1 );
+
+ BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p2.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T const> p3( p1 );
+
+ BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p3.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void> p4( p1 );
+
+ BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p4.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void const> p5( p3 );
+
+ BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p5.local_use_count(), 0 );
+}
+
+template<class T, class U> static void test_nonempty_shared_ptr_copy( boost::shared_ptr<U> const & p1 )
+{
+ long k = p1.use_count();
+
+ {
+ boost::local_shared_ptr<T> p2( p1 );
+
+ BOOST_TEST( p2.get() == p1.get() );
+ BOOST_TEST( p2.local_use_count() == 1 );
+
+ BOOST_TEST( p1.use_count() == k + 1 );
+ }
+
+ BOOST_TEST( p1.use_count() == k );
+}
+
+template<class T> static void null_shared_ptr_copy_test()
+{
+ boost::shared_ptr<T> p1( static_cast<T*>(0) );
+
+ test_nonempty_shared_ptr_copy<T>( p1 );
+ test_nonempty_shared_ptr_copy<T const>( p1 );
+ test_nonempty_shared_ptr_copy<T volatile>( p1 );
+ test_nonempty_shared_ptr_copy<T const volatile>( p1 );
+ test_nonempty_shared_ptr_copy<void>( p1 );
+ test_nonempty_shared_ptr_copy<void const>( p1 );
+ test_nonempty_shared_ptr_copy<void volatile>( p1 );
+ test_nonempty_shared_ptr_copy<void const volatile>( p1 );
+}
+
+template<class T> static void new_shared_ptr_copy_test()
+{
+ boost::shared_ptr<T> p1( new T() );
+
+ test_nonempty_shared_ptr_copy<T>( p1 );
+ test_nonempty_shared_ptr_copy<T const>( p1 );
+ test_nonempty_shared_ptr_copy<T volatile>( p1 );
+ test_nonempty_shared_ptr_copy<T const volatile>( p1 );
+ test_nonempty_shared_ptr_copy<void>( p1 );
+ test_nonempty_shared_ptr_copy<void const>( p1 );
+ test_nonempty_shared_ptr_copy<void volatile>( p1 );
+ test_nonempty_shared_ptr_copy<void const volatile>( p1 );
+}
+
+static void shared_ptr_copy_constructor()
+{
+ empty_shared_ptr_copy_test<int>();
+ empty_shared_ptr_copy_test<incomplete>();
+ empty_shared_ptr_copy_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ null_shared_ptr_copy_test<int>();
+ null_shared_ptr_copy_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_shared_ptr_copy_test<int>();
+ new_shared_ptr_copy_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+// shared_ptr_move constructor
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+template<class T> static void empty_shared_ptr_move_test()
+{
+ boost::local_shared_ptr<T> p2(( boost::shared_ptr<T>() ));
+
+ BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p2.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T const> p3(( boost::shared_ptr<T>() ));
+
+ BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p3.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void> p4(( boost::shared_ptr<T>() ));
+
+ BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p4.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void const> p5( std::move(p3) );
+
+ BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p5.local_use_count(), 0 );
+}
+
+template<class T, class U> static void test_nonempty_shared_ptr_move( boost::shared_ptr<U> && p1 )
+{
+ U* q = p1.get();
+
+ boost::local_shared_ptr<T> p2( std::move(p1) );
+
+ BOOST_TEST( p2.get() == q );
+ BOOST_TEST( p2.local_use_count() == 1 );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST( p1.use_count() == 0 );
+}
+
+template<class T> static void null_shared_ptr_move_test()
+{
+ test_nonempty_shared_ptr_move<T>( boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move<T const>( boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move<T volatile>( boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move<T const volatile>( boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move<void>( boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move<void const>( boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move<void volatile>( boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move<void const volatile>( boost::shared_ptr<T>( static_cast<T*>(0) ) );
+}
+
+template<class T> static void new_shared_ptr_move_test()
+{
+ test_nonempty_shared_ptr_move<T>( boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move<T const>( boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move<T volatile>( boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move<T const volatile>( boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move<void>( boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move<void const>( boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move<void volatile>( boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move<void const volatile>( boost::shared_ptr<T>( new T() ) );
+}
+
+static void shared_ptr_move_constructor()
+{
+ empty_shared_ptr_move_test<int>();
+ empty_shared_ptr_move_test<incomplete>();
+ empty_shared_ptr_move_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ null_shared_ptr_move_test<int>();
+ null_shared_ptr_move_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_shared_ptr_move_test<int>();
+ new_shared_ptr_move_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+#else
+
+static void shared_ptr_move_constructor()
+{
+}
+
+#endif
+
+// unique_ptr_constructor
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+template<class T, class U> static void test_null_unique_ptr( std::unique_ptr<U> && p1 )
+{
+ boost::local_shared_ptr<T> p2( std::move( p1 ) );
+
+ BOOST_TEST( p1.get() == 0 );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST( p2.local_use_count() == 0 );
+}
+
+template<class T> static void null_unique_ptr_test()
+{
+ test_null_unique_ptr<T>( std::unique_ptr<T>() );
+
+ test_null_unique_ptr<T const>( std::unique_ptr<T>() );
+ test_null_unique_ptr<T volatile>( std::unique_ptr<T>() );
+ test_null_unique_ptr<T const volatile>( std::unique_ptr<T>() );
+
+ test_null_unique_ptr<T const>( std::unique_ptr<T const>() );
+ test_null_unique_ptr<T volatile>( std::unique_ptr<T volatile>() );
+ test_null_unique_ptr<T const volatile>( std::unique_ptr<T const volatile>() );
+
+ test_null_unique_ptr<void>( std::unique_ptr<T>() );
+
+ test_null_unique_ptr<void const>( std::unique_ptr<T>() );
+ test_null_unique_ptr<void volatile>( std::unique_ptr<T>() );
+ test_null_unique_ptr<void const volatile>( std::unique_ptr<T>() );
+
+ test_null_unique_ptr<void const>( std::unique_ptr<T const>() );
+ test_null_unique_ptr<void volatile>( std::unique_ptr<T volatile>() );
+ test_null_unique_ptr<void const volatile>( std::unique_ptr<T const volatile>() );
+}
+
+template<class T, class U, class D> static void test_nonempty_unique_ptr( std::unique_ptr<U, D> && p1 )
+{
+ U * q = p1.get();
+
+ boost::local_shared_ptr<T> p2( std::move(p1) );
+
+ BOOST_TEST( p2.get() == q );
+ BOOST_TEST( p2.local_use_count() == 1 );
+
+ BOOST_TEST( p1.get() == 0 );
+}
+
+template<class T> static void new_unique_ptr_test()
+{
+ test_nonempty_unique_ptr<T>( std::unique_ptr<T>( new T() ) );
+
+ test_nonempty_unique_ptr<T const>( std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr<T volatile>( std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr<T const volatile>( std::unique_ptr<T>( new T() ) );
+
+ test_nonempty_unique_ptr<T const>( std::unique_ptr<T const>( new T() ) );
+ test_nonempty_unique_ptr<T volatile>( std::unique_ptr<T volatile>( new T() ) );
+ test_nonempty_unique_ptr<T const volatile>( std::unique_ptr<T const volatile>( new T() ) );
+
+ test_nonempty_unique_ptr<void>( std::unique_ptr<T>( new T() ) );
+
+ test_nonempty_unique_ptr<void const>( std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr<void volatile>( std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr<void const volatile>( std::unique_ptr<T>( new T() ) );
+
+ test_nonempty_unique_ptr<void const>( std::unique_ptr<T const>( new T() ) );
+ test_nonempty_unique_ptr<void volatile>( std::unique_ptr<T volatile>( new T() ) );
+ test_nonempty_unique_ptr<void const volatile>( std::unique_ptr<T const volatile>( new T() ) );
+}
+
+template<class T> static void test_deleter_unique_ptr()
+{
+ m = 0;
+
+ test_nonempty_unique_ptr<T>( std::unique_ptr<int, void(*)(int*)>( &m, deleter2 ) );
+
+ BOOST_TEST( m == 1 );
+}
+
+template<class T> static void deleter_unique_ptr_test()
+{
+ test_deleter_unique_ptr<T>();
+ test_deleter_unique_ptr<T const>();
+ test_deleter_unique_ptr<T volatile>();
+ test_deleter_unique_ptr<T const volatile>();
+}
+
+static void unique_ptr_constructor()
+{
+ null_unique_ptr_test<int>();
+ null_unique_ptr_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_unique_ptr_test<int>();
+ new_unique_ptr_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ deleter_unique_ptr_test<int>();
+ deleter_unique_ptr_test<void>();
+}
+
+#else
+
+static void unique_ptr_constructor()
+{
+}
+
+#endif
+
+// copy assignment
+
+template<class T> static void empty_copy_assign_test()
+{
+ boost::local_shared_ptr<T> p1;
+
+ BOOST_TEST_EQ( p1.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p1.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T> p2;
+
+ p2 = p1;
+
+ BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p2.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T const> p3;
+
+ p3 = p1;
+
+ BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p3.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void> p4;
+
+ p4 = p1;
+
+ BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p4.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void const> p5;
+
+ p5 = p3;
+
+ BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p5.local_use_count(), 0 );
+}
+
+template<class T> static void empty_copy_assign_test_()
+{
+ boost::local_shared_ptr<T> p1;
+
+ BOOST_TEST_EQ( p1.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p1.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T> p2( static_cast<T*>(0) );
+
+ p2 = p1;
+
+ BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p2.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T const> p3( static_cast<T const*>(0) );
+
+ p3 = p1;
+
+ BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p3.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void> p4( static_cast<T*>(0) );
+
+ p4 = p1;
+
+ BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p4.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void const> p5( static_cast<T const*>(0) );
+
+ p5 = p3;
+
+ BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p5.local_use_count(), 0 );
+}
+
+template<class T, class U> static void test_nonempty_copy_assign( boost::local_shared_ptr<T> p2, boost::local_shared_ptr<U> const & p1 )
+{
+ long k = p1.local_use_count();
+
+ p2 = p1;
+
+ BOOST_TEST( p2.get() == p1.get() );
+ BOOST_TEST( p2.local_use_count() == p1.local_use_count() );
+ BOOST_TEST( p2.local_use_count() == k + 1 );
+
+ p2.reset();
+
+ BOOST_TEST( p1.local_use_count() == k );
+}
+
+template<class T> static void null_copy_assign_test()
+{
+ boost::local_shared_ptr<T> p1( static_cast<T*>(0) );
+
+ test_nonempty_copy_assign( boost::local_shared_ptr<T>(), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T const>(), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T volatile>(), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T const volatile>(), p1 );
+
+ test_nonempty_copy_assign( boost::local_shared_ptr<T>( static_cast<T*>(0) ), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T const>( static_cast<T const*>(0) ), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T volatile>( static_cast<T volatile*>(0) ), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T const volatile>( static_cast<T const volatile*>(0) ), p1 );
+
+ test_nonempty_copy_assign( boost::local_shared_ptr<void>(), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<void const>(), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<void volatile>(), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<void const volatile>(), p1 );
+}
+
+template<class T> static void new_copy_assign_test()
+{
+ boost::local_shared_ptr<T> p1( new T() );
+
+ test_nonempty_copy_assign( boost::local_shared_ptr<T>(), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T const>(), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T volatile>(), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T const volatile>(), p1 );
+
+ test_nonempty_copy_assign( boost::local_shared_ptr<T>( static_cast<T*>(0) ), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T const>( static_cast<T const*>(0) ), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T volatile>( static_cast<T volatile*>(0) ), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T const volatile>( static_cast<T const volatile*>(0) ), p1 );
+
+ test_nonempty_copy_assign( boost::local_shared_ptr<T>( new T() ), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T const>( new T const() ), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T volatile>( new T volatile() ), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<T const volatile>( new T const volatile() ), p1 );
+
+ test_nonempty_copy_assign( boost::local_shared_ptr<void>(), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<void const>(), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<void volatile>(), p1 );
+ test_nonempty_copy_assign( boost::local_shared_ptr<void const volatile>(), p1 );
+}
+
+static void copy_assignment()
+{
+ empty_copy_assign_test<incomplete>();
+ empty_copy_assign_test<int>();
+ empty_copy_assign_test_<int>();
+ empty_copy_assign_test<X>();
+ empty_copy_assign_test_<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ null_copy_assign_test<int>();
+ null_copy_assign_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_copy_assign_test<int>();
+ new_copy_assign_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+// move assignment
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+template<class T> static void empty_move_assign_test()
+{
+ boost::local_shared_ptr<T> p2;
+
+ p2 = boost::local_shared_ptr<T>();
+
+ BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p2.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T const> p3;
+
+ p3 = boost::local_shared_ptr<T>();
+
+ BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p3.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void> p4;
+
+ p4 = boost::local_shared_ptr<T>();
+
+ BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p4.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void const> p5;
+
+ p5 = std::move( p3 );
+
+ BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p5.local_use_count(), 0 );
+}
+
+template<class T> static void empty_move_assign_test_()
+{
+ boost::local_shared_ptr<T> p2( static_cast<T*>(0) );
+
+ p2 = boost::local_shared_ptr<T>();
+
+ BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p2.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T const> p3( static_cast<T const*>(0) );
+
+ p3 = boost::local_shared_ptr<T>();
+
+ BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p3.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void> p4( static_cast<T*>(0) );
+
+ p4 = boost::local_shared_ptr<T>();
+
+ BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p4.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void const> p5( static_cast<T const*>(0) );
+
+ p5 = std::move( p3 );
+
+ BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p5.local_use_count(), 0 );
+}
+
+template<class T, class U> static void test_nonempty_move_assign( boost::local_shared_ptr<T> p2, boost::local_shared_ptr<U> && p1 )
+{
+ U* q = p1.get();
+ long k = p1.local_use_count();
+
+ p2 = std::move( p1 );
+
+ BOOST_TEST( p2.get() == q );
+ BOOST_TEST( p2.local_use_count() == k );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST( p1.local_use_count() == 0 );
+}
+
+template<class T> static void null_move_assign_test()
+{
+ test_nonempty_move_assign( boost::local_shared_ptr<T>(), boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T const>(), boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T volatile>(), boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T const volatile>(), boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+
+ test_nonempty_move_assign( boost::local_shared_ptr<T>( static_cast<T*>(0) ), boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T const>( static_cast<T const*>(0) ), boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T volatile>( static_cast<T volatile*>(0) ), boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T const volatile>( static_cast<T const volatile*>(0) ), boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+
+ test_nonempty_move_assign( boost::local_shared_ptr<void>(), boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<void const>(), boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<void volatile>(), boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<void const volatile>(), boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+}
+
+template<class T> static void new_move_assign_test()
+{
+ test_nonempty_move_assign( boost::local_shared_ptr<T>(), boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T const>(), boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T volatile>(), boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T const volatile>(), boost::local_shared_ptr<T>( new T() ) );
+
+ test_nonempty_move_assign( boost::local_shared_ptr<T>( static_cast<T*>(0) ), boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T const>( static_cast<T const*>(0) ), boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T volatile>( static_cast<T volatile*>(0) ), boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T const volatile>( static_cast<T const volatile*>(0) ), boost::local_shared_ptr<T>( new T() ) );
+
+ test_nonempty_move_assign( boost::local_shared_ptr<T>( new T() ), boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T const>( new T const() ), boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T volatile>( new T volatile() ), boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<T const volatile>( new T const volatile() ), boost::local_shared_ptr<T>( new T() ) );
+
+ test_nonempty_move_assign( boost::local_shared_ptr<void>(), boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<void const>(), boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<void volatile>(), boost::local_shared_ptr<T>( new T() ) );
+ test_nonempty_move_assign( boost::local_shared_ptr<void const volatile>(), boost::local_shared_ptr<T>( new T() ) );
+}
+
+static void move_assignment()
+{
+ empty_move_assign_test<incomplete>();
+ empty_move_assign_test<int>();
+ empty_move_assign_test_<int>();
+ empty_move_assign_test<X>();
+ empty_move_assign_test_<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ null_move_assign_test<int>();
+ null_move_assign_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_move_assign_test<int>();
+ new_move_assign_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+#else
+
+static void move_assignment()
+{
+}
+
+#endif
+
+// nullptr assignment
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+template<class T> static void test_nullptr_assign( boost::local_shared_ptr<T> p1 )
+{
+ p1 = nullptr;
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST( p1.local_use_count() == 0 );
+}
+
+template<class T> static void empty_nullptr_assign_test()
+{
+ test_nullptr_assign( boost::local_shared_ptr<T>() );
+ test_nullptr_assign( boost::local_shared_ptr<T const>() );
+ test_nullptr_assign( boost::local_shared_ptr<T volatile>() );
+ test_nullptr_assign( boost::local_shared_ptr<T const volatile>() );
+}
+
+template<class T> static void null_nullptr_assign_test()
+{
+ test_nullptr_assign( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nullptr_assign( boost::local_shared_ptr<T const>( static_cast<T const*>(0) ) );
+ test_nullptr_assign( boost::local_shared_ptr<T volatile>( static_cast<T volatile*>(0) ) );
+ test_nullptr_assign( boost::local_shared_ptr<T const volatile>( static_cast<T const volatile*>(0) ) );
+}
+
+template<class T> static void new_nullptr_assign_test()
+{
+ test_nullptr_assign( boost::local_shared_ptr<T>( new T() ) );
+ test_nullptr_assign( boost::local_shared_ptr<T const>( new T const() ) );
+ test_nullptr_assign( boost::local_shared_ptr<T volatile>( new T volatile() ) );
+ test_nullptr_assign( boost::local_shared_ptr<T const volatile>( new T const volatile() ) );
+}
+
+static void nullptr_assignment()
+{
+ empty_nullptr_assign_test<incomplete>();
+ empty_nullptr_assign_test<void>();
+ empty_nullptr_assign_test<int>();
+ empty_nullptr_assign_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ null_nullptr_assign_test<int>();
+ null_nullptr_assign_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_nullptr_assign_test<int>();
+ new_nullptr_assign_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+#else
+
+static void nullptr_assignment()
+{
+}
+
+#endif
+
+// default_reset
+
+template<class T> static void test_default_reset( boost::local_shared_ptr<T> p1 )
+{
+ p1.reset();
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST( p1.local_use_count() == 0 );
+}
+
+template<class T> static void empty_default_reset_test()
+{
+ test_default_reset( boost::local_shared_ptr<T>() );
+ test_default_reset( boost::local_shared_ptr<T const>() );
+ test_default_reset( boost::local_shared_ptr<T volatile>() );
+ test_default_reset( boost::local_shared_ptr<T const volatile>() );
+}
+
+template<class T> static void null_default_reset_test()
+{
+ test_default_reset( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_default_reset( boost::local_shared_ptr<T const>( static_cast<T const*>(0) ) );
+ test_default_reset( boost::local_shared_ptr<T volatile>( static_cast<T volatile*>(0) ) );
+ test_default_reset( boost::local_shared_ptr<T const volatile>( static_cast<T const volatile*>(0) ) );
+}
+
+template<class T> static void new_default_reset_test()
+{
+ test_default_reset( boost::local_shared_ptr<T>( new T() ) );
+ test_default_reset( boost::local_shared_ptr<T const>( new T const() ) );
+ test_default_reset( boost::local_shared_ptr<T volatile>( new T volatile() ) );
+ test_default_reset( boost::local_shared_ptr<T const volatile>( new T const volatile() ) );
+}
+
+static void default_reset()
+{
+ empty_default_reset_test<incomplete>();
+ empty_default_reset_test<void>();
+ empty_default_reset_test<int>();
+ empty_default_reset_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ null_default_reset_test<int>();
+ null_default_reset_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_default_reset_test<int>();
+ new_default_reset_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+// shared_ptr copy assignment
+
+template<class T> static void empty_shared_ptr_copy_assign_test()
+{
+ boost::shared_ptr<T> sp1;
+
+ BOOST_TEST_EQ( sp1.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( sp1.use_count(), 0 );
+
+ boost::local_shared_ptr<T> p2;
+
+ p2 = sp1;
+
+ BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p2.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T const> p3;
+
+ p3 = sp1;
+
+ BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p3.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void> p4;
+
+ p4 = sp1;
+
+ BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p4.local_use_count(), 0 );
+
+ boost::shared_ptr<T const> sp2( sp1 );
+ boost::local_shared_ptr<void const> p5;
+
+ p5 = sp2;
+
+ BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p5.local_use_count(), 0 );
+}
+
+template<class T> static void empty_shared_ptr_copy_assign_test_()
+{
+ boost::shared_ptr<T> sp1;
+
+ BOOST_TEST_EQ( sp1.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( sp1.use_count(), 0 );
+
+ boost::local_shared_ptr<T> p2( static_cast<T*>(0) );
+
+ p2 = sp1;
+
+ BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p2.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T const> p3( static_cast<T const*>(0) );
+
+ p3 = sp1;
+
+ BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p3.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void> p4( static_cast<T*>(0) );
+
+ p4 = sp1;
+
+ BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p4.local_use_count(), 0 );
+
+ boost::shared_ptr<T const> sp2( sp1 );
+ boost::local_shared_ptr<void const> p5( static_cast<T const*>(0) );
+
+ p5 = sp2;
+
+ BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p5.local_use_count(), 0 );
+}
+
+template<class T, class U> static void test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T> p2, boost::shared_ptr<U> const & p1 )
+{
+ long k = p1.use_count();
+
+ p2 = p1;
+
+ BOOST_TEST( p2.get() == p1.get() );
+ BOOST_TEST( p2.local_use_count() == 1 );
+ BOOST_TEST( p1.use_count() == k + 1 );
+
+ p2.reset();
+
+ BOOST_TEST( p1.use_count() == k );
+}
+
+template<class T> static void null_shared_ptr_copy_assign_test()
+{
+ boost::shared_ptr<T> p1( static_cast<T*>(0) );
+
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T>(), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T const>(), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T volatile>(), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T const volatile>(), p1 );
+
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T>( static_cast<T*>(0) ), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T const>( static_cast<T const*>(0) ), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T volatile>( static_cast<T volatile*>(0) ), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T const volatile>( static_cast<T const volatile*>(0) ), p1 );
+
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<void>(), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<void const>(), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<void volatile>(), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<void const volatile>(), p1 );
+}
+
+template<class T> static void new_shared_ptr_copy_assign_test()
+{
+ boost::shared_ptr<T> p1( new T() );
+
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T>(), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T const>(), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T volatile>(), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T const volatile>(), p1 );
+
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T>( static_cast<T*>(0) ), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T const>( static_cast<T const*>(0) ), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T volatile>( static_cast<T volatile*>(0) ), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T const volatile>( static_cast<T const volatile*>(0) ), p1 );
+
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T>( new T() ), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T const>( new T const() ), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T volatile>( new T volatile() ), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<T const volatile>( new T const volatile() ), p1 );
+
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<void>(), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<void const>(), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<void volatile>(), p1 );
+ test_nonempty_shared_ptr_copy_assign( boost::local_shared_ptr<void const volatile>(), p1 );
+}
+
+static void shared_ptr_copy_assignment()
+{
+ empty_shared_ptr_copy_assign_test<incomplete>();
+ empty_shared_ptr_copy_assign_test<int>();
+ empty_shared_ptr_copy_assign_test_<int>();
+ empty_shared_ptr_copy_assign_test<X>();
+ empty_shared_ptr_copy_assign_test_<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ null_shared_ptr_copy_assign_test<int>();
+ null_shared_ptr_copy_assign_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_shared_ptr_copy_assign_test<int>();
+ new_shared_ptr_copy_assign_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+// shared_ptr_move assignment
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+template<class T> static void empty_shared_ptr_move_assign_test()
+{
+ boost::local_shared_ptr<T> p2;
+
+ p2 = boost::shared_ptr<T>();
+
+ BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p2.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T const> p3;
+
+ p3 = boost::shared_ptr<T>();
+
+ BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p3.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void> p4;
+
+ p4 = boost::shared_ptr<T>();
+
+ BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p4.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void const> p5;
+
+ p5 = boost::shared_ptr<T const>();
+
+ BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p5.local_use_count(), 0 );
+}
+
+template<class T> static void empty_shared_ptr_move_assign_test_()
+{
+ boost::local_shared_ptr<T> p2( static_cast<T*>(0) );
+
+ p2 = boost::shared_ptr<T>();
+
+ BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p2.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T const> p3( static_cast<T const*>(0) );
+
+ p3 = boost::shared_ptr<T>();
+
+ BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p3.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void> p4( static_cast<T*>(0) );
+
+ p4 = boost::shared_ptr<T>();
+
+ BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p4.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void const> p5( static_cast<T const*>(0) );
+
+ p5 = boost::shared_ptr<T const>();
+
+ BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p5.local_use_count(), 0 );
+}
+
+template<class T, class U> static void test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T> p2, boost::shared_ptr<U> && p1 )
+{
+ U* q = p1.get();
+ long k = p1.use_count();
+
+ p2 = std::move( p1 );
+
+ BOOST_TEST_EQ( p2.get(), q );
+ BOOST_TEST_EQ( p2.local_use_count(), 1 );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST( p1.use_count() == 0 );
+
+ boost::shared_ptr<T> p3( p2 );
+
+ BOOST_TEST_EQ( p3.get(), q );
+ BOOST_TEST_EQ( p3.use_count(), k + 1 );
+}
+
+template<class T> static void null_shared_ptr_move_assign_test()
+{
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T>(), boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T const>(), boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T volatile>(), boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T const volatile>(), boost::shared_ptr<T>( static_cast<T*>(0) ) );
+
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T>( static_cast<T*>(0) ), boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T const>( static_cast<T const*>(0) ), boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T volatile>( static_cast<T volatile*>(0) ), boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T const volatile>( static_cast<T const volatile*>(0) ), boost::shared_ptr<T>( static_cast<T*>(0) ) );
+
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<void>(), boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<void const>(), boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<void volatile>(), boost::shared_ptr<T>( static_cast<T*>(0) ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<void const volatile>(), boost::shared_ptr<T>( static_cast<T*>(0) ) );
+}
+
+template<class T> static void new_shared_ptr_move_assign_test()
+{
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T>(), boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T const>(), boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T volatile>(), boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T const volatile>(), boost::shared_ptr<T>( new T() ) );
+
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T>( static_cast<T*>(0) ), boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T const>( static_cast<T const*>(0) ), boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T volatile>( static_cast<T volatile*>(0) ), boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T const volatile>( static_cast<T const volatile*>(0) ), boost::shared_ptr<T>( new T() ) );
+
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T>( new T() ), boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T const>( new T const() ), boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T volatile>( new T volatile() ), boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<T const volatile>( new T const volatile() ), boost::shared_ptr<T>( new T() ) );
+
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<void>(), boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<void const>(), boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<void volatile>(), boost::shared_ptr<T>( new T() ) );
+ test_nonempty_shared_ptr_move_assign( boost::local_shared_ptr<void const volatile>(), boost::shared_ptr<T>( new T() ) );
+}
+
+static void shared_ptr_move_assignment()
+{
+ empty_shared_ptr_move_assign_test<incomplete>();
+ empty_shared_ptr_move_assign_test<int>();
+ empty_shared_ptr_move_assign_test_<int>();
+ empty_shared_ptr_move_assign_test<X>();
+ empty_shared_ptr_move_assign_test_<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ null_shared_ptr_move_assign_test<int>();
+ null_shared_ptr_move_assign_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_shared_ptr_move_assign_test<int>();
+ new_shared_ptr_move_assign_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+#else
+
+static void shared_ptr_move_assignment()
+{
+}
+
+#endif
+
+// unique_ptr assignment
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) && !defined( BOOST_NO_CXX11_SMART_PTR )
+
+template<class T> static void empty_unique_ptr_assign_test()
+{
+ boost::local_shared_ptr<T> p2;
+
+ p2 = std::unique_ptr<T>();
+
+ BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p2.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T const> p3;
+
+ p3 = std::unique_ptr<T>();
+
+ BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p3.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void> p4;
+
+ p4 = std::unique_ptr<T>();
+
+ BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p4.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void const> p5;
+
+ p5 = std::unique_ptr<T const>();
+
+ BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p5.local_use_count(), 0 );
+}
+
+template<class T> static void empty_unique_ptr_assign_test_()
+{
+ boost::local_shared_ptr<T> p2( static_cast<T*>(0) );
+
+ p2 = std::unique_ptr<T>();
+
+ BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p2.local_use_count(), 0 );
+
+ boost::local_shared_ptr<T const> p3( static_cast<T const*>(0) );
+
+ p3 = std::unique_ptr<T>();
+
+ BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p3.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void> p4( static_cast<T*>(0) );
+
+ p4 = std::unique_ptr<T>();
+
+ BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p4.local_use_count(), 0 );
+
+ boost::local_shared_ptr<void const> p5( static_cast<T const*>(0) );
+
+ p5 = std::unique_ptr<T const>();
+
+ BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
+ BOOST_TEST_EQ( p5.local_use_count(), 0 );
+}
+
+template<class T, class U, class D> static void test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T> p2, std::unique_ptr<U, D> && p1 )
+{
+ U* q = p1.get();
+
+ p2 = std::move( p1 );
+
+ BOOST_TEST_EQ( p2.get(), q );
+ BOOST_TEST_EQ( p2.local_use_count(), 1 );
+
+ BOOST_TEST( p1.get() == 0 );
+}
+
+template<class T> static void new_unique_ptr_assign_test()
+{
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T>(), std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const>(), std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T volatile>(), std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const volatile>(), std::unique_ptr<T>( new T() ) );
+
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T>( static_cast<T*>(0) ), std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const>( static_cast<T const*>(0) ), std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T volatile>( static_cast<T volatile*>(0) ), std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const volatile>( static_cast<T const volatile*>(0) ), std::unique_ptr<T>( new T() ) );
+
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T>( new T() ), std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const>( new T const() ), std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T volatile>( new T volatile() ), std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const volatile>( new T const volatile() ), std::unique_ptr<T>( new T() ) );
+
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void>(), std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void const>(), std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void volatile>(), std::unique_ptr<T>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void const volatile>(), std::unique_ptr<T>( new T() ) );
+}
+
+template<class T> static void del_unique_ptr_assign_test()
+{
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T volatile>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const volatile>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T>( static_cast<T*>(0) ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const>( static_cast<T const*>(0) ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T volatile>( static_cast<T volatile*>(0) ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const volatile>( static_cast<T const volatile*>(0) ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T>( new T() ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const>( new T const() ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T volatile>( new T volatile() ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const volatile>( new T const volatile() ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void const>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void volatile>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+ test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void const volatile>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
+}
+
+static void unique_ptr_assignment()
+{
+ empty_unique_ptr_assign_test<int>();
+ empty_unique_ptr_assign_test_<int>();
+ empty_unique_ptr_assign_test<X>();
+ empty_unique_ptr_assign_test_<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_unique_ptr_assign_test<int>();
+ new_unique_ptr_assign_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ del_unique_ptr_assign_test<int>();
+ del_unique_ptr_assign_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+#else
+
+static void unique_ptr_assignment()
+{
+}
+
+#endif
+
+// pointer reset
+
+template<class T, class U> static void test_pointer_reset( boost::local_shared_ptr<U> p2 )
+{
+ T * q = new T();
+
+ p2.reset( q );
+
+ BOOST_TEST_EQ( p2.get(), q );
+ BOOST_TEST_EQ( p2.local_use_count(), 1 );
+}
+
+template<class T> static void empty_pointer_reset_test()
+{
+ test_pointer_reset<T>( boost::local_shared_ptr<T>() );
+ test_pointer_reset<T>( boost::local_shared_ptr<T const>() );
+ test_pointer_reset<T>( boost::local_shared_ptr<T volatile>() );
+ test_pointer_reset<T>( boost::local_shared_ptr<T const volatile>() );
+
+ test_pointer_reset<T>( boost::local_shared_ptr<void>() );
+ test_pointer_reset<T>( boost::local_shared_ptr<void const>() );
+ test_pointer_reset<T>( boost::local_shared_ptr<void volatile>() );
+ test_pointer_reset<T>( boost::local_shared_ptr<void const volatile>() );
+}
+
+template<class T> static void null_pointer_reset_test()
+{
+ test_pointer_reset<T>( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_pointer_reset<T>( boost::local_shared_ptr<T const>( static_cast<T*>(0) ) );
+ test_pointer_reset<T>( boost::local_shared_ptr<T volatile>( static_cast<T*>(0) ) );
+ test_pointer_reset<T>( boost::local_shared_ptr<T const volatile>( static_cast<T*>(0) ) );
+
+ test_pointer_reset<T>( boost::local_shared_ptr<void>( static_cast<T*>(0) ) );
+ test_pointer_reset<T>( boost::local_shared_ptr<void const>( static_cast<T*>(0) ) );
+ test_pointer_reset<T>( boost::local_shared_ptr<void volatile>( static_cast<T*>(0) ) );
+ test_pointer_reset<T>( boost::local_shared_ptr<void const volatile>( static_cast<T*>(0) ) );
+}
+
+template<class T> static void new_pointer_reset_test()
+{
+ test_pointer_reset<T>( boost::local_shared_ptr<T>( new T() ) );
+ test_pointer_reset<T>( boost::local_shared_ptr<T const>( new T() ) );
+ test_pointer_reset<T>( boost::local_shared_ptr<T volatile>( new T() ) );
+ test_pointer_reset<T>( boost::local_shared_ptr<T const volatile>( new T() ) );
+
+ test_pointer_reset<T>( boost::local_shared_ptr<void>( new T() ) );
+ test_pointer_reset<T>( boost::local_shared_ptr<void const>( new T() ) );
+ test_pointer_reset<T>( boost::local_shared_ptr<void volatile>( new T() ) );
+ test_pointer_reset<T>( boost::local_shared_ptr<void const volatile>( new T() ) );
+}
+
+static void pointer_reset()
+{
+ empty_pointer_reset_test<int>();
+ empty_pointer_reset_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ null_pointer_reset_test<int>();
+ null_pointer_reset_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_pointer_reset_test<int>();
+ new_pointer_reset_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+// deleter reset
+
+template<class T> class deleter
+{
+private:
+
+ bool * called_;
+
+public:
+
+ explicit deleter( bool * called ): called_( called ) {}
+ void operator()( T * p ) { *called_ = true; delete p; }
+};
+
+template<class T, class U> static void test_deleter_reset( boost::local_shared_ptr<U> p2 )
+{
+ T * q = new T();
+
+ bool called = false;
+
+ p2.reset( q, deleter<T>( &called ) );
+
+ BOOST_TEST_EQ( p2.get(), q );
+ BOOST_TEST_EQ( p2.local_use_count(), 1 );
+
+ boost::shared_ptr<U> p3( p2 );
+
+ BOOST_TEST( boost::get_deleter< deleter<T> >( p3 ) != 0 );
+
+ p3.reset();
+ BOOST_TEST( !called );
+
+ p2.reset();
+ BOOST_TEST( called );
+}
+
+template<class T> static void empty_deleter_reset_test()
+{
+ test_deleter_reset<T>( boost::local_shared_ptr<T>() );
+ test_deleter_reset<T>( boost::local_shared_ptr<T const>() );
+ test_deleter_reset<T>( boost::local_shared_ptr<T volatile>() );
+ test_deleter_reset<T>( boost::local_shared_ptr<T const volatile>() );
+
+ test_deleter_reset<T>( boost::local_shared_ptr<void>() );
+ test_deleter_reset<T>( boost::local_shared_ptr<void const>() );
+ test_deleter_reset<T>( boost::local_shared_ptr<void volatile>() );
+ test_deleter_reset<T>( boost::local_shared_ptr<void const volatile>() );
+}
+
+template<class T> static void null_deleter_reset_test()
+{
+ test_deleter_reset<T>( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_deleter_reset<T>( boost::local_shared_ptr<T const>( static_cast<T*>(0) ) );
+ test_deleter_reset<T>( boost::local_shared_ptr<T volatile>( static_cast<T*>(0) ) );
+ test_deleter_reset<T>( boost::local_shared_ptr<T const volatile>( static_cast<T*>(0) ) );
+
+ test_deleter_reset<T>( boost::local_shared_ptr<void>( static_cast<T*>(0) ) );
+ test_deleter_reset<T>( boost::local_shared_ptr<void const>( static_cast<T*>(0) ) );
+ test_deleter_reset<T>( boost::local_shared_ptr<void volatile>( static_cast<T*>(0) ) );
+ test_deleter_reset<T>( boost::local_shared_ptr<void const volatile>( static_cast<T*>(0) ) );
+}
+
+template<class T> static void new_deleter_reset_test()
+{
+ test_deleter_reset<T>( boost::local_shared_ptr<T>( new T() ) );
+ test_deleter_reset<T>( boost::local_shared_ptr<T const>( new T() ) );
+ test_deleter_reset<T>( boost::local_shared_ptr<T volatile>( new T() ) );
+ test_deleter_reset<T>( boost::local_shared_ptr<T const volatile>( new T() ) );
+
+ test_deleter_reset<T>( boost::local_shared_ptr<void>( new T() ) );
+ test_deleter_reset<T>( boost::local_shared_ptr<void const>( new T() ) );
+ test_deleter_reset<T>( boost::local_shared_ptr<void volatile>( new T() ) );
+ test_deleter_reset<T>( boost::local_shared_ptr<void const volatile>( new T() ) );
+}
+
+static void deleter_reset()
+{
+ empty_deleter_reset_test<int>();
+ empty_deleter_reset_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ null_deleter_reset_test<int>();
+ null_deleter_reset_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_deleter_reset_test<int>();
+ new_deleter_reset_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+// allocator reset
+
+template<class T, class U> static void test_allocator_reset( boost::local_shared_ptr<U> p2 )
+{
+ T * q = new T();
+
+ bool called = false;
+
+ p2.reset( q, deleter<T>( &called ), std::allocator<T>() );
+
+ BOOST_TEST_EQ( p2.get(), q );
+ BOOST_TEST_EQ( p2.local_use_count(), 1 );
+
+ boost::shared_ptr<U> p3( p2 );
+
+ BOOST_TEST( boost::get_deleter< deleter<T> >( p3 ) != 0 );
+
+ p3.reset();
+ BOOST_TEST( !called );
+
+ p2.reset();
+ BOOST_TEST( called );
+}
+
+template<class T> static void empty_allocator_reset_test()
+{
+ test_allocator_reset<T>( boost::local_shared_ptr<T>() );
+ test_allocator_reset<T>( boost::local_shared_ptr<T const>() );
+ test_allocator_reset<T>( boost::local_shared_ptr<T volatile>() );
+ test_allocator_reset<T>( boost::local_shared_ptr<T const volatile>() );
+
+ test_allocator_reset<T>( boost::local_shared_ptr<void>() );
+ test_allocator_reset<T>( boost::local_shared_ptr<void const>() );
+ test_allocator_reset<T>( boost::local_shared_ptr<void volatile>() );
+ test_allocator_reset<T>( boost::local_shared_ptr<void const volatile>() );
+}
+
+template<class T> static void null_allocator_reset_test()
+{
+ test_allocator_reset<T>( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
+ test_allocator_reset<T>( boost::local_shared_ptr<T const>( static_cast<T*>(0) ) );
+ test_allocator_reset<T>( boost::local_shared_ptr<T volatile>( static_cast<T*>(0) ) );
+ test_allocator_reset<T>( boost::local_shared_ptr<T const volatile>( static_cast<T*>(0) ) );
+
+ test_allocator_reset<T>( boost::local_shared_ptr<void>( static_cast<T*>(0) ) );
+ test_allocator_reset<T>( boost::local_shared_ptr<void const>( static_cast<T*>(0) ) );
+ test_allocator_reset<T>( boost::local_shared_ptr<void volatile>( static_cast<T*>(0) ) );
+ test_allocator_reset<T>( boost::local_shared_ptr<void const volatile>( static_cast<T*>(0) ) );
+}
+
+template<class T> static void new_allocator_reset_test()
+{
+ test_allocator_reset<T>( boost::local_shared_ptr<T>( new T() ) );
+ test_allocator_reset<T>( boost::local_shared_ptr<T const>( new T() ) );
+ test_allocator_reset<T>( boost::local_shared_ptr<T volatile>( new T() ) );
+ test_allocator_reset<T>( boost::local_shared_ptr<T const volatile>( new T() ) );
+
+ test_allocator_reset<T>( boost::local_shared_ptr<void>( new T() ) );
+ test_allocator_reset<T>( boost::local_shared_ptr<void const>( new T() ) );
+ test_allocator_reset<T>( boost::local_shared_ptr<void volatile>( new T() ) );
+ test_allocator_reset<T>( boost::local_shared_ptr<void const volatile>( new T() ) );
+}
+
+static void allocator_reset()
+{
+ empty_allocator_reset_test<int>();
+ empty_allocator_reset_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ null_allocator_reset_test<int>();
+ null_allocator_reset_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_allocator_reset_test<int>();
+ new_allocator_reset_test<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+// aliasing reset
+
+struct null_deleter
+{
+ void operator()( void const volatile* ) {}
+};
+
+template<class T, class U> void test_aliasing_reset_( boost::local_shared_ptr<T> const & p1, U * p2 )
+{
+ boost::local_shared_ptr<U> p3( static_cast<U*>(0), null_deleter() );
+
+ p3.reset( p1, p2 );
+
+ BOOST_TEST( p3.get() == p2 );
+ BOOST_TEST( p3.local_use_count() == p1.local_use_count() );
+ BOOST_TEST( !p3.owner_before( p1 ) && !p1.owner_before( p3 ) );
+}
+
+template<class T, class U> void test_01_aliasing_reset_()
+{
+ U u;
+ boost::local_shared_ptr<T> p1;
+
+ test_aliasing_reset_( p1, &u );
+}
+
+template<class T, class U> void test_01_aliasing_reset()
+{
+ test_01_aliasing_reset_<T, U>();
+ test_01_aliasing_reset_<T const, U>();
+ test_01_aliasing_reset_<T volatile, U>();
+ test_01_aliasing_reset_<T const volatile, U>();
+
+ test_01_aliasing_reset_<T, U volatile>();
+ test_01_aliasing_reset_<T const, U volatile>();
+ test_01_aliasing_reset_<T volatile, U volatile>();
+ test_01_aliasing_reset_<T const volatile, U volatile>();
+}
+
+template<class T, class U> void test_10_aliasing_reset_()
+{
+ boost::local_shared_ptr<T> p1( new T() );
+ test_aliasing_reset_( p1, static_cast<U*>(0) );
+}
+
+template<class T, class U> void test_10_aliasing_reset()
+{
+ test_10_aliasing_reset_<T, U>();
+ test_10_aliasing_reset_<T const, U>();
+ test_10_aliasing_reset_<T volatile, U>();
+ test_10_aliasing_reset_<T const volatile, U>();
+
+ test_10_aliasing_reset_<T, U const>();
+ test_10_aliasing_reset_<T const, U const>();
+ test_10_aliasing_reset_<T volatile, U const>();
+ test_10_aliasing_reset_<T const volatile, U const>();
+
+ test_10_aliasing_reset_<T, U volatile>();
+ test_10_aliasing_reset_<T const, U volatile>();
+ test_10_aliasing_reset_<T volatile, U volatile>();
+ test_10_aliasing_reset_<T const volatile, U volatile>();
+
+ test_10_aliasing_reset_<T, U const volatile>();
+ test_10_aliasing_reset_<T const, U const volatile>();
+ test_10_aliasing_reset_<T volatile, U const volatile>();
+ test_10_aliasing_reset_<T const volatile, U const volatile>();
+}
+
+template<class T, class U> void test_11_aliasing_reset_()
+{
+ U u;
+ boost::local_shared_ptr<T> p1( new T() );
+
+ test_aliasing_reset_( p1, &u );
+}
+
+template<class T, class U> void test_11_aliasing_reset()
+{
+ test_11_aliasing_reset_<T, U>();
+ test_11_aliasing_reset_<T const, U>();
+ test_11_aliasing_reset_<T volatile, U>();
+ test_11_aliasing_reset_<T const volatile, U>();
+
+ test_11_aliasing_reset_<T, U volatile>();
+ test_11_aliasing_reset_<T const, U volatile>();
+ test_11_aliasing_reset_<T volatile, U volatile>();
+ test_11_aliasing_reset_<T const volatile, U volatile>();
+}
+
+static void aliasing_reset()
+{
+ test_01_aliasing_reset<int, int>();
+ test_10_aliasing_reset<int, int>();
+ test_11_aliasing_reset<int, int>();
+
+ test_01_aliasing_reset<void, int>();
+
+ test_10_aliasing_reset<int, void>();
+
+ test_10_aliasing_reset<int, incomplete>();
+
+ test_01_aliasing_reset<X, X>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_10_aliasing_reset<X, X>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_11_aliasing_reset<X, X>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_01_aliasing_reset<int, X>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_10_aliasing_reset<int, X>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_11_aliasing_reset<int, X>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_01_aliasing_reset<X, int>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_10_aliasing_reset<X, int>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_11_aliasing_reset<X, int>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_01_aliasing_reset<void, X>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_10_aliasing_reset<X, void>();
+ BOOST_TEST( X::instances == 0 );
+
+ test_10_aliasing_reset<X, incomplete>();
+ BOOST_TEST( X::instances == 0 );
+}
+
+// element access
+
+template<class T> static void empty_element_access_()
+{
+ boost::local_shared_ptr<T> p1;
+
+ BOOST_TEST_EQ( p1.operator->(), static_cast<T*>(0) );
+ BOOST_TEST_EQ( p1.get(), static_cast<T*>(0) );
+ BOOST_TEST( p1? false: true );
+ BOOST_TEST( !p1 );
+ BOOST_TEST_EQ( p1.local_use_count(), 0 );
+}
+
+template<class T> static void empty_element_access()
+{
+ empty_element_access_<T>();
+ empty_element_access_<T const>();
+ empty_element_access_<T volatile>();
+ empty_element_access_<T const volatile>();
+}
+
+template<class T> static void new_element_access_()
+{
+ {
+ T * p0 = new T();
+ boost::local_shared_ptr<T> p1( p0 );
+
+ BOOST_TEST_EQ( p1.operator->(), p0 );
+ BOOST_TEST_EQ( p1.get(), p0 );
+ BOOST_TEST_EQ( &*p1, p0 );
+ BOOST_TEST( p1? true: false );
+ BOOST_TEST_NOT( !p1 );
+ BOOST_TEST_EQ( p1.local_use_count(), 1 );
+ }
+
+ {
+ T * p0 = new T[3]();
+ boost::local_shared_ptr<T[]> p1( p0 );
+
+ BOOST_TEST_EQ( p1.get(), p0 );
+
+ BOOST_TEST_EQ( &p1[0], &p0[0] );
+ BOOST_TEST_EQ( &p1[1], &p0[1] );
+ BOOST_TEST_EQ( &p1[2], &p0[2] );
+
+ BOOST_TEST( p1? true: false );
+ BOOST_TEST_NOT( !p1 );
+ BOOST_TEST_EQ( p1.local_use_count(), 1 );
+ }
+
+ {
+ T * p0 = new T[3]();
+ boost::local_shared_ptr<T[3]> p1( p0 );
+
+ BOOST_TEST_EQ( p1.get(), p0 );
+
+ BOOST_TEST_EQ( &p1[0], &p0[0] );
+ BOOST_TEST_EQ( &p1[1], &p0[1] );
+ BOOST_TEST_EQ( &p1[2], &p0[2] );
+
+ BOOST_TEST( p1? true: false );
+ BOOST_TEST_NOT( !p1 );
+ BOOST_TEST_EQ( p1.local_use_count(), 1 );
+ }
+}
+
+template<class T> static void new_element_access()
+{
+ new_element_access_<T>();
+ new_element_access_<T const>();
+ new_element_access_<T volatile>();
+ new_element_access_<T const volatile>();
+}
+
+static void element_access()
+{
+ empty_element_access<int>();
+ empty_element_access<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ empty_element_access<incomplete>();
+ empty_element_access<void>();
+
+ new_element_access<int>();
+ new_element_access<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+// shared_ptr conversion
+
+template<class T, class U> static void empty_shared_ptr_conversion_()
+{
+ boost::local_shared_ptr<T> p1;
+ boost::shared_ptr<U> p2( p1 );
+
+ BOOST_TEST_EQ( p2.get(), static_cast<U*>(0) );
+ BOOST_TEST_EQ( p2.use_count(), 0 );
+}
+
+template<class T> static void empty_shared_ptr_conversion()
+{
+ empty_shared_ptr_conversion_<T, T>();
+ empty_shared_ptr_conversion_<T, T const>();
+ empty_shared_ptr_conversion_<T, T volatile>();
+ empty_shared_ptr_conversion_<T, T const volatile>();
+
+ empty_shared_ptr_conversion_<T const, T const>();
+ empty_shared_ptr_conversion_<T volatile, T volatile>();
+ empty_shared_ptr_conversion_<T const volatile, T const volatile>();
+
+ empty_shared_ptr_conversion_<T, void>();
+ empty_shared_ptr_conversion_<T, void const>();
+ empty_shared_ptr_conversion_<T, void volatile>();
+ empty_shared_ptr_conversion_<T, void const volatile>();
+
+ empty_shared_ptr_conversion_<T const, void const>();
+ empty_shared_ptr_conversion_<T volatile, void volatile>();
+ empty_shared_ptr_conversion_<T const volatile, void const volatile>();
+}
+
+template<class T, class U> static void new_shared_ptr_conversion_()
+{
+ boost::local_shared_ptr<T> p1( new T() );
+ boost::shared_ptr<U> p2( p1 );
+
+ BOOST_TEST_EQ( p2.get(), p1.get() );
+ BOOST_TEST_EQ( p2.use_count(), 2 );
+
+ boost::shared_ptr<U> p3( p1 );
+
+ BOOST_TEST_EQ( p3.get(), p1.get() );
+ BOOST_TEST_EQ( p3.use_count(), 3 );
+ BOOST_TEST( !(p2 < p3) && !(p3 < p2) );
+
+ BOOST_TEST_EQ( p1.local_use_count(), 1 );
+
+ p1.reset();
+
+ BOOST_TEST_EQ( p2.use_count(), 2 );
+ BOOST_TEST_EQ( p3.use_count(), 2 );
+}
+
+template<class T> static void new_shared_ptr_conversion()
+{
+ new_shared_ptr_conversion_<T, T>();
+ new_shared_ptr_conversion_<T, T const>();
+ new_shared_ptr_conversion_<T, T volatile>();
+ new_shared_ptr_conversion_<T, T const volatile>();
+
+ new_shared_ptr_conversion_<T const, T const>();
+ new_shared_ptr_conversion_<T volatile, T volatile>();
+ new_shared_ptr_conversion_<T const volatile, T const volatile>();
+
+ new_shared_ptr_conversion_<T, void>();
+ new_shared_ptr_conversion_<T, void const>();
+ new_shared_ptr_conversion_<T, void volatile>();
+ new_shared_ptr_conversion_<T, void const volatile>();
+
+ new_shared_ptr_conversion_<T const, void const>();
+ new_shared_ptr_conversion_<T volatile, void volatile>();
+ new_shared_ptr_conversion_<T const volatile, void const volatile>();
+}
+
+static void shared_ptr_conversion()
+{
+ empty_shared_ptr_conversion<void>();
+ empty_shared_ptr_conversion<incomplete>();
+ empty_shared_ptr_conversion<int>();
+ empty_shared_ptr_conversion<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_shared_ptr_conversion<int>();
+ new_shared_ptr_conversion<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+// weak_ptr conversion
+
+template<class T, class U> static void empty_weak_ptr_conversion_()
+{
+ boost::local_shared_ptr<T> p1;
+ boost::weak_ptr<U> p2( p1 );
+
+ BOOST_TEST_EQ( p2.lock().get(), static_cast<U*>(0) );
+ BOOST_TEST_EQ( p2.use_count(), 0 );
+}
+
+template<class T> static void empty_weak_ptr_conversion()
+{
+ empty_weak_ptr_conversion_<T, T>();
+ empty_weak_ptr_conversion_<T, T const>();
+ empty_weak_ptr_conversion_<T, T volatile>();
+ empty_weak_ptr_conversion_<T, T const volatile>();
+
+ empty_weak_ptr_conversion_<T const, T const>();
+ empty_weak_ptr_conversion_<T volatile, T volatile>();
+ empty_weak_ptr_conversion_<T const volatile, T const volatile>();
+
+ empty_weak_ptr_conversion_<T, void>();
+ empty_weak_ptr_conversion_<T, void const>();
+ empty_weak_ptr_conversion_<T, void volatile>();
+ empty_weak_ptr_conversion_<T, void const volatile>();
+
+ empty_weak_ptr_conversion_<T const, void const>();
+ empty_weak_ptr_conversion_<T volatile, void volatile>();
+ empty_weak_ptr_conversion_<T const volatile, void const volatile>();
+}
+
+template<class T, class U> static void new_weak_ptr_conversion_()
+{
+ boost::local_shared_ptr<T> p1( new T() );
+ boost::weak_ptr<U> p2( p1 );
+
+ BOOST_TEST_EQ( p2.lock().get(), p1.get() );
+ BOOST_TEST_EQ( p2.use_count(), 1 );
+
+ boost::weak_ptr<U> p3( p1 );
+
+ BOOST_TEST_EQ( p3.lock().get(), p1.get() );
+ BOOST_TEST_EQ( p3.use_count(), 1 );
+ BOOST_TEST( !(p2 < p3) && !(p3 < p2) );
+
+ BOOST_TEST_EQ( p1.local_use_count(), 1 );
+
+ p1.reset();
+
+ BOOST_TEST_EQ( p2.use_count(), 0 );
+ BOOST_TEST_EQ( p3.use_count(), 0 );
+}
+
+template<class T> static void new_weak_ptr_conversion()
+{
+ new_weak_ptr_conversion_<T, T>();
+ new_weak_ptr_conversion_<T, T const>();
+ new_weak_ptr_conversion_<T, T volatile>();
+ new_weak_ptr_conversion_<T, T const volatile>();
+
+ new_weak_ptr_conversion_<T const, T const>();
+ new_weak_ptr_conversion_<T volatile, T volatile>();
+ new_weak_ptr_conversion_<T const volatile, T const volatile>();
+
+ new_weak_ptr_conversion_<T, void>();
+ new_weak_ptr_conversion_<T, void const>();
+ new_weak_ptr_conversion_<T, void volatile>();
+ new_weak_ptr_conversion_<T, void const volatile>();
+
+ new_weak_ptr_conversion_<T const, void const>();
+ new_weak_ptr_conversion_<T volatile, void volatile>();
+ new_weak_ptr_conversion_<T const volatile, void const volatile>();
+}
+
+static void weak_ptr_conversion()
+{
+ empty_weak_ptr_conversion<void>();
+ empty_weak_ptr_conversion<incomplete>();
+ empty_weak_ptr_conversion<int>();
+ empty_weak_ptr_conversion<X>();
+
+ BOOST_TEST( X::instances == 0 );
+
+ new_weak_ptr_conversion<int>();
+ new_weak_ptr_conversion<X>();
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+// main
+
+int main()
+{
+ default_constructor();
+ nullptr_constructor();
+ pointer_constructor();
+ deleter_constructor();
+ copy_constructor();
+ move_constructor();
+ aliasing_constructor();
+ nullptr_deleter_constructor();
+ allocator_constructor();
+ nullptr_allocator_constructor();
+ shared_ptr_copy_constructor();
+ shared_ptr_move_constructor();
+ unique_ptr_constructor();
+
+ copy_assignment();
+ move_assignment();
+ nullptr_assignment();
+ shared_ptr_copy_assignment();
+ shared_ptr_move_assignment();
+ unique_ptr_assignment();
+
+ default_reset();
+ pointer_reset();
+ deleter_reset();
+ allocator_reset();
+ aliasing_reset();
+
+ element_access();
+ shared_ptr_conversion();
+ weak_ptr_conversion();
+ // swap_test();
+ // owner_before_test();
+ // equal_test();
+ // operator< ?
+ // casts
+ // get_pointer
+ // operator<<
+ // hash
+
+ return boost::report_errors();
+}
diff --git a/test/lsp_array_cast_test.cpp b/test/lsp_array_cast_test.cpp
new file mode 100644
index 0000000..183cddc
--- /dev/null
+++ b/test/lsp_array_cast_test.cpp
@@ -0,0 +1,202 @@
+//
+// lsp_array_cast_test.cpp
+//
+// Copyright 2012, 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
+//
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+struct X
+{
+};
+
+void static_cast_test()
+{
+ {
+ boost::local_shared_ptr<void> pv;
+
+ boost::local_shared_ptr<int[]> pi = boost::static_pointer_cast<int[]>( pv );
+ BOOST_TEST( pi.get() == 0 );
+
+ boost::local_shared_ptr<int[3]> pi2 = boost::static_pointer_cast<int[3]>( pv );
+ BOOST_TEST( pi2.get() == 0 );
+
+ boost::local_shared_ptr<X[]> px = boost::static_pointer_cast<X[]>( pv );
+ BOOST_TEST( px.get() == 0 );
+
+ boost::local_shared_ptr<X[5]> px2 = boost::static_pointer_cast<X[5]>( pv );
+ BOOST_TEST( px2.get() == 0 );
+ }
+
+ {
+ boost::local_shared_ptr<int[]> pi( new int[2] );
+ boost::local_shared_ptr<void> pv( pi );
+
+ boost::local_shared_ptr<int[]> pi2 = boost::static_pointer_cast<int[]>( pv );
+ BOOST_TEST(pi.get() == pi2.get());
+ BOOST_TEST(!(pi < pi2 || pi2 < pi));
+
+ boost::local_shared_ptr<int[2]> pi3 = boost::static_pointer_cast<int[2]>( pv );
+ BOOST_TEST(pi.get() == pi3.get());
+ BOOST_TEST(!(pi < pi3 || pi3 < pi));
+
+ boost::local_shared_ptr<void> pv2( pi3 );
+
+ boost::local_shared_ptr<int[]> pi4 = boost::static_pointer_cast<int[]>( pv2 );
+ BOOST_TEST(pi.get() == pi4.get());
+ BOOST_TEST(!(pi < pi4 || pi4 < pi));
+ }
+
+ {
+ boost::local_shared_ptr<X[]> px( new X[4] );
+ boost::local_shared_ptr<void> pv( px );
+
+ boost::local_shared_ptr<X[]> px2 = boost::static_pointer_cast<X[]>( pv );
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+
+ boost::local_shared_ptr<X[4]> px3 = boost::static_pointer_cast<X[4]>( pv );
+ BOOST_TEST(px.get() == px3.get());
+ BOOST_TEST(!(px < px3 || px3 < px));
+
+ boost::local_shared_ptr<void> pv2( px3 );
+
+ boost::local_shared_ptr<X[]> px4 = boost::static_pointer_cast<X[]>( pv2 );
+ BOOST_TEST(px.get() == px4.get());
+ BOOST_TEST(!(px < px4 || px4 < px));
+ }
+}
+
+void const_cast_test()
+{
+ {
+ boost::local_shared_ptr<int const volatile[]> px;
+
+ boost::local_shared_ptr<int[]> px2 = boost::const_pointer_cast<int[]>(px);
+ BOOST_TEST( px2.get() == 0 );
+ }
+
+ {
+ boost::local_shared_ptr<int const volatile[2]> px;
+
+ boost::local_shared_ptr<int[2]> px2 = boost::const_pointer_cast<int[2]>(px);
+ BOOST_TEST( px2.get() == 0 );
+ }
+
+ {
+ boost::local_shared_ptr<X const volatile[]> px;
+
+ boost::local_shared_ptr<X[]> px2 = boost::const_pointer_cast<X[]>(px);
+ BOOST_TEST( px2.get() == 0 );
+ }
+
+ {
+ boost::local_shared_ptr<X const volatile[5]> px;
+
+ boost::local_shared_ptr<X[5]> px2 = boost::const_pointer_cast<X[5]>(px);
+ BOOST_TEST( px2.get() == 0 );
+ }
+
+ {
+ boost::local_shared_ptr<int const volatile[]> px( new int[3] );
+
+ boost::local_shared_ptr<int[]> px2 = boost::const_pointer_cast<int[]>(px);
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+ }
+
+ {
+ boost::local_shared_ptr<int const volatile[3]> px( new int[3] );
+
+ boost::local_shared_ptr<int[3]> px2 = boost::const_pointer_cast<int[3]>(px);
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+ }
+
+ {
+ boost::local_shared_ptr<X const volatile[]> px( new X[4] );
+
+ boost::local_shared_ptr<X[]> px2 = boost::const_pointer_cast<X[]>(px);
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+ }
+
+ {
+ boost::local_shared_ptr<X const volatile[4]> px( new X[4] );
+
+ boost::local_shared_ptr<X[4]> px2 = boost::const_pointer_cast<X[4]>(px);
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+ }
+}
+
+void reinterpret_cast_test()
+{
+ {
+ boost::local_shared_ptr<int[]> pi;
+ BOOST_TEST( pi.get() == 0 );
+
+ boost::local_shared_ptr<int[3]> pi2 = boost::reinterpret_pointer_cast<int[3]>( pi );
+ BOOST_TEST( pi2.get() == 0 );
+
+ boost::local_shared_ptr<int[6]> pi3 = boost::reinterpret_pointer_cast<int[6]>( pi2 );
+ BOOST_TEST( pi3.get() == 0 );
+ }
+
+ {
+ boost::local_shared_ptr<X[]> px;
+ BOOST_TEST( px.get() == 0 );
+
+ boost::local_shared_ptr<X[5]> px2 = boost::reinterpret_pointer_cast<X[5]>( px );
+ BOOST_TEST( px2.get() == 0 );
+
+ boost::local_shared_ptr<X[9]> px3 = boost::reinterpret_pointer_cast<X[9]>( px2 );
+ BOOST_TEST( px3.get() == 0 );
+ }
+
+ {
+ boost::local_shared_ptr<int[]> pi( new int[2] );
+
+ boost::local_shared_ptr<int[2]> pi2 = boost::reinterpret_pointer_cast<int[2]>( pi );
+ BOOST_TEST(pi.get() == pi2.get());
+ BOOST_TEST(!(pi < pi2 || pi2 < pi));
+
+ boost::local_shared_ptr<int[1]> pi3 = boost::reinterpret_pointer_cast<int[1]>( pi2 );
+ BOOST_TEST(pi.get() == pi3.get());
+ BOOST_TEST(!(pi < pi3 || pi3 < pi));
+
+ boost::local_shared_ptr<int[]> pi4 = boost::reinterpret_pointer_cast<int[]>( pi3 );
+ BOOST_TEST(pi.get() == pi4.get());
+ BOOST_TEST(!(pi < pi4 || pi4 < pi));
+ }
+
+ {
+ boost::local_shared_ptr<X[]> px( new X[4] );
+
+ boost::local_shared_ptr<X[7]> px2 = boost::reinterpret_pointer_cast<X[7]>( px );
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+
+ boost::local_shared_ptr<X[4]> px3 = boost::reinterpret_pointer_cast<X[4]>( px2 );
+ BOOST_TEST(px.get() == px3.get());
+ BOOST_TEST(!(px < px3 || px3 < px));
+
+ boost::local_shared_ptr<X[]> px4 = boost::reinterpret_pointer_cast<X[]>( px3 );
+ BOOST_TEST(px.get() == px4.get());
+ BOOST_TEST(!(px < px4 || px4 < px));
+ }
+}
+
+int main()
+{
+ static_cast_test();
+ const_cast_test();
+ reinterpret_cast_test();
+
+ return boost::report_errors();
+}
diff --git a/test/lsp_array_cv_test.cpp b/test/lsp_array_cv_test.cpp
new file mode 100644
index 0000000..869d206
--- /dev/null
+++ b/test/lsp_array_cv_test.cpp
@@ -0,0 +1,60 @@
+//
+// lsp_array_cv_test.cpp
+//
+// Copyright 2012, 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
+//
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+
+struct X
+{
+};
+
+class B
+{
+};
+
+class D: public B
+{
+};
+
+#define TEST_CONV( T, U ) \
+ { \
+ boost::local_shared_ptr< T > p1; \
+ boost::local_shared_ptr< U > p2( p1 ); \
+ p2 = p1; \
+ boost::local_shared_ptr< U > p3 = boost::local_shared_ptr< T >(); \
+ p3 = boost::local_shared_ptr< T >(); \
+ }
+
+#define TEST_CV_TRUE( T, U ) \
+ TEST_CONV( T, U ) \
+ TEST_CONV( T, const U ) \
+ TEST_CONV( T, volatile U ) \
+ TEST_CONV( T, const volatile U ) \
+ TEST_CONV( const T, const U ) \
+ TEST_CONV( const T, const volatile U ) \
+ TEST_CONV( volatile T, volatile U ) \
+ TEST_CONV( volatile T, const volatile U ) \
+ TEST_CONV( const volatile T, const volatile U )
+
+int main()
+{
+ TEST_CV_TRUE( X, X )
+ TEST_CV_TRUE( X, void )
+ TEST_CV_TRUE( D, B )
+
+ TEST_CV_TRUE( X[], X[] )
+ TEST_CV_TRUE( X[3], X[3] )
+
+ TEST_CV_TRUE( X[3], X[] )
+
+ TEST_CV_TRUE( X[], void )
+ TEST_CV_TRUE( X[3], void )
+
+ return 0;
+}
diff --git a/test/lsp_array_n_test.cpp b/test/lsp_array_n_test.cpp
new file mode 100644
index 0000000..a31e264
--- /dev/null
+++ b/test/lsp_array_n_test.cpp
@@ -0,0 +1,248 @@
+//
+// lsp_array_n_test.cpp
+//
+// Copyright 2012, 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
+//
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <memory>
+#include <utility>
+
+class X: public boost::enable_shared_from_this< X >
+{
+public:
+
+ static int allocations;
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+ void* operator new[]( std::size_t n )
+ {
+ ++allocations;
+ return ::operator new[]( n );
+ }
+
+ void operator delete[]( void* p )
+ {
+ --allocations;
+ ::operator delete[]( p );
+ }
+
+private:
+
+ X( X const& );
+ X& operator=( X const& );
+};
+
+int X::allocations = 0;
+int X::instances = 0;
+
+template< class T> class array_deleter
+{
+public:
+
+ static int calls;
+
+ void operator()( T * p ) const
+ {
+ ++calls;
+ delete[] p;
+ }
+
+private:
+
+ template< class Y > void operator()( Y * p ) const;
+};
+
+template< class T > int array_deleter< T >::calls = 0;
+
+int main()
+{
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::local_shared_ptr<X[3]> px;
+ BOOST_TEST( !px );
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ boost::local_shared_ptr<X[3]> px2( new X[ 3 ] );
+ BOOST_TEST( px2 );
+
+ try
+ {
+ px2[0].shared_from_this();
+ BOOST_ERROR( "px2[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 3 );
+
+ {
+ X & rx = px2[ 0 ];
+ BOOST_TEST( &rx == px2.get() );
+ }
+
+ boost::local_shared_ptr<X const[3]> px3( px2 );
+ BOOST_TEST( px3 == px2 );
+ BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) );
+
+ {
+ X const & rx = px3[ 1 ];
+ BOOST_TEST( &rx == px3.get() + 1 );
+ }
+
+ px3.reset();
+ px3 = px2;
+ BOOST_TEST( px3 == px2 );
+ BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) );
+
+ boost::local_shared_ptr<X volatile[3]> px4( px2 );
+ BOOST_TEST( px4 == px2 );
+ BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) );
+
+ {
+ X volatile & rx = px4[ 2 ];
+ BOOST_TEST( &rx == px4.get() + 2 );
+ }
+
+ px4.reset();
+ px4 = px2;
+ BOOST_TEST( px4 == px2 );
+ BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) );
+
+ boost::local_shared_ptr<void> px5( px2 );
+ BOOST_TEST( px5 == px2 );
+ BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) );
+
+ px5.reset();
+ px5 = px2;
+ BOOST_TEST( px5 == px2 );
+ BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) );
+
+ boost::weak_ptr<X[3]> wp( px );
+ BOOST_TEST( wp.lock() == px );
+
+ boost::weak_ptr<X[3]> wp2( px2 );
+ BOOST_TEST( wp2.lock() == px2 );
+
+ wp2.reset();
+ wp2 = px2;
+ BOOST_TEST( wp2.lock() == px2 );
+
+ boost::weak_ptr<X const[3]> wp3( px2 );
+ BOOST_TEST( wp3.lock() == px2 );
+
+ wp3.reset();
+ wp3 = px2;
+ BOOST_TEST( wp3.lock() == px2 );
+
+ boost::weak_ptr<X volatile[3]> wp4( px2 );
+ BOOST_TEST( wp4.lock() == px2 );
+
+ wp4.reset();
+ wp4 = px2;
+ BOOST_TEST( wp4.lock() == px2 );
+
+ boost::weak_ptr<void> wp5( px2 );
+ BOOST_TEST( wp5.lock() == px2 );
+
+ wp5.reset();
+ wp5 = px2;
+ BOOST_TEST( wp5.lock() == px2 );
+
+ px2.reset();
+
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 3 );
+
+ px3.reset();
+ px4.reset();
+ px5.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ BOOST_TEST( wp2.lock() == 0 );
+ BOOST_TEST( wp3.lock() == 0 );
+ BOOST_TEST( wp4.lock() == 0 );
+ BOOST_TEST( wp5.lock() == 0 );
+ }
+
+ {
+ boost::local_shared_ptr<X[5]> px( new X[ 5 ], array_deleter< X >() );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 5 );
+
+ try
+ {
+ px[0].shared_from_this();
+ BOOST_ERROR( "px[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ px.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( array_deleter< X >::calls == 1 );
+ }
+
+ {
+ boost::local_shared_ptr<X[6]> px( new X[ 6 ], array_deleter< X >(), std::allocator< X >() );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 6 );
+
+ try
+ {
+ px[0].shared_from_this();
+ BOOST_ERROR( "px[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ px.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( array_deleter< X >::calls == 2 );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/lsp_array_test.cpp b/test/lsp_array_test.cpp
new file mode 100644
index 0000000..77728ea
--- /dev/null
+++ b/test/lsp_array_test.cpp
@@ -0,0 +1,311 @@
+//
+// lsp_array_test.cpp
+//
+// Copyright 2012, 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
+//
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <memory>
+#include <utility>
+
+class X: public boost::enable_shared_from_this< X >
+{
+public:
+
+ static int allocations;
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+ void* operator new[]( std::size_t n )
+ {
+ ++allocations;
+ return ::operator new[]( n );
+ }
+
+ void operator delete[]( void* p )
+ {
+ --allocations;
+ ::operator delete[]( p );
+ }
+
+private:
+
+ X( X const& );
+ X& operator=( X const& );
+};
+
+int X::allocations = 0;
+int X::instances = 0;
+
+template< class T> class array_deleter
+{
+public:
+
+ static int calls;
+
+ void operator()( T * p ) const
+ {
+ ++calls;
+ delete[] p;
+ }
+
+private:
+
+ template< class Y > void operator()( Y * p ) const;
+};
+
+template< class T > int array_deleter< T >::calls = 0;
+
+int main()
+{
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::local_shared_ptr<X[]> px;
+ BOOST_TEST( !px );
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ boost::local_shared_ptr<X[]> px2( new X[ 3 ] );
+ BOOST_TEST( px2 );
+
+ try
+ {
+ px2[0].shared_from_this();
+ BOOST_ERROR( "px2[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 3 );
+
+ {
+ X & rx = px2[ 0 ];
+ BOOST_TEST( &rx == px2.get() );
+ }
+
+ boost::local_shared_ptr<X const[]> px3( px2 );
+ BOOST_TEST( px3 == px2 );
+ BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) );
+
+ {
+ X const & rx = px3[ 1 ];
+ BOOST_TEST( &rx == px3.get() + 1 );
+ }
+
+ px3.reset();
+ px3 = px2;
+ BOOST_TEST( px3 == px2 );
+ BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) );
+
+ boost::local_shared_ptr<X volatile[]> px4( px2 );
+ BOOST_TEST( px4 == px2 );
+ BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) );
+
+ {
+ X volatile & rx = px4[ 2 ];
+ BOOST_TEST( &rx == px4.get() + 2 );
+ }
+
+ px4.reset();
+ px4 = px2;
+ BOOST_TEST( px4 == px2 );
+ BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) );
+
+ boost::local_shared_ptr<void> px5( px2 );
+ BOOST_TEST( px5 == px2 );
+ BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) );
+
+ px5.reset();
+ px5 = px2;
+ BOOST_TEST( px5 == px2 );
+ BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) );
+
+ boost::weak_ptr<X[]> wp( px );
+ BOOST_TEST( wp.lock() == px );
+
+ boost::weak_ptr<X[]> wp2( px2 );
+ BOOST_TEST( wp2.lock() == px2 );
+
+ wp2.reset();
+ wp2 = px2;
+ BOOST_TEST( wp2.lock() == px2 );
+
+ boost::weak_ptr<X const[]> wp3( px2 );
+ BOOST_TEST( wp3.lock() == px2 );
+
+ wp3.reset();
+ wp3 = px2;
+ BOOST_TEST( wp3.lock() == px2 );
+
+ boost::weak_ptr<X volatile[]> wp4( px2 );
+ BOOST_TEST( wp4.lock() == px2 );
+
+ wp4.reset();
+ wp4 = px2;
+ BOOST_TEST( wp4.lock() == px2 );
+
+ boost::weak_ptr<void> wp5( px2 );
+ BOOST_TEST( wp5.lock() == px2 );
+
+ wp5.reset();
+ wp5 = px2;
+ BOOST_TEST( wp5.lock() == px2 );
+
+ px2.reset();
+
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 3 );
+
+ px3.reset();
+ px4.reset();
+ px5.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ BOOST_TEST( wp2.lock() == 0 );
+ BOOST_TEST( wp3.lock() == 0 );
+ BOOST_TEST( wp4.lock() == 0 );
+ BOOST_TEST( wp5.lock() == 0 );
+ }
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ {
+ std::unique_ptr<X[]> px( new X[ 4 ] );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 4 );
+
+ boost::local_shared_ptr<X[]> px2( std::move( px ) );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 4 );
+ BOOST_TEST( px.get() == 0 );
+
+ try
+ {
+ px2[0].shared_from_this();
+ BOOST_ERROR( "px2[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ px2.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ std::unique_ptr<X[]> px( new X[ 4 ] );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 4 );
+
+ boost::local_shared_ptr<X[]> px2;
+ px2 = std::move( px );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 4 );
+ BOOST_TEST( px.get() == 0 );
+
+ try
+ {
+ px2[0].shared_from_this();
+ BOOST_ERROR( "px2[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ px2.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+ }
+
+#endif
+
+ {
+ boost::local_shared_ptr<X[]> px( new X[ 5 ], array_deleter< X >() );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 5 );
+
+ try
+ {
+ px[0].shared_from_this();
+ BOOST_ERROR( "px[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ px.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( array_deleter< X >::calls == 1 );
+ }
+
+ {
+ boost::local_shared_ptr<X[]> px( new X[ 6 ], array_deleter< X >(), std::allocator< X >() );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 6 );
+
+ try
+ {
+ px[0].shared_from_this();
+ BOOST_ERROR( "px[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ px.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( array_deleter< X >::calls == 2 );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/lsp_convertible_test.cpp b/test/lsp_convertible_test.cpp
new file mode 100644
index 0000000..4f5017a
--- /dev/null
+++ b/test/lsp_convertible_test.cpp
@@ -0,0 +1,108 @@
+#include <boost/config.hpp>
+
+// lsp_convertible_test.cpp
+//
+// Copyright 2012, 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
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+
+//
+
+class X;
+
+class B
+{
+};
+
+class D: public B
+{
+};
+
+using boost::is_convertible;
+
+#define TEST_CV_TRUE_( S1, T, S2, U ) \
+ BOOST_TEST(( is_convertible< S1<T>, S2<U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<const U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<const volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<const U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<const volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<const volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<const volatile U> >::value == true ));
+
+#define TEST_CV_FALSE_( S1, T, S2, U ) \
+ BOOST_TEST(( is_convertible< S1<T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<const volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<const volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<const volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<const volatile U> >::value == false ));
+
+using boost::local_shared_ptr;
+using boost::shared_ptr;
+using boost::weak_ptr;
+
+#define TEST_CV_TRUE( T, U ) \
+ TEST_CV_TRUE_( local_shared_ptr, T, local_shared_ptr, U ) \
+ TEST_CV_TRUE_( shared_ptr, T, local_shared_ptr, U )
+
+#define TEST_CV_FALSE( T, U ) \
+ TEST_CV_FALSE_( local_shared_ptr, T, local_shared_ptr, U ) \
+ TEST_CV_FALSE_( shared_ptr, T, local_shared_ptr, U )
+
+int main()
+{
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ TEST_CV_TRUE( X, X )
+ TEST_CV_TRUE( X, void )
+ TEST_CV_FALSE( void, X )
+ TEST_CV_TRUE( D, B )
+ TEST_CV_FALSE( B, D )
+
+ TEST_CV_TRUE( X[], X[] )
+ TEST_CV_FALSE( D[], B[] )
+
+ TEST_CV_TRUE( X[3], X[3] )
+ TEST_CV_FALSE( X[3], X[4] )
+ TEST_CV_FALSE( D[3], B[3] )
+
+ TEST_CV_TRUE( X[3], X[] )
+ TEST_CV_FALSE( X[], X[3] )
+
+ TEST_CV_TRUE( X[], void )
+ TEST_CV_FALSE( void, X[] )
+
+ TEST_CV_TRUE( X[3], void )
+ TEST_CV_FALSE( void, X[3] )
+
+#endif
+
+ return boost::report_errors();
+}
diff --git a/test/lsp_convertible_test2.cpp b/test/lsp_convertible_test2.cpp
new file mode 100644
index 0000000..2104b4e
--- /dev/null
+++ b/test/lsp_convertible_test2.cpp
@@ -0,0 +1,108 @@
+#include <boost/config.hpp>
+
+// lsp_convertible_test.cpp
+//
+// Copyright 2012, 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
+
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+
+//
+
+class X;
+
+class B
+{
+};
+
+class D: public B
+{
+};
+
+using boost::is_convertible;
+
+#define TEST_CV_TRUE_( S1, T, S2, U ) \
+ BOOST_TEST(( is_convertible< S1<T>, S2<U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<const U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<const volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<const U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<const volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<const volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<const volatile U> >::value == true ));
+
+#define TEST_CV_FALSE_( S1, T, S2, U ) \
+ BOOST_TEST(( is_convertible< S1<T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<const volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<const volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<const volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<const volatile U> >::value == false ));
+
+using boost::local_shared_ptr;
+using boost::shared_ptr;
+using boost::weak_ptr;
+
+#define TEST_CV_TRUE( T, U ) \
+ TEST_CV_TRUE_( local_shared_ptr, T, shared_ptr, U ) \
+ TEST_CV_TRUE_( local_shared_ptr, T, weak_ptr, U )
+
+#define TEST_CV_FALSE( T, U ) \
+ TEST_CV_FALSE_( local_shared_ptr, T, shared_ptr, U ) \
+ TEST_CV_FALSE_( local_shared_ptr, T, weak_ptr, U )
+
+int main()
+{
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+
+ TEST_CV_TRUE( X, X )
+ TEST_CV_TRUE( X, void )
+ TEST_CV_FALSE( void, X )
+ TEST_CV_TRUE( D, B )
+ TEST_CV_FALSE( B, D )
+
+ TEST_CV_TRUE( X[], X[] )
+ TEST_CV_FALSE( D[], B[] )
+
+ TEST_CV_TRUE( X[3], X[3] )
+ TEST_CV_FALSE( X[3], X[4] )
+ TEST_CV_FALSE( D[3], B[3] )
+
+ TEST_CV_TRUE( X[3], X[] )
+ TEST_CV_FALSE( X[], X[3] )
+
+ TEST_CV_TRUE( X[], void )
+ TEST_CV_FALSE( void, X[] )
+
+ TEST_CV_TRUE( X[3], void )
+ TEST_CV_FALSE( void, X[3] )
+
+#endif
+
+ return boost::report_errors();
+}
diff --git a/test/lw_mutex_test.cpp b/test/lw_mutex_test.cpp
new file mode 100644
index 0000000..a47ac1e
--- /dev/null
+++ b/test/lw_mutex_test.cpp
@@ -0,0 +1,28 @@
+//
+// lw_mutex_test.cpp
+//
+// Copyright 2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/detail/lightweight_mutex.hpp>
+
+// Sanity check only
+
+boost::detail::lightweight_mutex m1;
+
+int main()
+{
+ boost::detail::lightweight_mutex::scoped_lock lock1( m1 );
+
+ boost::detail::lightweight_mutex m2;
+ boost::detail::lightweight_mutex m3;
+
+ boost::detail::lightweight_mutex::scoped_lock lock2( m2 );
+ boost::detail::lightweight_mutex::scoped_lock lock3( m3 );
+
+ return 0;
+}
diff --git a/test/lw_thread_test.cpp b/test/lw_thread_test.cpp
new file mode 100644
index 0000000..1fe2274
--- /dev/null
+++ b/test/lw_thread_test.cpp
@@ -0,0 +1,36 @@
+
+// lw_thread_test.cpp
+//
+// Copyright 2018 Peter Dimov
+// Distributed under the Boost Software License, Version 1.0.
+
+#include <boost/detail/lightweight_thread.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr/detail/atomic_count.hpp>
+
+boost::detail::atomic_count count( 0 );
+
+void f()
+{
+ ++count;
+}
+
+int main()
+{
+ int const N = 4;
+ boost::detail::lw_thread_t th[ N ] = {};
+
+ for( int i = 0; i < N; ++i )
+ {
+ boost::detail::lw_thread_create( th[ i ], f );
+ }
+
+ for( int i = 0; i < N; ++i )
+ {
+ boost::detail::lw_thread_join( th[ i ] );
+ }
+
+ BOOST_TEST_EQ( count, N );
+
+ return boost::report_errors();
+}
diff --git a/test/lwm_win32_cs_test.cpp b/test/lwm_win32_cs_test.cpp
new file mode 100644
index 0000000..cd8be86
--- /dev/null
+++ b/test/lwm_win32_cs_test.cpp
@@ -0,0 +1,18 @@
+//
+// lwm_win32_cs_test.cpp
+//
+// 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)
+//
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# include <windows.h>
+# include <boost/smart_ptr/detail/lwm_win32_cs.hpp>
+#endif
+
+int main()
+{
+}
diff --git a/test/make_local_shared_array_esft_test.cpp b/test/make_local_shared_array_esft_test.cpp
new file mode 100644
index 0000000..5106f39
--- /dev/null
+++ b/test/make_local_shared_array_esft_test.cpp
@@ -0,0 +1,66 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/enable_shared_from_this.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+
+class type
+ : public boost::enable_shared_from_this<type> {
+public:
+ static unsigned instances;
+
+ type() {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ BOOST_TEST(type::instances == 0);
+ {
+ boost::local_shared_ptr<type[]> result =
+ boost::make_local_shared<type[]>(3);
+ try {
+ result[0].shared_from_this();
+ BOOST_ERROR("shared_from_this did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 3);
+ }
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ boost::local_shared_ptr<type[3]> result =
+ boost::make_local_shared_noinit<type[3]>();
+ try {
+ result[0].shared_from_this();
+ BOOST_ERROR("shared_from_this did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 3);
+ }
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/make_local_shared_array_noinit_test.cpp b/test/make_local_shared_array_noinit_test.cpp
new file mode 100644
index 0000000..f4a07a2
--- /dev/null
+++ b/test/make_local_shared_array_noinit_test.cpp
@@ -0,0 +1,216 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/align/is_aligned.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+#include <boost/smart_ptr/weak_ptr.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+
+class type {
+public:
+ static unsigned instances;
+
+ type()
+ : value_(0.0) {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+ void set(long double value) {
+ value_ = value;
+ }
+
+ long double get() const {
+ return value_;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+
+ long double value_;
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ {
+ boost::local_shared_ptr<int[]> result =
+ boost::make_local_shared_noinit<int[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<int[3]> result =
+ boost::make_local_shared_noinit<int[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<int[][2]> result =
+ boost::make_local_shared_noinit<int[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<int[2][2]> result =
+ boost::make_local_shared_noinit<int[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<const int[]> result =
+ boost::make_local_shared_noinit<const int[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<const int[3]> result =
+ boost::make_local_shared_noinit<const int[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<const int[][2]> result =
+ boost::make_local_shared_noinit<const int[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<const int[2][2]> result =
+ boost::make_local_shared_noinit<const int[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::local_shared_ptr<type[]> result =
+ boost::make_local_shared_noinit<type[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[3]> result =
+ boost::make_local_shared_noinit<type[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[3]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[][2]> result =
+ boost::make_local_shared_noinit<type[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<type[][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[2][2]> result =
+ boost::make_local_shared_noinit<type[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<type[2][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[]> result =
+ boost::make_local_shared_noinit<const type[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<const type[]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[3]> result =
+ boost::make_local_shared_noinit<const type[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<const type[3]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[][2]> result =
+ boost::make_local_shared_noinit<const type[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<const type[][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[2][2]> result =
+ boost::make_local_shared_noinit<const type[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<const type[2][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/make_local_shared_array_test.cpp b/test/make_local_shared_array_test.cpp
new file mode 100644
index 0000000..2781763
--- /dev/null
+++ b/test/make_local_shared_array_test.cpp
@@ -0,0 +1,238 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/align/is_aligned.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+#include <boost/smart_ptr/weak_ptr.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+
+class type {
+public:
+ static unsigned instances;
+
+ type()
+ : value_(0.0) {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+ void set(long double value) {
+ value_ = value;
+ }
+
+ long double get() const {
+ return value_;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+
+ long double value_;
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ {
+ boost::local_shared_ptr<int[]> result =
+ boost::make_local_shared<int[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::local_shared_ptr<int[3]> result =
+ boost::make_local_shared<int[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::local_shared_ptr<int[][2]> result =
+ boost::make_local_shared<int[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::local_shared_ptr<int[2][2]> result =
+ boost::make_local_shared<int[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::local_shared_ptr<const int[]> result =
+ boost::make_local_shared<const int[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::local_shared_ptr<const int[3]> result =
+ boost::make_local_shared<const int[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::local_shared_ptr<const int[][2]> result =
+ boost::make_local_shared<const int[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::local_shared_ptr<const int[2][2]> result =
+ boost::make_local_shared<const int[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::local_shared_ptr<type[]> result =
+ boost::make_local_shared<type[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[]> w1 = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[3]> result =
+ boost::make_local_shared<type[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[3]> w1 = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[][2]> result =
+ boost::make_local_shared<type[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<type[2][2]> result =
+ boost::make_local_shared<type[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[]> result =
+ boost::make_local_shared<const type[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[3]> result =
+ boost::make_local_shared<const type[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[][2]> result =
+ boost::make_local_shared<const type[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::local_shared_ptr<const type[2][2]> result =
+ boost::make_local_shared<const type[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.local_use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/make_local_shared_array_throws_test.cpp b/test/make_local_shared_array_throws_test.cpp
new file mode 100644
index 0000000..e1841df
--- /dev/null
+++ b/test/make_local_shared_array_throws_test.cpp
@@ -0,0 +1,93 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+
+class type {
+public:
+ static unsigned instances;
+
+ type() {
+ if (instances == 5) {
+ throw true;
+ }
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ try {
+ boost::make_local_shared<type[]>(6);
+ BOOST_ERROR("make_local_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::make_local_shared<type[][2]>(3);
+ BOOST_ERROR("make_local_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::make_local_shared<type[6]>();
+ BOOST_ERROR("make_local_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::make_local_shared<type[3][2]>();
+ BOOST_ERROR("make_local_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::make_local_shared_noinit<type[]>(6);
+ BOOST_ERROR("make_local_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::make_local_shared_noinit<type[][2]>(3);
+ BOOST_ERROR("make_local_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::make_local_shared_noinit<type[6]>();
+ BOOST_ERROR("make_local_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::make_local_shared_noinit<type[3][2]>();
+ BOOST_ERROR("make_local_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/make_local_shared_array_value_test.cpp b/test/make_local_shared_array_value_test.cpp
new file mode 100644
index 0000000..ab07460
--- /dev/null
+++ b/test/make_local_shared_array_value_test.cpp
@@ -0,0 +1,55 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+
+int main()
+{
+ {
+ boost::local_shared_ptr<int[]> result =
+ boost::make_local_shared<int[]>(4, 1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ {
+ boost::local_shared_ptr<int[4]> result =
+ boost::make_local_shared<int[4]>(1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ {
+ boost::local_shared_ptr<const int[]> result =
+ boost::make_local_shared<const int[]>(4, 1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ {
+ boost::local_shared_ptr<const int[4]> result =
+ boost::make_local_shared<const int[4]>(1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/make_local_shared_arrays_test.cpp b/test/make_local_shared_arrays_test.cpp
new file mode 100644
index 0000000..986b88f
--- /dev/null
+++ b/test/make_local_shared_arrays_test.cpp
@@ -0,0 +1,56 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+ !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+
+int main()
+{
+ {
+ boost::local_shared_ptr<int[][2]> result =
+ boost::make_local_shared<int[][2]>(2, {0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ {
+ boost::local_shared_ptr<int[2][2]> result =
+ boost::make_local_shared<int[2][2]>({0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ {
+ boost::local_shared_ptr<const int[][2]> result =
+ boost::make_local_shared<const int[][2]>(2, {0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ {
+ boost::local_shared_ptr<const int[2][2]> result =
+ boost::make_local_shared<const int[2][2]>({0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/make_local_shared_esft_test.cpp b/test/make_local_shared_esft_test.cpp
new file mode 100644
index 0000000..b5e130e
--- /dev/null
+++ b/test/make_local_shared_esft_test.cpp
@@ -0,0 +1,308 @@
+// make_local_shared_esft_test.cpp
+//
+// Copyright 2007-2009, 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
+
+#include <boost/config.hpp>
+
+#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) || defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES )
+
+int main()
+{
+}
+
+#else
+
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+class X: public boost::enable_shared_from_this<X>
+{
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+
+public:
+
+ static int instances;
+
+ explicit X( int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0 )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+};
+
+int X::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_local_shared< X >();
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_local_shared_noinit< X >();
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_local_shared< X >( 1 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2, 3 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2, 3, 4 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2, 3, 4, 5 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6, 7 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8, 9 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ return boost::report_errors();
+}
+
+#endif
diff --git a/test/make_local_shared_test.cpp b/test/make_local_shared_test.cpp
new file mode 100644
index 0000000..e972c0d
--- /dev/null
+++ b/test/make_local_shared_test.cpp
@@ -0,0 +1,268 @@
+// make_local_shared_test.cpp
+//
+// Copyright 2007-2009, 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
+
+#include <boost/config.hpp>
+
+#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) || defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES )
+
+int main()
+{
+}
+
+#else
+
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_local_shared.hpp>
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <cstddef>
+
+class X
+{
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+
+ void * operator new( std::size_t n )
+ {
+ // lack of this definition causes link errors on Comeau C++
+ BOOST_ERROR( "private X::new called" );
+ return ::operator new( n );
+ }
+
+ void operator delete( void * p )
+ {
+ // lack of this definition causes link errors on MSVC
+ BOOST_ERROR( "private X::delete called" );
+ ::operator delete( p );
+ }
+
+public:
+
+ static int instances;
+
+ int v;
+
+ explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+};
+
+int X::instances = 0;
+
+template<class T> static long use_count( boost::local_shared_ptr<T> const & p )
+{
+ return boost::shared_ptr<T>( p ).use_count() - 1;
+}
+
+int main()
+{
+ {
+ boost::local_shared_ptr< int > pi = boost::make_local_shared< int >();
+
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.local_use_count() == 1 );
+ BOOST_TEST( use_count( pi ) == 1 );
+
+ BOOST_TEST( *pi == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< int > pi = boost::make_local_shared_noinit< int >();
+
+ BOOST_TEST( pi.get() != 0 );
+ }
+
+ {
+ boost::local_shared_ptr< int > pi = boost::make_local_shared< int >( 5 );
+
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.local_use_count() == 1 );
+ BOOST_TEST( use_count( pi ) == 1 );
+
+ BOOST_TEST( *pi == 5 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::local_shared_ptr< X > pi = boost::make_local_shared< X >();
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.local_use_count() == 1 );
+ BOOST_TEST( use_count( pi ) == 1 );
+ BOOST_TEST( pi->v == 0 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::make_local_shared_noinit< X >();
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.local_use_count() == 1 );
+ BOOST_TEST( use_count( pi ) == 1 );
+ BOOST_TEST( pi->v == 0 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.local_use_count() == 1 );
+ BOOST_TEST( use_count( pi ) == 1 );
+ BOOST_TEST( pi->v == 1 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.local_use_count() == 1 );
+ BOOST_TEST( use_count( pi ) == 1 );
+ BOOST_TEST( pi->v == 1+2 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2, 3 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.local_use_count() == 1 );
+ BOOST_TEST( use_count( pi ) == 1 );
+ BOOST_TEST( pi->v == 1+2+3 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2, 3, 4 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.local_use_count() == 1 );
+ BOOST_TEST( use_count( pi ) == 1 );
+ BOOST_TEST( pi->v == 1+2+3+4 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2, 3, 4, 5 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.local_use_count() == 1 );
+ BOOST_TEST( use_count( pi ) == 1 );
+ BOOST_TEST( pi->v == 1+2+3+4+5 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.local_use_count() == 1 );
+ BOOST_TEST( use_count( pi ) == 1 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6, 7 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.local_use_count() == 1 );
+ BOOST_TEST( use_count( pi ) == 1 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.local_use_count() == 1 );
+ BOOST_TEST( use_count( pi ) == 1 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8, 9 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.local_use_count() == 1 );
+ BOOST_TEST( use_count( pi ) == 1 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ return boost::report_errors();
+}
+
+#endif
diff --git a/test/make_shared_array_esft_test.cpp b/test/make_shared_array_esft_test.cpp
new file mode 100644
index 0000000..f52e3cf
--- /dev/null
+++ b/test/make_shared_array_esft_test.cpp
@@ -0,0 +1,57 @@
+/*
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/enable_shared_from_this.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+class type
+ : public boost::enable_shared_from_this<type> {
+public:
+ static unsigned instances;
+
+ type() {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ BOOST_TEST(type::instances == 0);
+ {
+ boost::shared_ptr<type[]> result =
+ boost::make_shared<type[]>(3);
+ try {
+ result[0].shared_from_this();
+ BOOST_ERROR("shared_from_this did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 3);
+ }
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ boost::shared_ptr<type[3]> result =
+ boost::make_shared_noinit<type[3]>();
+ try {
+ result[0].shared_from_this();
+ BOOST_ERROR("shared_from_this did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 3);
+ }
+ }
+ return boost::report_errors();
+}
diff --git a/test/make_shared_array_noinit_test.cpp b/test/make_shared_array_noinit_test.cpp
new file mode 100644
index 0000000..757e798
--- /dev/null
+++ b/test/make_shared_array_noinit_test.cpp
@@ -0,0 +1,207 @@
+/*
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/align/is_aligned.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/smart_ptr/weak_ptr.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+
+class type {
+public:
+ static unsigned instances;
+
+ type()
+ : value_(0.0) {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+ void set(long double value) {
+ value_ = value;
+ }
+
+ long double get() const {
+ return value_;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+
+ long double value_;
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ {
+ boost::shared_ptr<int[]> result =
+ boost::make_shared_noinit<int[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<int[3]> result =
+ boost::make_shared_noinit<int[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<int[][2]> result =
+ boost::make_shared_noinit<int[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<int[2][2]> result =
+ boost::make_shared_noinit<int[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<const int[]> result =
+ boost::make_shared_noinit<const int[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<const int[3]> result =
+ boost::make_shared_noinit<const int[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<const int[][2]> result =
+ boost::make_shared_noinit<const int[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<const int[2][2]> result =
+ boost::make_shared_noinit<const int[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ }
+ {
+ boost::shared_ptr<type[]> result =
+ boost::make_shared_noinit<type[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[3]> result =
+ boost::make_shared_noinit<type[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[3]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[][2]> result =
+ boost::make_shared_noinit<type[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<type[][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[2][2]> result =
+ boost::make_shared_noinit<type[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<type[2][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[]> result =
+ boost::make_shared_noinit<const type[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<const type[]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[3]> result =
+ boost::make_shared_noinit<const type[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<const type[3]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[][2]> result =
+ boost::make_shared_noinit<const type[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<const type[][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[2][2]> result =
+ boost::make_shared_noinit<const type[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ boost::weak_ptr<const type[2][2]> other = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
diff --git a/test/make_shared_array_test.cpp b/test/make_shared_array_test.cpp
new file mode 100644
index 0000000..c6bac24
--- /dev/null
+++ b/test/make_shared_array_test.cpp
@@ -0,0 +1,229 @@
+/*
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/align/is_aligned.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/smart_ptr/weak_ptr.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+
+class type {
+public:
+ static unsigned instances;
+
+ type()
+ : value_(0.0) {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+ void set(long double value) {
+ value_ = value;
+ }
+
+ long double get() const {
+ return value_;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+
+ long double value_;
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ {
+ boost::shared_ptr<int[]> result =
+ boost::make_shared<int[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::shared_ptr<int[3]> result =
+ boost::make_shared<int[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::shared_ptr<int[][2]> result =
+ boost::make_shared<int[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::shared_ptr<int[2][2]> result =
+ boost::make_shared<int[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::shared_ptr<const int[]> result =
+ boost::make_shared<const int[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::shared_ptr<const int[3]> result =
+ boost::make_shared<const int[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ boost::shared_ptr<const int[][2]> result =
+ boost::make_shared<const int[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::shared_ptr<const int[2][2]> result =
+ boost::make_shared<const int[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<int>::value));
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ boost::shared_ptr<type[]> result =
+ boost::make_shared<type[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[]> w1 = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[3]> result =
+ boost::make_shared<type[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ boost::weak_ptr<type[3]> w1 = result;
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[][2]> result =
+ boost::make_shared<type[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<type[2][2]> result =
+ boost::make_shared<type[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[]> result =
+ boost::make_shared<const type[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[3]> result =
+ boost::make_shared<const type[3]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[][2]> result =
+ boost::make_shared<const type[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ {
+ boost::shared_ptr<const type[2][2]> result =
+ boost::make_shared<const type[2][2]>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result.use_count() == 1);
+ BOOST_TEST(boost::alignment::is_aligned(result.get(),
+ boost::alignment_of<type>::value));
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
diff --git a/test/make_shared_array_throws_test.cpp b/test/make_shared_array_throws_test.cpp
new file mode 100644
index 0000000..a754360
--- /dev/null
+++ b/test/make_shared_array_throws_test.cpp
@@ -0,0 +1,84 @@
+/*
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+class type {
+public:
+ static unsigned instances;
+
+ type() {
+ if (instances == 5) {
+ throw true;
+ }
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ try {
+ boost::make_shared<type[]>(6);
+ BOOST_ERROR("make_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::make_shared<type[][2]>(3);
+ BOOST_ERROR("make_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::make_shared<type[6]>();
+ BOOST_ERROR("make_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::make_shared<type[3][2]>();
+ BOOST_ERROR("make_shared did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::make_shared_noinit<type[]>(6);
+ BOOST_ERROR("make_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::make_shared_noinit<type[][2]>(3);
+ BOOST_ERROR("make_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::make_shared_noinit<type[6]>();
+ BOOST_ERROR("make_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ try {
+ boost::make_shared_noinit<type[3][2]>();
+ BOOST_ERROR("make_shared_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
diff --git a/test/make_shared_array_tmp_test.cpp b/test/make_shared_array_tmp_test.cpp
new file mode 100644
index 0000000..6e776bb
--- /dev/null
+++ b/test/make_shared_array_tmp_test.cpp
@@ -0,0 +1,43 @@
+// make_shared_array_tmp_test.cpp
+//
+// 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
+
+#include <boost/make_shared.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+struct X
+{
+ static int destroyed;
+
+ ~X()
+ {
+ ++destroyed;
+ }
+};
+
+int X::destroyed = 0;
+
+int main()
+{
+ {
+ X::destroyed = 0;
+
+ boost::make_shared< X[3] >();
+
+ BOOST_TEST_EQ( X::destroyed, 3 );
+ }
+
+ {
+ X::destroyed = 0;
+
+ boost::make_shared< X[] >( 3 );
+
+ BOOST_TEST_EQ( X::destroyed, 3 );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/make_shared_array_value_test.cpp b/test/make_shared_array_value_test.cpp
new file mode 100644
index 0000000..44d12d3
--- /dev/null
+++ b/test/make_shared_array_value_test.cpp
@@ -0,0 +1,46 @@
+/*
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+int main()
+{
+ {
+ boost::shared_ptr<int[]> result =
+ boost::make_shared<int[]>(4, 1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ {
+ boost::shared_ptr<int[4]> result =
+ boost::make_shared<int[4]>(1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ {
+ boost::shared_ptr<const int[]> result =
+ boost::make_shared<const int[]>(4, 1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ {
+ boost::shared_ptr<const int[4]> result =
+ boost::make_shared<const int[4]>(1);
+ BOOST_TEST(result[0] == 1);
+ BOOST_TEST(result[1] == 1);
+ BOOST_TEST(result[2] == 1);
+ BOOST_TEST(result[3] == 1);
+ }
+ return boost::report_errors();
+}
diff --git a/test/make_shared_arrays_test.cpp b/test/make_shared_arrays_test.cpp
new file mode 100644
index 0000000..598b974
--- /dev/null
+++ b/test/make_shared_arrays_test.cpp
@@ -0,0 +1,54 @@
+/*
+Copyright 2012-2015 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+int main()
+{
+ {
+ boost::shared_ptr<int[][2]> result =
+ boost::make_shared<int[][2]>(2, {0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ {
+ boost::shared_ptr<int[2][2]> result =
+ boost::make_shared<int[2][2]>({0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ {
+ boost::shared_ptr<const int[][2]> result =
+ boost::make_shared<const int[][2]>(2, {0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ {
+ boost::shared_ptr<const int[2][2]> result =
+ boost::make_shared<const int[2][2]>({0, 1});
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 1);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 1);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/make_shared_esft_test.cpp b/test/make_shared_esft_test.cpp
new file mode 100644
index 0000000..71b2912
--- /dev/null
+++ b/test/make_shared_esft_test.cpp
@@ -0,0 +1,296 @@
+// make_shared_esft_test.cpp
+//
+// Copyright 2007-2009 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+class X: public boost::enable_shared_from_this<X>
+{
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+
+public:
+
+ static int instances;
+
+ explicit X( int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0 )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+};
+
+int X::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_shared< X >();
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_shared_noinit< X >();
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_shared< X >( 1 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8, 9 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = px->shared_from_this();
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+
+ px.reset();
+ BOOST_TEST( X::instances == 1 );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "px->shared_from_this() failed" );
+ }
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ return boost::report_errors();
+}
diff --git a/test/make_shared_fp_test.cpp b/test/make_shared_fp_test.cpp
new file mode 100644
index 0000000..f443d34
--- /dev/null
+++ b/test/make_shared_fp_test.cpp
@@ -0,0 +1,19 @@
+//
+// make_shared_fp_test.cpp
+//
+// Copyright 2010 Georg Fritzsche
+//
+// 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
+//
+
+
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+
+int main()
+{
+ typedef boost::shared_ptr<int>(*FP)();
+ FP fp = boost::make_shared<int>;
+}
diff --git a/test/make_shared_move_emulation_test.cpp b/test/make_shared_move_emulation_test.cpp
new file mode 100644
index 0000000..c607e05
--- /dev/null
+++ b/test/make_shared_move_emulation_test.cpp
@@ -0,0 +1,81 @@
+// make_shared_move_emulation_test.cpp - a test of make_shared
+// semi-perfect forwarding of constructor arguments when using a C++03
+// compiler with move emulation.
+// Note the "semi": it means moving temporaries (real r-values) doesn't work.
+//
+// Copyright 2016 Giel van Schijndel
+//
+// 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/shared_ptr.hpp>
+
+class movearg
+{
+private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(movearg)
+public:
+ movearg()
+ {}
+ movearg(BOOST_RV_REF(movearg))
+ {}
+ movearg& operator=(BOOST_RV_REF(movearg))
+ {
+ return *this;
+ }
+};
+
+class ByVal
+{
+public:
+ ByVal(movearg) {}
+};
+
+class ByRef
+{
+public:
+ enum constructor_id
+ {
+ move_constructor,
+ const_ref_constructor
+ };
+
+ ByRef(BOOST_RV_REF(movearg)): constructed_by_(move_constructor)
+ {}
+ ByRef(const movearg &arg): constructed_by_(const_ref_constructor)
+ {}
+
+ constructor_id constructed_by_;
+};
+
+int main()
+{
+ {
+ movearg a;
+ boost::shared_ptr< ByVal > x = boost::make_shared< ByVal >(boost::move(a));
+ }
+ {
+ movearg a;
+ boost::shared_ptr< ByRef > x = boost::make_shared< ByRef >(boost::move(a));
+ BOOST_TEST( x->constructed_by_ == ByRef::move_constructor);
+ }
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+ {
+ boost::shared_ptr< ByVal > x = boost::make_shared< ByVal >(movearg());
+ boost::shared_ptr< ByRef > y = boost::make_shared< ByRef >(movearg());
+ BOOST_TEST( y->constructed_by_ == ByRef::move_constructor);
+ }
+#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+ {
+ const movearg ca;
+ boost::shared_ptr< ByRef > x = boost::make_shared< ByRef >(ca);
+ BOOST_TEST( x->constructed_by_ == ByRef::const_ref_constructor);
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/make_shared_msvc_test.cpp b/test/make_shared_msvc_test.cpp
new file mode 100644
index 0000000..84de4a5
--- /dev/null
+++ b/test/make_shared_msvc_test.cpp
@@ -0,0 +1,19 @@
+//
+// make_shared_msvc_test.cpp
+//
+// 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
+//
+
+template<class T> struct value
+{
+};
+
+#include <boost/make_shared.hpp>
+
+int main()
+{
+}
diff --git a/test/make_shared_perfect_forwarding_test.cpp b/test/make_shared_perfect_forwarding_test.cpp
new file mode 100644
index 0000000..b7ad05d
--- /dev/null
+++ b/test/make_shared_perfect_forwarding_test.cpp
@@ -0,0 +1,98 @@
+// make_shared_perfect_forwarding_test.cpp - a test of make_shared
+// perfect forwarding of constructor arguments when using a C++0x
+// compiler.
+//
+// Copyright 2009 Frank Mori Hess
+//
+// 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/shared_ptr.hpp>
+
+#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+int main()
+{
+ return 0;
+}
+
+#else // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+class myarg
+{
+public:
+ myarg()
+ {}
+private:
+ myarg(myarg && other)
+ {}
+ myarg& operator=(myarg && other)
+ {
+ return *this;
+ }
+ myarg(const myarg & other)
+ {}
+ myarg& operator=(const myarg & other)
+ {
+ return *this;
+ }
+};
+
+class X
+{
+public:
+ enum constructor_id
+ {
+ move_constructor,
+ const_ref_constructor,
+ ref_constructor
+ };
+
+ X(myarg &&arg): constructed_by_(move_constructor)
+ {}
+ X(const myarg &arg): constructed_by_(const_ref_constructor)
+ {}
+ X(myarg &arg): constructed_by_(ref_constructor)
+ {}
+
+ constructor_id constructed_by_;
+};
+
+struct Y
+{
+ Y(int &value): ref(value)
+ {}
+ int &ref;
+};
+
+int main()
+{
+ {
+ myarg a;
+ boost::shared_ptr< X > x = boost::make_shared< X >(a);
+ BOOST_TEST( x->constructed_by_ == X::ref_constructor);
+ }
+ {
+ const myarg ca;
+ boost::shared_ptr< X > x = boost::make_shared< X >(ca);
+ BOOST_TEST( x->constructed_by_ == X::const_ref_constructor);
+ }
+ {
+ boost::shared_ptr< X > x = boost::make_shared< X >(myarg());
+ BOOST_TEST( x->constructed_by_ == X::move_constructor);
+ }
+ {
+ int value = 1;
+ boost::shared_ptr< Y > y = boost::make_shared< Y >(value);
+ BOOST_TEST( y->ref == 1 && value == y->ref );
+ ++y->ref;
+ BOOST_TEST( value == y->ref );
+ }
+
+ return boost::report_errors();
+}
+
+#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
diff --git a/test/make_shared_test.cpp b/test/make_shared_test.cpp
new file mode 100644
index 0000000..9e3cdd3
--- /dev/null
+++ b/test/make_shared_test.cpp
@@ -0,0 +1,239 @@
+// make_shared_test.cpp
+//
+// Copyright 2007-2009 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <cstddef>
+
+class X
+{
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+
+ void * operator new( std::size_t n )
+ {
+ // lack of this definition causes link errors on Comeau C++
+ BOOST_ERROR( "private X::new called" );
+ return ::operator new( n );
+ }
+
+ void operator delete( void * p )
+ {
+ // lack of this definition causes link errors on MSVC
+ BOOST_ERROR( "private X::delete called" );
+ ::operator delete( p );
+ }
+
+public:
+
+ static int instances;
+
+ int v;
+
+ explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+};
+
+int X::instances = 0;
+
+int main()
+{
+ {
+ boost::shared_ptr< int > pi = boost::make_shared< int >();
+
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.use_count() == 1 );
+
+ BOOST_TEST( *pi == 0 );
+ }
+
+ {
+ boost::shared_ptr< int > pi = boost::make_shared_noinit< int >();
+
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.use_count() == 1 );
+ }
+
+ {
+ boost::shared_ptr< int > pi = boost::make_shared< int >( 5 );
+
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.use_count() == 1 );
+
+ BOOST_TEST( *pi == 5 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr< X > pi = boost::make_shared< X >();
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.use_count() == 1 );
+ BOOST_TEST( pi->v == 0 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::make_shared_noinit< X >();
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.use_count() == 1 );
+ BOOST_TEST( pi->v == 0 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::make_shared< X >( 1 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.use_count() == 1 );
+ BOOST_TEST( pi->v == 1 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.use_count() == 1 );
+ BOOST_TEST( pi->v == 1+2 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.use_count() == 1 );
+ BOOST_TEST( pi->v == 1+2+3 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.use_count() == 1 );
+ BOOST_TEST( pi->v == 1+2+3+4 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.use_count() == 1 );
+ BOOST_TEST( pi->v == 1+2+3+4+5 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.use_count() == 1 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.use_count() == 1 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.use_count() == 1 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > pi = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8, 9 );
+ boost::weak_ptr<X> wp( pi );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( pi.get() != 0 );
+ BOOST_TEST( pi.use_count() == 1 );
+ BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
+
+ pi.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/make_unique_args_test.cpp b/test/make_unique_args_test.cpp
new file mode 100644
index 0000000..6e46612
--- /dev/null
+++ b/test/make_unique_args_test.cpp
@@ -0,0 +1,155 @@
+/*
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_SMART_PTR)
+#include <boost/core/lightweight_test.hpp>
+#include <boost/smart_ptr/make_unique.hpp>
+
+class type {
+public:
+ static unsigned instances;
+
+ type(int v1 = 0,
+ int v2 = 0,
+ int v3 = 0,
+ int v4 = 0,
+ int v5 = 0,
+ int v6 = 0,
+ int v7 = 0,
+ int v8 = 0,
+ int v9 = 0)
+ : sum_(v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9) {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+ int sum() const {
+ return sum_;
+ }
+
+private:
+ int sum_;
+
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ BOOST_TEST(type::instances == 0);
+ {
+ std::unique_ptr<type> result = boost::make_unique<type>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 1);
+ BOOST_TEST(result->sum() == 0);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ {
+ std::unique_ptr<type> result = boost::make_unique<type>(1);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 1);
+ BOOST_TEST(result->sum() == 1);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+
+ {
+ std::unique_ptr<type> result = boost::make_unique<type>(1, 2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 1);
+ BOOST_TEST(result->sum() == 1 + 2);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+
+ {
+ std::unique_ptr<type> result =
+ boost::make_unique<type>(1, 2, 3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 1);
+ BOOST_TEST(result->sum() == 1 + 2 + 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+
+ {
+ std::unique_ptr<type> result =
+ boost::make_unique<type>(1, 2, 3, 4);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 1);
+ BOOST_TEST(result->sum() == 1 + 2 + 3 + 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+
+ {
+ std::unique_ptr<type> result =
+ boost::make_unique<type>(1, 2, 3, 4, 5);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 1);
+ BOOST_TEST(result->sum() == 1 + 2 + 3 + 4 + 5);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+
+ {
+ std::unique_ptr<type> result =
+ boost::make_unique<type>(1, 2, 3, 4, 5, 6);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 1);
+ BOOST_TEST(result->sum() == 1 + 2 + 3 + 4 + 5 + 6);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+
+ {
+ std::unique_ptr<type> result =
+ boost::make_unique<type>(1, 2, 3, 4, 5, 6, 7);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 1);
+ BOOST_TEST(result->sum() == 1 + 2 + 3 + 4 + 5 + 6 + 7);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+
+ {
+ std::unique_ptr<type> result =
+ boost::make_unique<type>(1, 2, 3, 4, 5, 6, 7, 8);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 1);
+ BOOST_TEST(result->sum() == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+
+ {
+ std::unique_ptr<type> result =
+ boost::make_unique<type>(1, 2, 3, 4, 5, 6, 7, 8, 9);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 1);
+ BOOST_TEST(result->sum() == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+#endif
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/make_unique_array_noinit_test.cpp b/test/make_unique_array_noinit_test.cpp
new file mode 100644
index 0000000..44ac66e
--- /dev/null
+++ b/test/make_unique_array_noinit_test.cpp
@@ -0,0 +1,87 @@
+/*
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_SMART_PTR)
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr/make_unique.hpp>
+
+class type {
+public:
+ static unsigned instances;
+
+ type() {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ {
+ std::unique_ptr<int[]> result =
+ boost::make_unique_noinit<int[]>(3);
+ BOOST_TEST(result.get() != 0);
+ }
+ {
+ std::unique_ptr<int[][2]> result =
+ boost::make_unique_noinit<int[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ std::unique_ptr<type[]> result =
+ boost::make_unique_noinit<type[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ std::unique_ptr<type[][2]> result =
+ boost::make_unique_noinit<type[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ std::unique_ptr<const type[]> result =
+ boost::make_unique_noinit<const type[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ std::unique_ptr<const type[][2]> result =
+ boost::make_unique_noinit<const type[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/make_unique_array_test.cpp b/test/make_unique_array_test.cpp
new file mode 100644
index 0000000..447f79d
--- /dev/null
+++ b/test/make_unique_array_test.cpp
@@ -0,0 +1,110 @@
+/*
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_SMART_PTR)
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr/make_unique.hpp>
+
+class type {
+public:
+ static unsigned instances;
+
+ type() {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ {
+ std::unique_ptr<int[]> result = boost::make_unique<int[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ std::unique_ptr<int[][2]> result =
+ boost::make_unique<int[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ {
+ std::unique_ptr<const int[]> result =
+ boost::make_unique<const int[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result[0] == 0);
+ BOOST_TEST(result[1] == 0);
+ BOOST_TEST(result[2] == 0);
+ }
+ {
+ std::unique_ptr<const int[][2]> result =
+ boost::make_unique<const int[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result[0][0] == 0);
+ BOOST_TEST(result[0][1] == 0);
+ BOOST_TEST(result[1][0] == 0);
+ BOOST_TEST(result[1][1] == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ std::unique_ptr<type[]> result =
+ boost::make_unique<type[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ std::unique_ptr<type[][2]> result =
+ boost::make_unique<type[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ std::unique_ptr<const type[]> result =
+ boost::make_unique<const type[]>(3);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 3);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ std::unique_ptr<const type[][2]> result =
+ boost::make_unique<const type[][2]>(2);
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 4);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/make_unique_array_throws_test.cpp b/test/make_unique_array_throws_test.cpp
new file mode 100644
index 0000000..df4ab26
--- /dev/null
+++ b/test/make_unique_array_throws_test.cpp
@@ -0,0 +1,72 @@
+/*
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_SMART_PTR)
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr/make_unique.hpp>
+
+class type {
+public:
+ static unsigned instances;
+
+ type() {
+ if (instances == 5) {
+ throw true;
+ }
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ BOOST_TEST(type::instances == 0);
+ try {
+ boost::make_unique<type[]>(6);
+ BOOST_ERROR("make_unique did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ try {
+ boost::make_unique<type[][2]>(3);
+ BOOST_ERROR("make_unique did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ try {
+ boost::make_unique_noinit<type[]>(6);
+ BOOST_ERROR("make_unique_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ try {
+ boost::make_unique_noinit<type[][2]>(3);
+ BOOST_ERROR("make_unique_noinit did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/make_unique_noinit_test.cpp b/test/make_unique_noinit_test.cpp
new file mode 100644
index 0000000..a7cd828
--- /dev/null
+++ b/test/make_unique_noinit_test.cpp
@@ -0,0 +1,63 @@
+/*
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_SMART_PTR)
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr/make_unique.hpp>
+
+class type {
+public:
+ static unsigned instances;
+
+ type() {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ {
+ std::unique_ptr<int> result = boost::make_unique_noinit<int>();
+ BOOST_TEST(result.get() != 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ std::unique_ptr<type> result =
+ boost::make_unique_noinit<type>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 1);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ std::unique_ptr<const type> result =
+ boost::make_unique_noinit<const type>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 1);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/make_unique_test.cpp b/test/make_unique_test.cpp
new file mode 100644
index 0000000..74c6033
--- /dev/null
+++ b/test/make_unique_test.cpp
@@ -0,0 +1,70 @@
+/*
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_SMART_PTR)
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr/make_unique.hpp>
+
+class type {
+public:
+ static unsigned instances;
+
+ type() {
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ {
+ std::unique_ptr<int> result = boost::make_unique<int>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(*result == 0);
+ }
+ {
+ std::unique_ptr<const int> result =
+ boost::make_unique<const int>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(*result == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ std::unique_ptr<type> result =
+ boost::make_unique<type>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 1);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ BOOST_TEST(type::instances == 0);
+ {
+ std::unique_ptr<const type> result =
+ boost::make_unique<const type>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(type::instances == 1);
+ result.reset();
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/make_unique_throws_test.cpp b/test/make_unique_throws_test.cpp
new file mode 100644
index 0000000..2032a2e
--- /dev/null
+++ b/test/make_unique_throws_test.cpp
@@ -0,0 +1,51 @@
+/*
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_SMART_PTR)
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr/make_unique.hpp>
+
+class type {
+public:
+ static unsigned instances;
+
+ type() {
+ if (instances == 0) {
+ throw true;
+ }
+ ++instances;
+ }
+
+ ~type() {
+ --instances;
+ }
+
+private:
+ type(const type&);
+ type& operator=(const type&);
+};
+
+unsigned type::instances = 0;
+
+int main()
+{
+ BOOST_TEST(type::instances == 0);
+ try {
+ boost::make_unique<type>();
+ BOOST_ERROR("make_unique did not throw");
+ } catch (...) {
+ BOOST_TEST(type::instances == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/make_unique_value_test.cpp b/test/make_unique_value_test.cpp
new file mode 100644
index 0000000..c7af67f
--- /dev/null
+++ b/test/make_unique_value_test.cpp
@@ -0,0 +1,56 @@
+/*
+Copyright 2014 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/config.hpp>
+#if !defined(BOOST_NO_CXX11_SMART_PTR)
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr/make_unique.hpp>
+
+struct type {
+ int x;
+ int y;
+};
+
+int main()
+{
+ {
+ std::unique_ptr<type> result = boost::make_unique<type>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result->x == 0);
+ BOOST_TEST(result->y == 0);
+ }
+ {
+ std::unique_ptr<const type> result =
+ boost::make_unique<const type>();
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result->x == 0);
+ BOOST_TEST(result->y == 0);
+ }
+#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
+ {
+ std::unique_ptr<type> result =
+ boost::make_unique<type>({ 1, 2 });
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result->x == 1);
+ BOOST_TEST(result->y == 2);
+ }
+ {
+ std::unique_ptr<const type> result =
+ boost::make_unique<const type>({ 1, 2 });
+ BOOST_TEST(result.get() != 0);
+ BOOST_TEST(result->x == 1);
+ BOOST_TEST(result->y == 2);
+ }
+#endif
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/owner_less_test.cpp b/test/owner_less_test.cpp
new file mode 100644
index 0000000..572b72b
--- /dev/null
+++ b/test/owner_less_test.cpp
@@ -0,0 +1,67 @@
+//
+// owner_less_test.cpp
+//
+// A regression test for owner_less
+//
+// Copyright (c) 2008 Frank Mori Hess
+//
+// 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)
+//
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr/owner_less.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+int main()
+{
+ boost::owner_less<boost::shared_ptr<int> > comp;
+ {
+ boost::shared_ptr<int> x;
+ boost::shared_ptr<int> y;
+ boost::weak_ptr<int> w;
+ BOOST_TEST(!(comp(x, w) || comp(w, x)));
+ }
+ {
+ boost::shared_ptr<int> z((int*)0);
+ boost::weak_ptr<int> w;
+ BOOST_TEST(comp(z, w) || comp(w, z));
+ {
+ boost::shared_ptr<int> zz(z);
+ w = boost::weak_ptr<int>(zz);
+ BOOST_TEST(!(comp(z, zz) || comp(z, zz)));
+ BOOST_TEST(!(comp(z, w) || comp(z, w)));
+ }
+ BOOST_TEST(!(comp(z, w) || comp(w, z)));
+ }
+ {
+ boost::shared_ptr<int> x;
+ boost::shared_ptr<int> z((int*)0);
+ BOOST_TEST(comp(x, z) || comp(z, x));
+ }
+ {
+ boost::shared_ptr<int> a((int*)0);
+ boost::shared_ptr<int> b((int*)0);
+ BOOST_TEST(comp(a, b) || comp(b, a));
+ boost::weak_ptr<int> w(a);
+ BOOST_TEST(!(comp(a, w) || comp(w, a)));
+ BOOST_TEST(comp(b, w) || comp(w, b));
+ }
+
+ boost::owner_less<boost::weak_ptr<int> > weak_comp;
+ {
+ boost::shared_ptr<int> a((int*)0);
+ boost::weak_ptr<int> wa(a);
+ boost::shared_ptr<int> b((int*)0);
+ boost::weak_ptr<int> wb(b);
+ BOOST_TEST(!(weak_comp(a, wa) || weak_comp(wa, a)));
+ BOOST_TEST(!(weak_comp(b, wb) || weak_comp(wb, b)));
+ BOOST_TEST(weak_comp(wa, wb) || weak_comp(wb, wa));
+ BOOST_TEST(weak_comp(wa, b) || weak_comp(b, wa));
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/pointer_cast_co_fail.cpp b/test/pointer_cast_co_fail.cpp
new file mode 100644
index 0000000..d8960b2
--- /dev/null
+++ b/test/pointer_cast_co_fail.cpp
@@ -0,0 +1,18 @@
+//
+// A negative test for unique_ptr const_cast
+//
+// Copyright 2016 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
+//
+
+#include <boost/pointer_cast.hpp>
+#include <memory>
+
+int main()
+{
+ std::unique_ptr<int> p1( new int );
+ std::unique_ptr<int[]> p2 = boost::const_pointer_cast<int[]>( std::move( p1 ) );
+}
diff --git a/test/pointer_cast_co_fail2.cpp b/test/pointer_cast_co_fail2.cpp
new file mode 100644
index 0000000..7fa8e18
--- /dev/null
+++ b/test/pointer_cast_co_fail2.cpp
@@ -0,0 +1,18 @@
+//
+// A negative test for unique_ptr const_cast
+//
+// Copyright 2016 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
+//
+
+#include <boost/pointer_cast.hpp>
+#include <memory>
+
+int main()
+{
+ std::unique_ptr<int[]> p1( new int[ 1 ] );
+ std::unique_ptr<int> p2 = boost::const_pointer_cast<int>( std::move( p1 ) );
+}
diff --git a/test/pointer_cast_co_fail3.cpp b/test/pointer_cast_co_fail3.cpp
new file mode 100644
index 0000000..d8872c8
--- /dev/null
+++ b/test/pointer_cast_co_fail3.cpp
@@ -0,0 +1,29 @@
+//
+// A negative test for unique_ptr const_cast
+//
+// Copyright 2016 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
+//
+
+#include <boost/pointer_cast.hpp>
+#include <memory>
+
+struct B
+{
+ virtual ~B()
+ {
+ }
+};
+
+struct D: B
+{
+};
+
+int main()
+{
+ std::unique_ptr<D[]> p1( new D[ 1 ] );
+ std::unique_ptr<B[]> p2 = boost::const_pointer_cast<B[]>( std::move( p1 ) );
+}
diff --git a/test/pointer_cast_dy_fail.cpp b/test/pointer_cast_dy_fail.cpp
new file mode 100644
index 0000000..c6df69d
--- /dev/null
+++ b/test/pointer_cast_dy_fail.cpp
@@ -0,0 +1,25 @@
+//
+// A negative test for unique_ptr dynamic_cast
+//
+// Copyright 2016 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
+//
+
+#include <boost/pointer_cast.hpp>
+#include <memory>
+
+struct B
+{
+ virtual ~B()
+ {
+ }
+};
+
+int main()
+{
+ std::unique_ptr<B> p1( new B );
+ std::unique_ptr<B[]> p2 = boost::dynamic_pointer_cast<B[]>( std::move( p1 ) );
+}
diff --git a/test/pointer_cast_dy_fail2.cpp b/test/pointer_cast_dy_fail2.cpp
new file mode 100644
index 0000000..223977a
--- /dev/null
+++ b/test/pointer_cast_dy_fail2.cpp
@@ -0,0 +1,25 @@
+//
+// A negative test for unique_ptr dynamic_cast
+//
+// Copyright 2016 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
+//
+
+#include <boost/pointer_cast.hpp>
+#include <memory>
+
+struct B
+{
+ virtual ~B()
+ {
+ }
+};
+
+int main()
+{
+ std::unique_ptr<B[]> p1( new B[ 1 ] );
+ std::unique_ptr<B> p2 = boost::dynamic_pointer_cast<B>( std::move( p1 ) );
+}
diff --git a/test/pointer_cast_dy_fail3.cpp b/test/pointer_cast_dy_fail3.cpp
new file mode 100644
index 0000000..1ac52e7
--- /dev/null
+++ b/test/pointer_cast_dy_fail3.cpp
@@ -0,0 +1,29 @@
+//
+// A negative test for unique_ptr dynamic_cast
+//
+// Copyright 2016 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
+//
+
+#include <boost/pointer_cast.hpp>
+#include <memory>
+
+struct B
+{
+ virtual ~B()
+ {
+ }
+};
+
+struct D: B
+{
+};
+
+int main()
+{
+ std::unique_ptr<D[]> p1( new D[ 1 ] );
+ std::unique_ptr<B[]> p2 = boost::dynamic_pointer_cast<B[]>( std::move( p1 ) );
+}
diff --git a/test/pointer_cast_st_fail.cpp b/test/pointer_cast_st_fail.cpp
new file mode 100644
index 0000000..0fcf8c1
--- /dev/null
+++ b/test/pointer_cast_st_fail.cpp
@@ -0,0 +1,18 @@
+//
+// A negative test for unique_ptr static_cast
+//
+// Copyright 2016 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
+//
+
+#include <boost/pointer_cast.hpp>
+#include <memory>
+
+int main()
+{
+ std::unique_ptr<int> p1( new int );
+ std::unique_ptr<int[]> p2 = boost::static_pointer_cast<int[]>( std::move( p1 ) );
+}
diff --git a/test/pointer_cast_st_fail2.cpp b/test/pointer_cast_st_fail2.cpp
new file mode 100644
index 0000000..3b227b9
--- /dev/null
+++ b/test/pointer_cast_st_fail2.cpp
@@ -0,0 +1,18 @@
+//
+// A negative test for unique_ptr static_cast
+//
+// Copyright 2016 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
+//
+
+#include <boost/pointer_cast.hpp>
+#include <memory>
+
+int main()
+{
+ std::unique_ptr<int[]> p1( new int[ 1 ] );
+ std::unique_ptr<int> p2 = boost::static_pointer_cast<int>( std::move( p1 ) );
+}
diff --git a/test/pointer_cast_st_fail3.cpp b/test/pointer_cast_st_fail3.cpp
new file mode 100644
index 0000000..4ca6a89
--- /dev/null
+++ b/test/pointer_cast_st_fail3.cpp
@@ -0,0 +1,29 @@
+//
+// A negative test for unique_ptr static_cast
+//
+// Copyright 2016 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
+//
+
+#include <boost/pointer_cast.hpp>
+#include <memory>
+
+struct B
+{
+ virtual ~B()
+ {
+ }
+};
+
+struct D: B
+{
+};
+
+int main()
+{
+ std::unique_ptr<D[]> p1( new D[ 1 ] );
+ std::unique_ptr<B[]> p2 = boost::static_pointer_cast<B[]>( std::move( p1 ) );
+}
diff --git a/test/pointer_cast_test.cpp b/test/pointer_cast_test.cpp
new file mode 100644
index 0000000..ae036fb
--- /dev/null
+++ b/test/pointer_cast_test.cpp
@@ -0,0 +1,128 @@
+//
+// pointer_cast_test.cpp - a test for boost/pointer_cast.hpp
+//
+// Copyright (c) 2005 Ion Gaztanaga
+// Copyright (c) 2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/config.hpp>
+
+#include <boost/pointer_cast.hpp>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/get_pointer.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+namespace
+{
+
+// Let's create these inheritance relationship:
+//
+// base base2
+// | |
+// derived
+// |
+// derived_derived
+//
+
+class base
+{
+ public:
+ virtual ~base(){}
+ int filler [5];
+};
+
+class base2
+{
+public:
+
+ virtual ~base2(){}
+ int filler [5];
+};
+
+class derived
+ : public base, public base2
+{
+ int filler [5];
+};
+
+class derived_derived
+ : public derived
+{
+ int filler [5];
+};
+
+// And now some simple check functions
+
+#if !defined( BOOST_NO_RTTI )
+
+template <class BasePtr>
+bool check_dynamic_pointer_cast(const BasePtr &ptr)
+{
+ //Check that dynamic_pointer_cast versus dynamic_cast
+ return
+ //Correct cast with dynamic_pointer_cast
+ boost::get_pointer(boost::dynamic_pointer_cast<derived>(ptr)) ==
+ //Correct cast with dynamic_cast
+ dynamic_cast<derived*>(boost::get_pointer(ptr))
+ &&
+ //Incorrect cast with dynamic_pointer_cast
+ boost::get_pointer(boost::dynamic_pointer_cast<derived_derived>(ptr)) ==
+ //Incorrect cast with dynamic_cast
+ dynamic_cast<derived_derived*>(boost::get_pointer(ptr));
+}
+
+#endif
+
+template <class BasePtr>
+bool check_static_pointer_cast(const BasePtr &ptr)
+{
+ return
+ //Cast base -> derived -> base2 using static_pointer_cast
+ boost::get_pointer(
+ boost::static_pointer_cast<base2>(
+ boost::static_pointer_cast<derived>(ptr))) ==
+ //Now the same with static_cast
+ static_cast<base2*>(static_cast<derived*>(boost::get_pointer(ptr)));
+}
+
+template <class BasePtr>
+bool check_const_pointer_cast(const BasePtr &ptr)
+{
+ return
+ //Unconst and const again using const_pointer_cast
+ boost::get_pointer(
+ boost::const_pointer_cast<const base>
+ (boost::const_pointer_cast<base>(ptr))) ==
+ //Now the same with const_cast
+ const_cast<const base*>(const_cast<base*>(boost::get_pointer(ptr)));
+}
+
+template <class BasePtr>
+void check_all_casts(const BasePtr &ptr)
+{
+#if !defined( BOOST_NO_RTTI )
+ BOOST_TEST( check_dynamic_pointer_cast( ptr ) );
+#endif
+ BOOST_TEST( check_static_pointer_cast( ptr ) );
+ BOOST_TEST( check_const_pointer_cast( ptr ) );
+}
+
+}
+
+int main()
+{
+ boost::shared_ptr<base> boost_shared(new derived);
+ base *plain = boost_shared.get();
+
+ check_all_casts(boost_shared);
+ check_all_casts(plain);
+
+ return boost::report_errors();
+}
diff --git a/test/pointer_cast_test2.cpp b/test/pointer_cast_test2.cpp
new file mode 100644
index 0000000..fd1d63e
--- /dev/null
+++ b/test/pointer_cast_test2.cpp
@@ -0,0 +1,247 @@
+//
+// pointer_cast_test2.cpp - a test for unique_ptr casts
+//
+// Copyright 2016 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
+//
+
+#include <boost/config.hpp>
+
+#if defined( BOOST_NO_CXX11_SMART_PTR )
+
+int main()
+{
+ return 0;
+}
+
+#else
+
+#include <boost/pointer_cast.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <memory>
+
+struct B1
+{
+};
+
+struct D1: B1
+{
+ ~D1()
+ {
+ }
+};
+
+static void test_static_cast()
+{
+ {
+ std::unique_ptr<int> p1( new int );
+ int * q1 = p1.get();
+
+ std::unique_ptr<int> p2 = boost::static_pointer_cast<int>( std::move( p1 ) );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST_EQ( p2.get(), q1 );
+ }
+
+ {
+ std::unique_ptr<int> p1( new int );
+ int * q1 = p1.get();
+
+ std::unique_ptr<int const> p2 = boost::static_pointer_cast<int const>( std::move( p1 ) );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST_EQ( p2.get(), q1 );
+ }
+
+ {
+ std::unique_ptr<int[]> p1( new int[ 1 ] );
+ int * q1 = p1.get();
+
+ std::unique_ptr<int[]> p2 = boost::static_pointer_cast<int[]>( std::move( p1 ) );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST_EQ( p2.get(), q1 );
+ }
+
+ {
+ std::unique_ptr<int[]> p1( new int[ 1 ] );
+ int * q1 = p1.get();
+
+ std::unique_ptr<int const[]> p2 = boost::static_pointer_cast<int const[]>( std::move( p1 ) );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST_EQ( p2.get(), q1 );
+ }
+
+ {
+ std::unique_ptr<D1> p1( new D1 );
+ D1 * q1 = p1.get();
+
+ std::unique_ptr<B1> p2 = boost::static_pointer_cast<B1>( std::move( p1 ) );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST_EQ( p2.get(), q1 );
+
+ std::unique_ptr<D1> p3 = boost::static_pointer_cast<D1>( std::move( p2 ) );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST_EQ( p3.get(), q1 );
+ }
+}
+
+static void test_const_cast()
+{
+ {
+ std::unique_ptr<int> p1( new int );
+ int * q1 = p1.get();
+
+ std::unique_ptr<int const> p2 = boost::const_pointer_cast<int const>( std::move( p1 ) );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST_EQ( p2.get(), q1 );
+
+ std::unique_ptr<int> p3 = boost::const_pointer_cast<int>( std::move( p2 ) );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST_EQ( p3.get(), q1 );
+ }
+
+ {
+ std::unique_ptr<int[]> p1( new int[ 1 ] );
+ int * q1 = p1.get();
+
+ std::unique_ptr<int const[]> p2 = boost::const_pointer_cast<int const[]>( std::move( p1 ) );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST_EQ( p2.get(), q1 );
+
+ std::unique_ptr<int[]> p3 = boost::const_pointer_cast<int[]>( std::move( p2 ) );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST_EQ( p3.get(), q1 );
+ }
+}
+
+struct B2
+{
+ virtual ~B2()
+ {
+ }
+};
+
+struct C2
+{
+ virtual ~C2()
+ {
+ }
+};
+
+struct D2: B2, C2
+{
+};
+
+static void test_dynamic_cast()
+{
+ {
+ std::unique_ptr<D2> p1( new D2 );
+ D2 * q1 = p1.get();
+
+ std::unique_ptr<B2> p2 = boost::dynamic_pointer_cast<B2>( std::move( p1 ) );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST_EQ( p2.get(), q1 );
+ }
+
+ {
+ std::unique_ptr<B2> p1( new D2 );
+ B2 * q1 = p1.get();
+
+ std::unique_ptr<D2> p2 = boost::dynamic_pointer_cast<D2>( std::move( p1 ) );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST_EQ( p2.get(), q1 );
+ }
+
+ {
+ std::unique_ptr<B2> p1( new B2 );
+ B2 * q1 = p1.get();
+
+ std::unique_ptr<D2> p2 = boost::dynamic_pointer_cast<D2>( std::move( p1 ) );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST_EQ( p1.get(), q1 );
+ }
+
+ {
+ D2 * q1 = new D2;
+ std::unique_ptr<B2> p1( q1 );
+
+ std::unique_ptr<C2> p2 = boost::dynamic_pointer_cast<C2>( std::move( p1 ) );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST_EQ( p2.get(), q1 );
+ }
+}
+
+static void test_reinterpret_cast()
+{
+ {
+ std::unique_ptr<int> p1( new int );
+ void * q1 = p1.get();
+
+ std::unique_ptr<char> p2 = boost::reinterpret_pointer_cast<char>( std::move( p1 ) );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST_EQ( p2.get(), q1 );
+
+ p1 = boost::reinterpret_pointer_cast<int>( std::move( p2 ) );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST_EQ( p1.get(), q1 );
+ }
+
+ {
+ std::unique_ptr<int> p1( new int );
+ void * q1 = p1.get();
+
+ std::unique_ptr<char[]> p2 = boost::reinterpret_pointer_cast<char[]>( std::move( p1 ) );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST_EQ( p2.get(), q1 );
+
+ p1 = boost::reinterpret_pointer_cast<int>( std::move( p2 ) );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST_EQ( p1.get(), q1 );
+ }
+
+ {
+ std::unique_ptr<int[]> p1( new int[ 1 ] );
+ void * q1 = p1.get();
+
+ std::unique_ptr<char[]> p2 = boost::reinterpret_pointer_cast<char[]>( std::move( p1 ) );
+
+ BOOST_TEST( p1.get() == 0 );
+ BOOST_TEST_EQ( p2.get(), q1 );
+
+ p1 = boost::reinterpret_pointer_cast<int[]>( std::move( p2 ) );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST_EQ( p1.get(), q1 );
+ }
+}
+
+int main()
+{
+ test_static_cast();
+ test_const_cast();
+ test_dynamic_cast();
+ test_reinterpret_cast();
+
+ return boost::report_errors();
+}
+
+#endif
diff --git a/test/pointer_to_other_test.cpp b/test/pointer_to_other_test.cpp
new file mode 100644
index 0000000..f1c6091
--- /dev/null
+++ b/test/pointer_to_other_test.cpp
@@ -0,0 +1,81 @@
+//
+// pointer_to_other_test.cpp - a test for boost/pointer_to_other.hpp
+//
+// Copyright (c) 2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/pointer_to_other.hpp>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/scoped_array.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+#include <boost/config.hpp>
+
+#include <memory>
+
+
+template<class T, class U> void assert_same_type( T** pt = 0, U** pu = 0 )
+{
+ pt = pu;
+}
+
+struct X;
+struct Y;
+
+int main()
+{
+ // shared_ptr
+
+ assert_same_type< boost::pointer_to_other< boost::shared_ptr<X>, Y >::type, boost::shared_ptr<Y> >();
+ assert_same_type< boost::pointer_to_other< boost::shared_ptr<X>, void >::type, boost::shared_ptr<void> >();
+ assert_same_type< boost::pointer_to_other< boost::shared_ptr<void>, Y >::type, boost::shared_ptr<Y> >();
+
+ // shared_array
+
+ assert_same_type< boost::pointer_to_other< boost::shared_array<X>, Y >::type, boost::shared_array<Y> >();
+ assert_same_type< boost::pointer_to_other< boost::shared_array<X>, void >::type, boost::shared_array<void> >();
+ assert_same_type< boost::pointer_to_other< boost::shared_array<void>, Y >::type, boost::shared_array<Y> >();
+
+ // scoped_ptr
+
+ assert_same_type< boost::pointer_to_other< boost::scoped_ptr<X>, Y >::type, boost::scoped_ptr<Y> >();
+ assert_same_type< boost::pointer_to_other< boost::scoped_ptr<X>, void >::type, boost::scoped_ptr<void> >();
+ assert_same_type< boost::pointer_to_other< boost::scoped_ptr<void>, Y >::type, boost::scoped_ptr<Y> >();
+
+ // scoped_array
+
+ assert_same_type< boost::pointer_to_other< boost::scoped_array<X>, Y >::type, boost::scoped_array<Y> >();
+ assert_same_type< boost::pointer_to_other< boost::scoped_array<X>, void >::type, boost::scoped_array<void> >();
+ assert_same_type< boost::pointer_to_other< boost::scoped_array<void>, Y >::type, boost::scoped_array<Y> >();
+
+ // intrusive_ptr
+
+ assert_same_type< boost::pointer_to_other< boost::intrusive_ptr<X>, Y >::type, boost::intrusive_ptr<Y> >();
+ assert_same_type< boost::pointer_to_other< boost::intrusive_ptr<X>, void >::type, boost::intrusive_ptr<void> >();
+ assert_same_type< boost::pointer_to_other< boost::intrusive_ptr<void>, Y >::type, boost::intrusive_ptr<Y> >();
+
+#if !defined( BOOST_NO_AUTO_PTR )
+
+ // auto_ptr
+
+ assert_same_type< boost::pointer_to_other< std::auto_ptr<X>, Y >::type, std::auto_ptr<Y> >();
+ assert_same_type< boost::pointer_to_other< std::auto_ptr<X>, void >::type, std::auto_ptr<void> >();
+ assert_same_type< boost::pointer_to_other< std::auto_ptr<void>, Y >::type, std::auto_ptr<Y> >();
+
+#endif
+
+ // raw pointer
+
+ assert_same_type< boost::pointer_to_other< X *, Y >::type, Y * >();
+ assert_same_type< boost::pointer_to_other< X *, void >::type, void * >();
+ assert_same_type< boost::pointer_to_other< void *, Y >::type, Y * >();
+
+ return 0;
+}
diff --git a/test/quick.cpp b/test/quick.cpp
new file mode 100644
index 0000000..0623094
--- /dev/null
+++ b/test/quick.cpp
@@ -0,0 +1,80 @@
+//
+// quick.cpp - a quick (CI) test for Boost.SmartPtr
+//
+// 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
+//
+
+#include <boost/smart_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+class X
+{
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+
+public:
+
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+};
+
+int X::instances = 0;
+
+int main()
+{
+ {
+ boost::shared_ptr<X> p1( new X );
+ BOOST_TEST_EQ( X::instances, 1 );
+ BOOST_TEST_EQ( p1.use_count(), 1 );
+
+ boost::shared_ptr<X> p2( p1 );
+ BOOST_TEST_EQ( p2.use_count(), 2 );
+
+ boost::weak_ptr<X> wp( p1 );
+ BOOST_TEST_EQ( wp.use_count(), 2 );
+
+ p1.reset();
+ BOOST_TEST_EQ( wp.use_count(), 1 );
+
+ p2.reset();
+ BOOST_TEST_EQ( wp.use_count(), 0 );
+ BOOST_TEST_EQ( X::instances, 0 );
+ }
+
+ {
+ boost::shared_ptr<X> p1 = boost::make_shared<X>();
+ BOOST_TEST_EQ( X::instances, 1 );
+ BOOST_TEST_EQ( p1.use_count(), 1 );
+
+ boost::shared_ptr<X> p2( p1 );
+ BOOST_TEST_EQ( p2.use_count(), 2 );
+
+ boost::weak_ptr<X> wp( p1 );
+ BOOST_TEST_EQ( wp.use_count(), 2 );
+
+ p1.reset();
+ BOOST_TEST_EQ( wp.use_count(), 1 );
+
+ p2.reset();
+ BOOST_TEST_EQ( wp.use_count(), 0 );
+ BOOST_TEST_EQ( X::instances, 0 );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/sa_nullptr_test.cpp b/test/sa_nullptr_test.cpp
new file mode 100644
index 0000000..a051d32
--- /dev/null
+++ b/test/sa_nullptr_test.cpp
@@ -0,0 +1,112 @@
+//
+// shared_array nullptr test
+//
+// Copyright 2012, 2013 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+
+#include <boost/shared_array.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <cstddef>
+#include <memory>
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+struct X
+{
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+};
+
+int X::instances = 0;
+
+int main()
+{
+ {
+ boost::shared_array<int> p( nullptr );
+
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.use_count() == 0 );
+
+ BOOST_TEST( p == nullptr );
+ BOOST_TEST( nullptr == p );
+ BOOST_TEST( !( p != nullptr ) );
+ BOOST_TEST( !( nullptr != p ) );
+ }
+
+ {
+ boost::shared_array<int> p( new int[ 1 ] );
+
+ BOOST_TEST( p.get() != 0 );
+ BOOST_TEST( p.use_count() == 1 );
+
+ BOOST_TEST( p != nullptr );
+ BOOST_TEST( nullptr != p );
+ BOOST_TEST( !( p == nullptr ) );
+ BOOST_TEST( !( nullptr == p ) );
+
+ p = nullptr;
+
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.use_count() == 0 );
+
+ BOOST_TEST( p == nullptr );
+ BOOST_TEST( nullptr == p );
+ BOOST_TEST( !( p != nullptr ) );
+ BOOST_TEST( !( nullptr != p ) );
+ }
+
+ {
+ BOOST_TEST( X::instances == 0 );
+
+ boost::shared_array<X> p( new X[ 2 ] );
+ BOOST_TEST( X::instances == 2 );
+
+ BOOST_TEST( p.get() != 0 );
+ BOOST_TEST( p.use_count() == 1 );
+
+ BOOST_TEST( p != nullptr );
+ BOOST_TEST( nullptr != p );
+ BOOST_TEST( !( p == nullptr ) );
+ BOOST_TEST( !( nullptr == p ) );
+
+ p = nullptr;
+ BOOST_TEST( X::instances == 0 );
+
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.use_count() == 0 );
+
+ BOOST_TEST( p == nullptr );
+ BOOST_TEST( nullptr == p );
+ BOOST_TEST( !( p != nullptr ) );
+ BOOST_TEST( !( nullptr != p ) );
+ }
+
+ return boost::report_errors();
+}
+
+#else
+
+int main()
+{
+ return 0;
+}
+
+#endif
diff --git a/test/scoped_array_eq_fail.cpp b/test/scoped_array_eq_fail.cpp
new file mode 100644
index 0000000..6c7f214
--- /dev/null
+++ b/test/scoped_array_eq_fail.cpp
@@ -0,0 +1,27 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#endif
+
+//
+// scoped_array_eq_fail.cpp - a negative test for "p == q"
+//
+// Copyright (c) 2008 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)
+//
+
+#include <boost/scoped_array.hpp>
+
+int main()
+{
+ boost::scoped_array<int> p, q;
+ p == q; // must fail
+ return 0;
+}
diff --git a/test/scoped_ptr_eq_fail.cpp b/test/scoped_ptr_eq_fail.cpp
new file mode 100644
index 0000000..0d6ade4
--- /dev/null
+++ b/test/scoped_ptr_eq_fail.cpp
@@ -0,0 +1,27 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#endif
+
+//
+// scoped_ptr_eq_fail.cpp - a negative test for "p == q"
+//
+// Copyright (c) 2008 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)
+//
+
+#include <boost/scoped_ptr.hpp>
+
+int main()
+{
+ boost::scoped_ptr<int> p, q;
+ p == q; // must fail
+ return 0;
+}
diff --git a/test/shared_from_raw_test.cpp b/test/shared_from_raw_test.cpp
new file mode 100644
index 0000000..cf5500f
--- /dev/null
+++ b/test/shared_from_raw_test.cpp
@@ -0,0 +1,170 @@
+//
+// shared_from_raw_test - based on shared_from_this_test
+//
+// Copyright (c) 2002, 2003, 2014 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
+//
+
+#include <boost/smart_ptr/enable_shared_from_raw.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X
+{
+public:
+
+ virtual void f() = 0;
+
+protected:
+
+ ~X() {}
+};
+
+class Y
+{
+public:
+
+ virtual boost::shared_ptr<X> getX() = 0;
+
+protected:
+
+ ~Y() {}
+};
+
+boost::shared_ptr<Y> createY();
+
+void test()
+{
+ boost::shared_ptr<Y> py = createY();
+ BOOST_TEST(py.get() != 0);
+ BOOST_TEST(py.use_count() == 1);
+
+ try
+ {
+ boost::shared_ptr<X> px = py->getX();
+ BOOST_TEST(px.get() != 0);
+ BOOST_TEST(py.use_count() == 2);
+
+ px->f();
+
+#if !defined( BOOST_NO_RTTI )
+ boost::shared_ptr<Y> py2 = boost::dynamic_pointer_cast<Y>(px);
+ BOOST_TEST(py.get() == py2.get());
+ BOOST_TEST(!(py < py2 || py2 < py));
+ BOOST_TEST(py.use_count() == 3);
+#endif
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "py->getX() failed" );
+ }
+}
+
+void test2();
+void test3();
+
+int main()
+{
+ test();
+ test2();
+ test3();
+ return boost::report_errors();
+}
+
+// virtual inheritance to stress the implementation
+// (prevents Y* -> impl*, enable_shared_from_raw* -> impl* casts)
+
+class impl: public X, public virtual Y, public virtual boost::enable_shared_from_raw
+{
+public:
+
+ virtual void f()
+ {
+ }
+
+ virtual boost::shared_ptr<X> getX()
+ {
+ boost::shared_ptr<impl> pi = boost::shared_from_raw( this );
+ BOOST_TEST( pi.get() == this );
+ return pi;
+ }
+};
+
+// intermediate impl2 to stress the implementation
+
+class impl2: public impl
+{
+};
+
+boost::shared_ptr<Y> createY()
+{
+ boost::shared_ptr<Y> pi(new impl2);
+ return pi;
+}
+
+void test2()
+{
+ boost::shared_ptr<Y> pi(static_cast<impl2*>(0));
+}
+
+//
+
+struct V: public boost::enable_shared_from_raw
+{
+};
+
+void test3()
+{
+ boost::shared_ptr<V> p( new V );
+
+ try
+ {
+ boost::shared_ptr<V> q = boost::shared_from_raw( p.get() );
+ BOOST_TEST( p == q );
+ BOOST_TEST( !(p < q) && !(q < p) );
+ }
+ catch( boost::bad_weak_ptr const & )
+ {
+ BOOST_ERROR( "shared_from_this( p.get() ) failed" );
+ }
+
+ V v2( *p );
+
+ try
+ {
+ // shared_from_raw differs from shared_from_this;
+ // it will not throw here and will create a shared_ptr
+
+ boost::shared_ptr<V> r = boost::shared_from_raw( &v2 );
+
+ // check if the shared_ptr is correct and that it does
+ // not share ownership with p
+
+ BOOST_TEST( r.get() == &v2 );
+ BOOST_TEST( p != r );
+ BOOST_TEST( (p < r) || (r < p) );
+ }
+ catch( boost::bad_weak_ptr const & )
+ {
+ BOOST_ERROR("shared_from_raw( &v2 ) failed");
+ }
+
+ try
+ {
+ *p = V();
+ boost::shared_ptr<V> r = boost::shared_from_raw( p.get() );
+ BOOST_TEST( p == r );
+ BOOST_TEST( !(p < r) && !(r < p) );
+ }
+ catch( boost::bad_weak_ptr const & )
+ {
+ BOOST_ERROR("shared_from_raw( p.get() ) threw bad_weak_ptr after *p = V()");
+ }
+}
diff --git a/test/shared_from_raw_test2.cpp b/test/shared_from_raw_test2.cpp
new file mode 100644
index 0000000..2a33637
--- /dev/null
+++ b/test/shared_from_raw_test2.cpp
@@ -0,0 +1,224 @@
+//
+// shared_from_raw_test2.cpp - based on esft_regtest.cpp
+//
+// Copyright (c) 2008, 2014 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
+//
+
+#include <boost/smart_ptr/enable_shared_from_raw.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/config.hpp>
+#include <memory>
+#include <string>
+
+class X: public boost::enable_shared_from_raw
+{
+private:
+
+ int destroyed_;
+ int deleted_;
+ int expected_;
+
+private:
+
+ X( X const& );
+ X& operator=( X const& );
+
+public:
+
+ static int instances;
+
+public:
+
+ explicit X( int expected ): destroyed_( 0 ), deleted_( 0 ), expected_( expected )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ BOOST_TEST( deleted_ == expected_ );
+ BOOST_TEST( destroyed_ == 0 );
+ ++destroyed_;
+ --instances;
+ }
+
+ typedef void (*deleter_type)( X* );
+
+ static void deleter( X * px )
+ {
+ ++px->deleted_;
+ }
+
+ static void deleter2( X * px )
+ {
+ ++px->deleted_;
+ delete px;
+ }
+};
+
+int X::instances = 0;
+
+void test()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ X x( 0 );
+ BOOST_TEST( X::instances == 1 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+#if !defined( BOOST_NO_AUTO_PTR )
+
+ {
+ std::auto_ptr<X> px( new X( 0 ) );
+ BOOST_TEST( X::instances == 1 );
+ }
+
+#endif
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X> px( new X( 0 ) );
+ BOOST_TEST( X::instances == 1 );
+
+ boost::weak_ptr<X> wp( px );
+ BOOST_TEST( !wp.expired() );
+
+ px.reset();
+
+ BOOST_TEST( wp.expired() );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ X x( 1 );
+ boost::shared_ptr<X> px( &x, X::deleter );
+ BOOST_TEST( X::instances == 1 );
+
+ X::deleter_type * pd = boost::get_deleter<X::deleter_type>( px );
+ BOOST_TEST( pd != 0 && *pd == X::deleter );
+
+ boost::weak_ptr<X> wp( px );
+ BOOST_TEST( !wp.expired() );
+
+ px.reset();
+
+ BOOST_TEST( wp.expired() );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X> px( new X( 1 ), X::deleter2 );
+ BOOST_TEST( X::instances == 1 );
+
+ X::deleter_type * pd = boost::get_deleter<X::deleter_type>( px );
+ BOOST_TEST( pd != 0 && *pd == X::deleter2 );
+
+ boost::weak_ptr<X> wp( px );
+ BOOST_TEST( !wp.expired() );
+
+ px.reset();
+
+ BOOST_TEST( wp.expired() );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+}
+
+struct V: public boost::enable_shared_from_raw
+{
+ virtual ~V() {}
+ std::string m_;
+};
+
+struct V2
+{
+ virtual ~V2() {}
+ std::string m2_;
+};
+
+struct W: V2, V
+{
+};
+
+void test2()
+{
+ boost::shared_ptr<W> p( new W );
+}
+
+void test3()
+{
+ V * p = new W;
+ boost::shared_ptr<void> pv( p );
+ BOOST_TEST( pv.get() == p );
+ BOOST_TEST( pv.use_count() == 1 );
+}
+
+struct null_deleter
+{
+ void operator()( void const* ) const {}
+};
+
+void test4()
+{
+ boost::shared_ptr<V> pv( new V );
+ boost::shared_ptr<V> pv2( pv.get(), null_deleter() );
+ BOOST_TEST( pv2.get() == pv.get() );
+ BOOST_TEST( pv2.use_count() == 1 );
+}
+
+void test5()
+{
+ V v;
+
+ boost::shared_ptr<V> p1( &v, null_deleter() );
+ BOOST_TEST( p1.get() == &v );
+ BOOST_TEST( p1.use_count() == 1 );
+
+ try
+ {
+ boost::shared_from_raw( p1.get() );
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "shared_from_raw( p1.get() ) failed" );
+ }
+
+ p1.reset();
+
+ boost::shared_ptr<V> p2( &v, null_deleter() );
+ BOOST_TEST( p2.get() == &v );
+ BOOST_TEST( p2.use_count() == 1 );
+
+ try
+ {
+ boost::shared_from_raw( p2.get() );
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "shared_from_raw( p2.get() ) failed" );
+ }
+}
+
+int main()
+{
+ test();
+ test2();
+ test3();
+ test4();
+ test5();
+
+ return boost::report_errors();
+}
diff --git a/test/shared_from_raw_test3.cpp b/test/shared_from_raw_test3.cpp
new file mode 100644
index 0000000..8c3adaf
--- /dev/null
+++ b/test/shared_from_raw_test3.cpp
@@ -0,0 +1,52 @@
+//
+// shared_from_raw_test3 - based on esft_second_ptr_test.cpp
+//
+// This test has been extracted from a real
+// scenario that occurs in Boost.Python
+//
+// Copyright 2009, 2014 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
+//
+
+
+#include <boost/smart_ptr/enable_shared_from_raw.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X: public boost::enable_shared_from_raw
+{
+};
+
+void null_deleter( void const* )
+{
+}
+
+int main()
+{
+ boost::shared_ptr<X> px( new X );
+
+ {
+ boost::shared_ptr<X> px2( px.get(), null_deleter );
+ BOOST_TEST( px == px2 );
+ }
+
+ try
+ {
+ boost::shared_ptr< X > qx = boost::shared_from_raw( px.get() );
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "shared_from_raw( px.get() ) failed" );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/shared_from_raw_test4.cpp b/test/shared_from_raw_test4.cpp
new file mode 100644
index 0000000..ab0658e
--- /dev/null
+++ b/test/shared_from_raw_test4.cpp
@@ -0,0 +1,56 @@
+//
+// shared_from_raw_test4 - based on esft_void_test.cpp
+//
+// Copyright 2009, 2014 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
+//
+
+
+#include <boost/smart_ptr/enable_shared_from_raw.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X: public boost::enable_shared_from_raw
+{
+};
+
+int main()
+{
+ boost::shared_ptr< void const volatile > pv( new X );
+ boost::shared_ptr< void > pv2 = boost::const_pointer_cast< void >( pv );
+ boost::shared_ptr< X > px = boost::static_pointer_cast< X >( pv2 );
+
+ try
+ {
+ boost::shared_ptr< X > qx = boost::shared_from_raw( px.get() );
+
+ BOOST_TEST( px == qx );
+ BOOST_TEST( !( px < qx ) && !( qx < px ) );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "shared_from_this( px.get() ) failed" );
+ }
+
+ boost::shared_ptr< X const volatile > px2( px );
+
+ try
+ {
+ boost::shared_ptr< X const volatile > qx2 = boost::shared_from_raw( px2.get() );
+
+ BOOST_TEST( px2 == qx2 );
+ BOOST_TEST( !( px2 < qx2 ) && !( qx2 < px2 ) );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "shared_from_this( px2.get() ) failed" );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/shared_from_raw_test5.cpp b/test/shared_from_raw_test5.cpp
new file mode 100644
index 0000000..fcf4e81
--- /dev/null
+++ b/test/shared_from_raw_test5.cpp
@@ -0,0 +1,168 @@
+//
+// shared_from_raw_test5.cpp - was esft_constructor_test.cpp
+//
+// A test for calling shared_from_raw from constructors
+// (that is, prior to the object's ownership being passed to
+// an external shared_ptr).
+//
+// Copyright (c) 2008 Frank Mori Hess
+// Copyright (c) 2008 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)
+//
+
+#include <boost/smart_ptr/enable_shared_from_raw.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <memory>
+
+class X: public boost::enable_shared_from_raw
+{
+private:
+
+ int destroyed_;
+ int deleted_;
+ int expected_;
+
+private:
+
+ X( X const& );
+ X& operator=( X const& );
+
+public:
+
+ static int instances;
+
+public:
+
+ explicit X( int expected, boost::shared_ptr<X> *early_px = 0 ): destroyed_( 0 ), deleted_( 0 ), expected_( expected )
+ {
+ ++instances;
+ if( early_px ) *early_px = shared_from_raw(this);
+ }
+
+ ~X()
+ {
+ BOOST_TEST( deleted_ == expected_ );
+ BOOST_TEST( destroyed_ == 0 );
+ ++destroyed_;
+ --instances;
+ }
+
+ typedef void (*deleter_type)( X* );
+
+ static void deleter( X * px )
+ {
+ ++px->deleted_;
+ }
+
+ static void deleter2( X * px )
+ {
+ ++px->deleted_;
+ delete px;
+ }
+};
+
+int X::instances = 0;
+
+template<typename T, typename U>
+bool are_shared_owners(const boost::shared_ptr<T> &a, const boost::shared_ptr<U> &b)
+{
+ return !(a < b) && !(b < a);
+}
+
+struct Y: public boost::enable_shared_from_raw
+{};
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X> early_px;
+ X* x = new X( 1, &early_px );
+ BOOST_TEST( early_px.use_count() > 0 );
+ BOOST_TEST( boost::get_deleter<X::deleter_type>(early_px) == 0 );
+ BOOST_TEST( early_px.get() == x );
+ boost::shared_ptr<X> px( x, &X::deleter2 );
+ BOOST_TEST( early_px.use_count() == 2 && px.use_count() == 2 );
+ BOOST_TEST(are_shared_owners(early_px, px));
+ px.reset();
+ BOOST_TEST( early_px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+ X::deleter_type *pd = boost::get_deleter<X::deleter_type>(early_px);
+ BOOST_TEST(pd && *pd == &X::deleter2 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X> early_px;
+ X* x = new X( 1, &early_px );
+ boost::weak_ptr<X> early_weak_px = early_px;
+ early_px.reset();
+ BOOST_TEST( !early_weak_px.expired() );
+ boost::shared_ptr<X> px( x, &X::deleter2 );
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST(are_shared_owners(early_weak_px.lock(), px));
+ px.reset();
+ BOOST_TEST( early_weak_px.expired() );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X> early_px;
+ X x( 2, &early_px );
+ BOOST_TEST( early_px.use_count() > 0 );
+ boost::shared_ptr<X> px( &x, &X::deleter );
+ BOOST_TEST( early_px.use_count() == 2 && px.use_count() == 2 );
+ early_px.reset();
+ BOOST_TEST( px.use_count() == 1 );
+ BOOST_TEST( X::instances == 1 );
+ px.reset();
+ // test reinitialization after all shared_ptr have expired
+ early_px = shared_from_raw(&x);
+ px.reset( &x, &X::deleter );
+ BOOST_TEST(are_shared_owners(early_px, px));
+ early_px.reset();
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::weak_ptr<X> early_weak_px;
+ {
+ boost::shared_ptr<X> early_px;
+ X x( 0, &early_px );
+ early_weak_px = early_px;
+ early_px.reset();
+ BOOST_TEST( !early_weak_px.expired() );
+ BOOST_TEST( X::instances == 1 );
+ }
+ BOOST_TEST( early_weak_px.expired() );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<Y> px(new Y());
+ Y y(*px);
+ px.reset();
+ try
+ {
+ shared_from_raw(&y);
+ }
+ catch( const boost::bad_weak_ptr & )
+ {
+ BOOST_ERROR("y threw bad_weak_ptr");
+ }
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/shared_from_raw_test6.cpp b/test/shared_from_raw_test6.cpp
new file mode 100644
index 0000000..d1941c6
--- /dev/null
+++ b/test/shared_from_raw_test6.cpp
@@ -0,0 +1,52 @@
+//
+// shared_from_raw_test6
+//
+// Tests that dangling shared_ptr instances are caught by
+// the BOOST_ASSERT in ~enable_shared_from_raw
+//
+// Copyright 2014 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
+//
+
+#define BOOST_ENABLE_ASSERT_HANDLER
+#include <boost/smart_ptr/enable_shared_from_raw.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <stdio.h>
+
+static int assertion_failed_ = 0;
+
+namespace boost
+{
+
+void assertion_failed( char const * expr, char const * function, char const * file, long line )
+{
+ printf( "Assertion '%s' failed in function '%s', file '%s', line %ld\n", expr, function, file, line );
+ ++assertion_failed_;
+}
+
+} // namespace boost
+
+class X: public boost::enable_shared_from_raw
+{
+};
+
+int main()
+{
+ boost::shared_ptr<X> px;
+
+ {
+ X x;
+ px = boost::shared_from_raw( &x );
+ }
+
+ BOOST_TEST_EQ( assertion_failed_, 1 );
+
+ // px is a dangling pointer here
+
+ return boost::report_errors();
+}
diff --git a/test/shared_from_this_test.cpp b/test/shared_from_this_test.cpp
new file mode 100644
index 0000000..b3d7838
--- /dev/null
+++ b/test/shared_from_this_test.cpp
@@ -0,0 +1,169 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#endif
+
+//
+// shared_from_this_test.cpp
+//
+// Copyright (c) 2002, 2003 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X
+{
+public:
+
+ virtual void f() = 0;
+
+protected:
+
+ ~X() {}
+};
+
+class Y
+{
+public:
+
+ virtual boost::shared_ptr<X> getX() = 0;
+
+protected:
+
+ ~Y() {}
+};
+
+boost::shared_ptr<Y> createY();
+
+void test()
+{
+ boost::shared_ptr<Y> py = createY();
+ BOOST_TEST(py.get() != 0);
+ BOOST_TEST(py.use_count() == 1);
+
+ try
+ {
+ boost::shared_ptr<X> px = py->getX();
+ BOOST_TEST(px.get() != 0);
+ BOOST_TEST(py.use_count() == 2);
+
+ px->f();
+
+#if !defined( BOOST_NO_RTTI )
+ boost::shared_ptr<Y> py2 = boost::dynamic_pointer_cast<Y>(px);
+ BOOST_TEST(py.get() == py2.get());
+ BOOST_TEST(!(py < py2 || py2 < py));
+ BOOST_TEST(py.use_count() == 3);
+#endif
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ BOOST_ERROR( "py->getX() failed" );
+ }
+}
+
+void test2();
+void test3();
+
+int main()
+{
+ test();
+ test2();
+ test3();
+ return boost::report_errors();
+}
+
+// virtual inheritance to stress the implementation
+// (prevents Y* -> impl*, enable_shared_from_this<impl>* -> impl* casts)
+
+class impl: public X, public virtual Y, public virtual boost::enable_shared_from_this<impl>
+{
+public:
+
+ virtual void f()
+ {
+ }
+
+ virtual boost::shared_ptr<X> getX()
+ {
+ boost::shared_ptr<impl> pi = shared_from_this();
+ BOOST_TEST(pi.get() == this);
+ return pi;
+ }
+};
+
+// intermediate impl2 to stress the implementation
+
+class impl2: public impl
+{
+};
+
+boost::shared_ptr<Y> createY()
+{
+ boost::shared_ptr<Y> pi(new impl2);
+ return pi;
+}
+
+void test2()
+{
+ boost::shared_ptr<Y> pi(static_cast<impl2*>(0));
+}
+
+//
+
+struct V: public boost::enable_shared_from_this<V>
+{
+};
+
+void test3()
+{
+ boost::shared_ptr<V> p(new V);
+
+ try
+ {
+ boost::shared_ptr<V> q = p->shared_from_this();
+ BOOST_TEST(p == q);
+ BOOST_TEST(!(p < q) && !(q < p));
+ }
+ catch( boost::bad_weak_ptr const & )
+ {
+ BOOST_ERROR( "p->shared_from_this() failed" );
+ }
+
+ V v2(*p);
+
+ try
+ {
+ boost::shared_ptr<V> r = v2.shared_from_this();
+ BOOST_ERROR("v2.shared_from_this() failed to throw");
+ }
+ catch( boost::bad_weak_ptr const & )
+ {
+ }
+
+ try
+ {
+ *p = V();
+ boost::shared_ptr<V> r = p->shared_from_this();
+ BOOST_TEST(p == r);
+ BOOST_TEST(!(p < r) && !(r < p));
+ }
+ catch( boost::bad_weak_ptr const & )
+ {
+ BOOST_ERROR("p->shared_from_this() threw bad_weak_ptr after *p = V()");
+ }
+}
diff --git a/test/shared_ptr_alias_move_test.cpp b/test/shared_ptr_alias_move_test.cpp
new file mode 100644
index 0000000..972f24b
--- /dev/null
+++ b/test/shared_ptr_alias_move_test.cpp
@@ -0,0 +1,255 @@
+#include <boost/config.hpp>
+
+// shared_ptr_alias_move_test.cpp
+//
+// Copyright (c) 2007 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)
+
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/shared_ptr.hpp>
+#include <utility>
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+class incomplete;
+
+struct X
+{
+ static long instances;
+
+ int v_;
+
+ explicit X( int v ): v_( v )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ v_ = 0;
+ --instances;
+ }
+
+private:
+ X( X const & );
+ X & operator=( X const & );
+};
+
+long X::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ int m = 0;
+ boost::shared_ptr< int > p;
+ boost::shared_ptr< int > p2( std::move( p ), &m );
+
+ BOOST_TEST( p2.get() == &m );
+ BOOST_TEST( p2? true: false );
+ BOOST_TEST( !!p2 );
+ BOOST_TEST( p2.use_count() == 0 );
+
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.use_count() == 0 );
+
+ p2.reset( std::move( p ), 0 );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST( p2? false: true );
+ BOOST_TEST( !p2 );
+ BOOST_TEST( p2.use_count() == 0 );
+
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.use_count() == 0 );
+ }
+
+ {
+ int m = 0;
+ boost::shared_ptr< int > p( new int );
+ boost::shared_ptr< int const > p2( std::move( p ), &m );
+
+ BOOST_TEST( p2.get() == &m );
+ BOOST_TEST( p2? true: false );
+ BOOST_TEST( !!p2 );
+ BOOST_TEST( p2.use_count() == 1 );
+
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.use_count() == 0 );
+
+ boost::shared_ptr< int volatile > p3;
+ p2.reset( std::move( p3 ), 0 );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST( p2? false: true );
+ BOOST_TEST( !p2 );
+ BOOST_TEST( p2.use_count() == 0 );
+
+ BOOST_TEST( p3.get() == 0 );
+ BOOST_TEST( p3.use_count() == 0 );
+
+ boost::shared_ptr< int const volatile > p4( new int );
+ p2.reset( std::move( p4 ), &m );
+
+ BOOST_TEST( p2.get() == &m );
+ BOOST_TEST( p2.use_count() == 1 );
+
+ BOOST_TEST( p4.get() == 0 );
+ BOOST_TEST( p4.use_count() == 0 );
+ }
+
+ {
+ boost::shared_ptr< int > p( new int );
+ boost::shared_ptr< void const > p2( std::move( p ), 0 );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST( p2? false: true );
+ BOOST_TEST( !p2 );
+ BOOST_TEST( p2.use_count() == 1 );
+
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.use_count() == 0 );
+
+ int m = 0;
+ boost::shared_ptr< void volatile > p3;
+
+ p2.reset( std::move( p3 ), &m );
+
+ BOOST_TEST( p2.get() == &m );
+ BOOST_TEST( p2? true: false );
+ BOOST_TEST( !!p2 );
+ BOOST_TEST( p2.use_count() == 0 );
+
+ BOOST_TEST( p3.get() == 0 );
+ BOOST_TEST( p3.use_count() == 0 );
+
+ boost::shared_ptr< void const volatile > p4( new int );
+ p2.reset( std::move( p4 ), 0 );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST( p2.use_count() == 1 );
+
+ BOOST_TEST( p4.get() == 0 );
+ BOOST_TEST( p4.use_count() == 0 );
+ }
+
+ {
+ boost::shared_ptr< incomplete > p;
+ boost::shared_ptr< incomplete > p2( std::move( p ), 0 );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST( p2? false: true );
+ BOOST_TEST( !p2 );
+ BOOST_TEST( p2.use_count() == 0 );
+
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.use_count() == 0 );
+
+ p2.reset( std::move( p ), 0 );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST( p2? false: true );
+ BOOST_TEST( !p2 );
+ BOOST_TEST( p2.use_count() == 0 );
+
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.use_count() == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > p( new X( 5 ) ), q( p );
+ boost::shared_ptr< int const > p2( std::move( q ), &q->v_ );
+
+ BOOST_TEST( p2.get() == &p->v_ );
+ BOOST_TEST( p2? true: false );
+ BOOST_TEST( !!p2 );
+ BOOST_TEST( p2.use_count() == p.use_count() );
+ BOOST_TEST( !( p < p2 ) && !( p2 < p ) );
+
+ BOOST_TEST( q.get() == 0 );
+ BOOST_TEST( q.use_count() == 0 );
+
+ p.reset();
+ BOOST_TEST( *p2 == 5 );
+
+ boost::shared_ptr< X const > p3( new X( 8 ) ), q3( p3 );
+ p2.reset( std::move( q3 ), &q3->v_ );
+
+ BOOST_TEST( p2.get() == &p3->v_ );
+ BOOST_TEST( p2? true: false );
+ BOOST_TEST( !!p2 );
+ BOOST_TEST( p2.use_count() == p3.use_count() );
+ BOOST_TEST( !( p3 < p2 ) && !( p2 < p3 ) );
+
+ BOOST_TEST( q3.get() == 0 );
+ BOOST_TEST( q3.use_count() == 0 );
+
+ p3.reset();
+ BOOST_TEST( *p2 == 8 );
+ }
+
+ {
+ boost::shared_ptr< X > p( new X( 5 ) );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.unique() );
+ BOOST_TEST( p->v_ == 5 );
+
+ boost::shared_ptr< X > p2( std::move( p ), p.get() );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p2.unique() );
+ BOOST_TEST( p2->v_ == 5 );
+
+ boost::shared_ptr< int const > p3( std::move( p2 ), &p2->v_ );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST( p3.unique() );
+ BOOST_TEST( *p3 == 5 );
+
+ p3.reset();
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr< X > p( new X( 5 ) );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.unique() );
+ BOOST_TEST( p->v_ == 5 );
+
+ {
+ boost::shared_ptr< X > p2(p);
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.get() == p2.get() );
+ BOOST_TEST( p.use_count() == 2 );
+ BOOST_TEST( p2.use_count() == 2 );
+
+ boost::shared_ptr< int const > p3( std::move( p2 ), &p2->v_ );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.use_count() == 2 );
+ BOOST_TEST( p2.use_count() == 0 );
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST( p3.use_count() == 2 );
+ BOOST_TEST( p3.get() == &p->v_ );
+ }
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.unique() );
+ BOOST_TEST( p->v_ == 5 );
+ }
+
+ return boost::report_errors();
+}
+
+#else // defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+int main()
+{
+ return 0;
+}
+
+#endif
diff --git a/test/shared_ptr_alias_test.cpp b/test/shared_ptr_alias_test.cpp
new file mode 100644
index 0000000..83d866f
--- /dev/null
+++ b/test/shared_ptr_alias_test.cpp
@@ -0,0 +1,146 @@
+#include <boost/config.hpp>
+
+// shared_ptr_alias_test.cpp
+//
+// Copyright (c) 2007 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)
+
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/shared_ptr.hpp>
+#include <memory>
+#include <cstddef>
+
+//
+
+class incomplete;
+
+struct X
+{
+ int v_;
+
+ explicit X( int v ): v_( v )
+ {
+ }
+
+ ~X()
+ {
+ v_ = 0;
+ }
+};
+
+int main()
+{
+ {
+ int m = 0;
+ boost::shared_ptr< int > p;
+ boost::shared_ptr< int > p2( p, &m );
+
+ BOOST_TEST( p2.get() == &m );
+ BOOST_TEST( p2? true: false );
+ BOOST_TEST( !!p2 );
+ BOOST_TEST( p2.use_count() == p.use_count() );
+ BOOST_TEST( !( p < p2 ) && !( p2 < p ) );
+
+ p2.reset( p, 0 );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST( p2? false: true );
+ BOOST_TEST( !p2 );
+ BOOST_TEST( p2.use_count() == p.use_count() );
+ BOOST_TEST( !( p < p2 ) && !( p2 < p ) );
+ }
+
+ {
+ int m = 0;
+ boost::shared_ptr< int > p( new int );
+ boost::shared_ptr< int const > p2( p, &m );
+
+ BOOST_TEST( p2.get() == &m );
+ BOOST_TEST( p2? true: false );
+ BOOST_TEST( !!p2 );
+ BOOST_TEST( p2.use_count() == p.use_count() );
+ BOOST_TEST( !( p < p2 ) && !( p2 < p ) );
+
+ boost::shared_ptr< int volatile > p3;
+ p2.reset( p3, 0 );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST( p2? false: true );
+ BOOST_TEST( !p2 );
+ BOOST_TEST( p2.use_count() == p3.use_count() );
+ BOOST_TEST( !( p3 < p2 ) && !( p2 < p3 ) );
+ }
+
+ {
+ boost::shared_ptr< int > p( new int );
+ boost::shared_ptr< void const > p2( p, 0 );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST( p2? false: true );
+ BOOST_TEST( !p2 );
+ BOOST_TEST( p2.use_count() == p.use_count() );
+ BOOST_TEST( !( p < p2 ) && !( p2 < p ) );
+
+ int m = 0;
+ boost::shared_ptr< void volatile > p3;
+
+ p2.reset( p3, &m );
+
+ BOOST_TEST( p2.get() == &m );
+ BOOST_TEST( p2? true: false );
+ BOOST_TEST( !!p2 );
+ BOOST_TEST( p2.use_count() == p3.use_count() );
+ BOOST_TEST( !( p3 < p2 ) && !( p2 < p3 ) );
+ }
+
+ {
+ boost::shared_ptr< incomplete > p;
+ boost::shared_ptr< incomplete > p2( p, 0 );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST( p2? false: true );
+ BOOST_TEST( !p2 );
+ BOOST_TEST( p2.use_count() == p.use_count() );
+ BOOST_TEST( !( p < p2 ) && !( p2 < p ) );
+
+ p2.reset( p, 0 );
+
+ BOOST_TEST( p2.get() == 0 );
+ BOOST_TEST( p2? false: true );
+ BOOST_TEST( !p2 );
+ BOOST_TEST( p2.use_count() == p.use_count() );
+ BOOST_TEST( !( p < p2 ) && !( p2 < p ) );
+ }
+
+ {
+ boost::shared_ptr< X > p( new X( 5 ) );
+ boost::shared_ptr< int const > p2( p, &p->v_ );
+
+ BOOST_TEST( p2.get() == &p->v_ );
+ BOOST_TEST( p2? true: false );
+ BOOST_TEST( !!p2 );
+ BOOST_TEST( p2.use_count() == p.use_count() );
+ BOOST_TEST( !( p < p2 ) && !( p2 < p ) );
+
+ p.reset();
+ BOOST_TEST( *p2 == 5 );
+
+ boost::shared_ptr< X const > p3( new X( 8 ) );
+ p2.reset( p3, &p3->v_ );
+
+ BOOST_TEST( p2.get() == &p3->v_ );
+ BOOST_TEST( p2? true: false );
+ BOOST_TEST( !!p2 );
+ BOOST_TEST( p2.use_count() == p3.use_count() );
+ BOOST_TEST( !( p3 < p2 ) && !( p2 < p3 ) );
+
+ p3.reset();
+ BOOST_TEST( *p2 == 8 );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/shared_ptr_alloc11_test.cpp b/test/shared_ptr_alloc11_test.cpp
new file mode 100644
index 0000000..c2b7d6a
--- /dev/null
+++ b/test/shared_ptr_alloc11_test.cpp
@@ -0,0 +1,116 @@
+#include <boost/config.hpp>
+
+// shared_ptr_alloc11_test.cpp
+//
+// Test the allocator constructor with a C++11 minimal allocator
+//
+// Copyright (c) 2005, 2014 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
+
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/shared_ptr.hpp>
+#include <memory>
+#include <cstddef>
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+template< class T > class cxx11_allocator
+{
+public:
+
+ typedef T value_type;
+
+ cxx11_allocator()
+ {
+ }
+
+ template< class Y > cxx11_allocator( cxx11_allocator<Y> const & )
+ {
+ }
+
+ T * allocate( std::size_t n )
+ {
+ return static_cast< T* >( ::operator new( n * sizeof( T ) ) );
+ }
+
+ void deallocate( T * p, std::size_t n )
+ {
+ ::operator delete( p );
+ }
+};
+
+//
+
+struct D;
+
+struct X
+{
+ static int instances;
+
+ X(): deleted_( false )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ BOOST_TEST( deleted_ );
+ --instances;
+ }
+
+private:
+
+ friend struct D;
+
+ bool deleted_;
+
+ X( X const & );
+ X & operator=( X const & );
+};
+
+int X::instances = 0;
+
+struct D
+{
+ void operator()( X * px ) const
+ {
+ px->deleted_ = true;
+ delete px;
+ }
+};
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ boost::shared_ptr<void> pv( new X, D(), cxx11_allocator<X>() );
+
+ BOOST_TEST( X::instances == 1 );
+
+ pv.reset();
+
+ BOOST_TEST( X::instances == 0 );
+
+ pv.reset( new X, D(), cxx11_allocator<void>() );
+
+ BOOST_TEST( X::instances == 1 );
+
+ pv.reset();
+
+ BOOST_TEST( X::instances == 0 );
+
+ return boost::report_errors();
+}
+
+#else // !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+int main()
+{
+ return 0;
+}
+
+#endif
diff --git a/test/shared_ptr_alloc2_test.cpp b/test/shared_ptr_alloc2_test.cpp
new file mode 100644
index 0000000..89a44bb
--- /dev/null
+++ b/test/shared_ptr_alloc2_test.cpp
@@ -0,0 +1,224 @@
+#include <boost/config.hpp>
+
+// shared_ptr_alloc2_test.cpp
+//
+// Copyright (c) 2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/shared_ptr.hpp>
+#include <memory>
+#include <cstddef>
+
+// test_allocator
+
+struct test_allocator_base
+{
+ int id_;
+
+ static int last_global_id_;
+ static int count_;
+
+ explicit test_allocator_base( int id ): id_( id )
+ {
+ }
+};
+
+int test_allocator_base::last_global_id_ = 0;
+int test_allocator_base::count_ = 0;
+
+template<class T> class test_allocator: public test_allocator_base
+{
+public:
+
+ typedef T * pointer;
+ typedef T const * const_pointer;
+ typedef T & reference;
+ typedef T const & const_reference;
+ typedef T value_type;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+private:
+
+ static T * last_pointer_;
+ static std::size_t last_n_;
+ static int last_id_;
+
+public:
+
+ template<class U> struct rebind
+ {
+ typedef test_allocator<U> other;
+ };
+
+ pointer address( reference r ) const
+ {
+ return &r;
+ }
+
+ const_pointer address( const_reference s ) const
+ {
+ return &s;
+ }
+
+ explicit test_allocator( int id = 0 ): test_allocator_base( id )
+ {
+ }
+
+ template<class U> test_allocator( test_allocator<U> const & r ): test_allocator_base( r )
+ {
+ }
+
+ template<class U> test_allocator & operator=( test_allocator<U> const & r )
+ {
+ test_allocator_base::operator=( r );
+ return *this;
+ }
+
+ void deallocate( pointer p, size_type n )
+ {
+ BOOST_TEST( p == last_pointer_ );
+ BOOST_TEST( n == last_n_ );
+ BOOST_TEST( id_ == last_id_ );
+
+ --count_;
+
+ ::operator delete( p );
+ }
+
+ pointer allocate( size_type n, void const * = 0 )
+ {
+ T * p = static_cast< T* >( ::operator new( n * sizeof( T ) ) );
+
+ last_pointer_ = p;
+ last_n_ = n;
+ last_id_ = id_;
+
+ last_global_id_ = id_;
+ ++count_;
+
+ return p;
+ }
+
+ void construct( pointer p, T const & t )
+ {
+ ::new( p ) T( t );
+ }
+
+ void destroy( pointer p )
+ {
+ p->~T();
+ }
+
+ size_type max_size() const
+ {
+ return size_type( -1 ) / sizeof( T );
+ }
+};
+
+template<class T> T * test_allocator<T>::last_pointer_ = 0;
+template<class T> std::size_t test_allocator<T>::last_n_ = 0;
+template<class T> int test_allocator<T>::last_id_ = 0;
+
+template<class T, class U> inline bool operator==( test_allocator<T> const & a1, test_allocator<U> const & a2 )
+{
+ return a1.id_ == a2.id_;
+}
+
+template<class T, class U> inline bool operator!=( test_allocator<T> const & a1, test_allocator<U> const & a2 )
+{
+ return a1.id_ != a2.id_;
+}
+
+template<> class test_allocator<void>: public test_allocator_base
+{
+public:
+
+ typedef void * pointer;
+ typedef void const * const_pointer;
+ typedef void value_type;
+
+ template<class U> struct rebind
+ {
+ typedef test_allocator<U> other;
+ };
+
+ explicit test_allocator( int id = 0 ): test_allocator_base( id )
+ {
+ }
+
+ template<class U> test_allocator( test_allocator<U> const & r ): test_allocator_base( r )
+ {
+ }
+
+ template<class U> test_allocator & operator=( test_allocator<U> const & r )
+ {
+ test_allocator_base::operator=( r );
+ return *this;
+ }
+};
+
+//
+
+struct X
+{
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+};
+
+int X::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ boost::shared_ptr<void> pv( new X, boost::checked_deleter<X>(), std::allocator<X>() );
+
+ BOOST_TEST( X::instances == 1 );
+
+ pv.reset( new X, boost::checked_deleter<X>(), test_allocator<float>( 42 ) );
+
+ BOOST_TEST( X::instances == 1 );
+
+ BOOST_TEST( test_allocator_base::last_global_id_ == 42 );
+ BOOST_TEST( test_allocator_base::count_ > 0 );
+
+ pv.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( test_allocator_base::count_ == 0 );
+
+ pv.reset( new X, boost::checked_deleter<X>(), test_allocator<void>( 43 ) );
+
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( test_allocator_base::last_global_id_ == 43 );
+
+ pv.reset( new X, boost::checked_deleter<X>(), std::allocator<void>() );
+
+ BOOST_TEST( X::instances == 1 );
+
+ pv.reset();
+
+ BOOST_TEST( X::instances == 0 );
+
+ return boost::report_errors();
+}
diff --git a/test/shared_ptr_alloc3_test.cpp b/test/shared_ptr_alloc3_test.cpp
new file mode 100644
index 0000000..011e9cf
--- /dev/null
+++ b/test/shared_ptr_alloc3_test.cpp
@@ -0,0 +1,78 @@
+#include <boost/config.hpp>
+
+// shared_ptr_alloc3_test.cpp
+//
+// Copyright (c) 2005, 2014 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
+
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/shared_ptr.hpp>
+#include <memory>
+#include <cstddef>
+
+//
+
+struct D;
+
+struct X
+{
+ static int instances;
+
+ X(): deleted_( false )
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ BOOST_TEST( deleted_ );
+ --instances;
+ }
+
+private:
+
+ friend struct D;
+
+ bool deleted_;
+
+ X( X const & );
+ X & operator=( X const & );
+};
+
+int X::instances = 0;
+
+struct D
+{
+ void operator()( X * px ) const
+ {
+ px->deleted_ = true;
+ delete px;
+ }
+};
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ boost::shared_ptr<void> pv( new X, D(), std::allocator<X>() );
+
+ BOOST_TEST( X::instances == 1 );
+
+ pv.reset();
+
+ BOOST_TEST( X::instances == 0 );
+
+ pv.reset( new X, D(), std::allocator<void>() );
+
+ BOOST_TEST( X::instances == 1 );
+
+ pv.reset();
+
+ BOOST_TEST( X::instances == 0 );
+
+ return boost::report_errors();
+}
diff --git a/test/shared_ptr_alloc_construct11_test.cpp b/test/shared_ptr_alloc_construct11_test.cpp
new file mode 100644
index 0000000..3ddabc8
--- /dev/null
+++ b/test/shared_ptr_alloc_construct11_test.cpp
@@ -0,0 +1,128 @@
+/*
+Copyright 2017 Glen Joseph Fernandes
+(glenjofe@gmail.com)
+
+Distributed under the Boost Software License, Version 1.0.
+(http://www.boost.org/LICENSE_1_0.txt)
+*/
+#include <boost/core/lightweight_test.hpp>
+#include <boost/make_shared.hpp>
+
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+struct counters {
+ unsigned allocate;
+ unsigned construct;
+};
+
+template<class T = void>
+class creator {
+public:
+ typedef T value_type;
+
+ creator(counters* state)
+ : state_(state) { }
+
+ template<class U>
+ creator(const creator<U>& other)
+ : state_(other.state()) { }
+
+ T* allocate(std::size_t size) {
+ void* ptr = ::operator new(sizeof(T) * size);
+ ++state_->allocate;
+ return static_cast<T*>(ptr);
+ }
+
+ void deallocate(T* ptr, std::size_t) {
+ ::operator delete(ptr);
+ --state_->allocate;
+ }
+
+ template<class... Args>
+ void construct(T* ptr, Args&&... args) {
+ ::new(static_cast<void*>(ptr)) T(std::forward<Args>(args)...);
+ ++state_->construct;
+ }
+
+ void destroy(T* ptr) {
+ ptr->~T();
+ --state_->construct;
+ }
+
+ counters* state() const {
+ return state_;
+ }
+
+private:
+ counters* state_;
+};
+
+template<class T, class U>
+inline bool
+operator==(const creator<T>& lhs, const creator<U>& rhs)
+{
+ return lhs.state() == rhs.state();
+}
+
+template<class T, class U>
+inline bool
+operator!=(const creator<T>& lhs, const creator<U>& rhs)
+{
+ return !(lhs == rhs);
+}
+
+struct deleter {
+ template<class U>
+ void operator()(U ptr) const {
+ delete ptr;
+ }
+};
+
+int main()
+{
+ {
+ counters state = { };
+ boost::shared_ptr<int> pointer(new int(), deleter(),
+ creator<int>(&state));
+ BOOST_TEST(state.allocate == 1);
+ BOOST_TEST(state.construct == 0);
+ pointer.reset();
+ BOOST_TEST(state.allocate == 0);
+ }
+ {
+ counters state = { };
+ boost::shared_ptr<int> pointer =
+ boost::allocate_shared<int>(creator<int>(&state));
+ BOOST_TEST(state.allocate == 1);
+ BOOST_TEST(state.construct == 1);
+ pointer.reset();
+ BOOST_TEST(state.allocate == 0);
+ BOOST_TEST(state.construct == 0);
+ }
+ {
+ counters state = { };
+ boost::shared_ptr<int[]> pointer =
+ boost::allocate_shared<int[]>(creator<>(&state), 5);
+ BOOST_TEST(state.allocate == 1);
+ BOOST_TEST(state.construct == 5);
+ pointer.reset();
+ BOOST_TEST(state.allocate == 0);
+ BOOST_TEST(state.construct == 0);
+ }
+ {
+ counters state = { };
+ boost::shared_ptr<int[5]> pointer =
+ boost::allocate_shared<int[5]>(creator<>(&state));
+ BOOST_TEST(state.allocate == 1);
+ BOOST_TEST(state.construct == 5);
+ pointer.reset();
+ BOOST_TEST(state.allocate == 0);
+ BOOST_TEST(state.construct == 0);
+ }
+ return boost::report_errors();
+}
+#else
+int main()
+{
+ return 0;
+}
+#endif
diff --git a/test/shared_ptr_alloc_test.cpp b/test/shared_ptr_alloc_test.cpp
new file mode 100644
index 0000000..0dedc37
--- /dev/null
+++ b/test/shared_ptr_alloc_test.cpp
@@ -0,0 +1,166 @@
+//
+// shared_ptr_alloc_test.cpp - use to evaluate the impact of count allocations
+//
+// Copyright (c) 2002, 2003 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/config.hpp>
+#include <boost/detail/quick_allocator.hpp>
+
+#include <iostream>
+#include <vector>
+#include <ctime>
+#include <cstddef>
+#include <memory>
+
+int const n = 1024 * 1024;
+
+template<class T> void test(T * = 0)
+{
+ std::clock_t t = std::clock();
+ std::clock_t t2;
+
+ {
+ std::vector< boost::shared_ptr<T> > v;
+
+ for(int i = 0; i < n; ++i)
+ {
+ boost::shared_ptr<T> pi(new T(i));
+ v.push_back(pi);
+ }
+
+ t2 = std::clock();
+ }
+
+ std::clock_t t3 = std::clock();
+
+ std::cout << " " << static_cast<double>(t3 - t) / CLOCKS_PER_SEC << " seconds, " << static_cast<double>(t2 - t) / CLOCKS_PER_SEC << " + " << static_cast<double>(t3 - t2) / CLOCKS_PER_SEC << ".\n";
+}
+
+class X
+{
+public:
+
+ explicit X(int n): n_(n)
+ {
+ }
+
+ void * operator new(std::size_t)
+ {
+ return std::allocator<X>().allocate(1, static_cast<X*>(0));
+ }
+
+ void operator delete(void * p)
+ {
+ std::allocator<X>().deallocate(static_cast<X*>(p), 1);
+ }
+
+private:
+
+ X(X const &);
+ X & operator=(X const &);
+
+ int n_;
+};
+
+class Y
+{
+public:
+
+ explicit Y(int n): n_(n)
+ {
+ }
+
+ void * operator new(std::size_t n)
+ {
+ return boost::detail::quick_allocator<Y>::alloc(n);
+ }
+
+ void operator delete(void * p, std::size_t n)
+ {
+ boost::detail::quick_allocator<Y>::dealloc(p, n);
+ }
+
+private:
+
+ Y(Y const &);
+ Y & operator=(Y const &);
+
+ int n_;
+};
+
+class Z: public Y
+{
+public:
+
+ explicit Z(int n): Y(n), m_(n + 1)
+ {
+ }
+
+private:
+
+ Z(Z const &);
+ Z & operator=(Z const &);
+
+ int m_;
+};
+
+int main()
+{
+ std::cout << BOOST_COMPILER "\n";
+ std::cout << BOOST_PLATFORM "\n";
+ std::cout << BOOST_STDLIB "\n";
+
+#if defined(BOOST_HAS_THREADS)
+ std::cout << "BOOST_HAS_THREADS: (defined)\n";
+#else
+ std::cout << "BOOST_HAS_THREADS: (not defined)\n";
+#endif
+
+#if defined(BOOST_SP_USE_STD_ALLOCATOR)
+ std::cout << "BOOST_SP_USE_STD_ALLOCATOR: (defined)\n";
+#else
+ std::cout << "BOOST_SP_USE_STD_ALLOCATOR: (not defined)\n";
+#endif
+
+#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
+ std::cout << "BOOST_SP_USE_QUICK_ALLOCATOR: (defined)\n";
+#else
+ std::cout << "BOOST_SP_USE_QUICK_ALLOCATOR: (not defined)\n";
+#endif
+
+#if defined(BOOST_QA_PAGE_SIZE)
+ std::cout << "BOOST_QA_PAGE_SIZE: " << BOOST_QA_PAGE_SIZE << "\n";
+#else
+ std::cout << "BOOST_QA_PAGE_SIZE: (not defined)\n";
+#endif
+
+ std::cout << n << " shared_ptr<int> allocations + deallocations:\n";
+
+ test<int>();
+ test<int>();
+ test<int>();
+
+ std::cout << n << " shared_ptr<X> allocations + deallocations:\n";
+
+ test<X>();
+ test<X>();
+ test<X>();
+
+ std::cout << n << " shared_ptr<Y> allocations + deallocations:\n";
+
+ test<Y>();
+ test<Y>();
+ test<Y>();
+
+ std::cout << n << " shared_ptr<Z> allocations + deallocations:\n";
+
+ test<Z>();
+ test<Z>();
+ test<Z>();
+}
diff --git a/test/shared_ptr_assign_fail.cpp b/test/shared_ptr_assign_fail.cpp
new file mode 100644
index 0000000..c2820e0
--- /dev/null
+++ b/test/shared_ptr_assign_fail.cpp
@@ -0,0 +1,32 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#endif
+
+//
+// shared_ptr_assign_fail.cpp - a negative test for shared_ptr assignment
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+//
+// 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)
+//
+
+#include <boost/shared_ptr.hpp>
+
+bool boost_error(char const *, char const *, char const *, long)
+{
+ return true;
+}
+
+int main()
+{
+ boost::shared_ptr<int> p;
+ p = new int(42); // assignment must fail
+ return 0;
+}
diff --git a/test/shared_ptr_basic_test.cpp b/test/shared_ptr_basic_test.cpp
new file mode 100644
index 0000000..4d4179e
--- /dev/null
+++ b/test/shared_ptr_basic_test.cpp
@@ -0,0 +1,311 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#pragma warning(disable: 4355) // 'this' : used in base member initializer list
+
+#if (BOOST_MSVC >= 1310)
+#pragma warning(disable: 4675) // resolved overload found with Koenig lookup
+#endif
+
+#endif
+
+//
+// shared_ptr_basic_test.cpp
+//
+// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
+//
+// 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)
+//
+
+#include <boost/detail/lightweight_test.hpp>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+int cnt = 0;
+
+struct X
+{
+ X()
+ {
+ ++cnt;
+ }
+
+ ~X() // virtual destructor deliberately omitted
+ {
+ --cnt;
+ }
+
+ virtual int id() const
+ {
+ return 1;
+ }
+
+private:
+
+ X(X const &);
+ X & operator= (X const &);
+};
+
+struct Y: public X
+{
+ Y()
+ {
+ ++cnt;
+ }
+
+ ~Y()
+ {
+ --cnt;
+ }
+
+ virtual int id() const
+ {
+ return 2;
+ }
+
+private:
+
+ Y(Y const &);
+ Y & operator= (Y const &);
+};
+
+int * get_object()
+{
+ ++cnt;
+ return &cnt;
+}
+
+void release_object(int * p)
+{
+ BOOST_TEST(p == &cnt);
+ --cnt;
+}
+
+template<class T> void test_is_X(boost::shared_ptr<T> const & p)
+{
+ BOOST_TEST(p->id() == 1);
+ BOOST_TEST((*p).id() == 1);
+}
+
+template<class T> void test_is_X(boost::weak_ptr<T> const & p)
+{
+ BOOST_TEST(p.get() != 0);
+ BOOST_TEST(p.get()->id() == 1);
+}
+
+template<class T> void test_is_Y(boost::shared_ptr<T> const & p)
+{
+ BOOST_TEST(p->id() == 2);
+ BOOST_TEST((*p).id() == 2);
+}
+
+template<class T> void test_is_Y(boost::weak_ptr<T> const & p)
+{
+ boost::shared_ptr<T> q = p.lock();
+ BOOST_TEST(q.get() != 0);
+ BOOST_TEST(q->id() == 2);
+}
+
+template<class T> void test_eq(T const & a, T const & b)
+{
+ BOOST_TEST(a == b);
+ BOOST_TEST(!(a != b));
+ BOOST_TEST(!(a < b));
+ BOOST_TEST(!(b < a));
+}
+
+template<class T> void test_ne(T const & a, T const & b)
+{
+ BOOST_TEST(!(a == b));
+ BOOST_TEST(a != b);
+ BOOST_TEST(a < b || b < a);
+ BOOST_TEST(!(a < b && b < a));
+}
+
+template<class T, class U> void test_shared(boost::weak_ptr<T> const & a, boost::weak_ptr<U> const & b)
+{
+ BOOST_TEST(!(a < b));
+ BOOST_TEST(!(b < a));
+}
+
+template<class T, class U> void test_nonshared(boost::weak_ptr<T> const & a, boost::weak_ptr<U> const & b)
+{
+ BOOST_TEST(a < b || b < a);
+ BOOST_TEST(!(a < b && b < a));
+}
+
+template<class T, class U> void test_eq2(T const & a, U const & b)
+{
+ BOOST_TEST(a == b);
+ BOOST_TEST(!(a != b));
+}
+
+template<class T, class U> void test_ne2(T const & a, U const & b)
+{
+ BOOST_TEST(!(a == b));
+ BOOST_TEST(a != b);
+}
+
+template<class T> void test_is_zero(boost::shared_ptr<T> const & p)
+{
+ BOOST_TEST(!p);
+ BOOST_TEST(p.get() == 0);
+}
+
+template<class T> void test_is_nonzero(boost::shared_ptr<T> const & p)
+{
+ // p? true: false is used to test p in a boolean context.
+ // BOOST_TEST(p) is not guaranteed to test the conversion,
+ // as the macro might test !!p instead.
+ BOOST_TEST(p? true: false);
+ BOOST_TEST(p.get() != 0);
+}
+
+int main()
+{
+ using namespace boost;
+
+ {
+ shared_ptr<X> p(new Y);
+ shared_ptr<X> p2(new X);
+
+ test_is_nonzero(p);
+ test_is_nonzero(p2);
+ test_is_Y(p);
+ test_is_X(p2);
+ test_ne(p, p2);
+
+ {
+ shared_ptr<X> q(p);
+ test_eq(p, q);
+ }
+
+#if !defined( BOOST_NO_RTTI )
+ shared_ptr<Y> p3 = dynamic_pointer_cast<Y>(p);
+ shared_ptr<Y> p4 = dynamic_pointer_cast<Y>(p2);
+
+ test_is_nonzero(p3);
+ test_is_zero(p4);
+
+ BOOST_TEST(p.use_count() == 2);
+ BOOST_TEST(p2.use_count() == 1);
+ BOOST_TEST(p3.use_count() == 2);
+
+ test_is_Y(p3);
+ test_eq2(p, p3);
+ test_ne2(p2, p4);
+#endif
+
+ shared_ptr<void> p5(p);
+
+ test_is_nonzero(p5);
+ test_eq2(p, p5);
+
+ weak_ptr<X> wp1(p2);
+
+ BOOST_TEST(!wp1.expired());
+ BOOST_TEST(wp1.use_count() != 0);
+
+ p.reset();
+ p2.reset();
+#if !defined( BOOST_NO_RTTI )
+ p3.reset();
+ p4.reset();
+#endif
+
+ test_is_zero(p);
+ test_is_zero(p2);
+#if !defined( BOOST_NO_RTTI )
+ test_is_zero(p3);
+ test_is_zero(p4);
+#endif
+
+ BOOST_TEST(p5.use_count() == 1);
+
+ BOOST_TEST(wp1.expired());
+ BOOST_TEST(wp1.use_count() == 0);
+
+ try
+ {
+ shared_ptr<X> sp1(wp1);
+ BOOST_ERROR("shared_ptr<X> sp1(wp1) failed to throw");
+ }
+ catch(boost::bad_weak_ptr const &)
+ {
+ }
+
+ test_is_zero(wp1.lock());
+
+ weak_ptr<X> wp2 = static_pointer_cast<X>(p5);
+
+ BOOST_TEST(wp2.use_count() == 1);
+ test_is_Y(wp2);
+ test_nonshared(wp1, wp2);
+
+ // Scoped to not affect the subsequent use_count() tests.
+ {
+ shared_ptr<X> sp2(wp2);
+ test_is_nonzero(wp2.lock());
+ }
+
+#if !defined( BOOST_NO_RTTI )
+ weak_ptr<Y> wp3 = dynamic_pointer_cast<Y>(wp2.lock());
+
+ BOOST_TEST(wp3.use_count() == 1);
+ test_shared(wp2, wp3);
+
+ weak_ptr<X> wp4(wp3);
+
+ BOOST_TEST(wp4.use_count() == 1);
+ test_shared(wp2, wp4);
+#endif
+
+ wp1 = p2;
+ test_is_zero(wp1.lock());
+
+#if !defined( BOOST_NO_RTTI )
+ wp1 = p4;
+ wp1 = wp3;
+#endif
+ wp1 = wp2;
+
+ BOOST_TEST(wp1.use_count() == 1);
+ test_shared(wp1, wp2);
+
+ weak_ptr<X> wp5;
+
+ bool b1 = wp1 < wp5;
+ bool b2 = wp5 < wp1;
+
+ p5.reset();
+
+ BOOST_TEST(wp1.use_count() == 0);
+ BOOST_TEST(wp2.use_count() == 0);
+#if !defined( BOOST_NO_RTTI )
+ BOOST_TEST(wp3.use_count() == 0);
+#endif
+
+ // Test operator< stability for std::set< weak_ptr<> >
+ // Thanks to Joe Gottman for pointing this out
+
+ BOOST_TEST(b1 == (wp1 < wp5));
+ BOOST_TEST(b2 == (wp5 < wp1));
+
+ {
+ // note that both get_object and release_object deal with int*
+ shared_ptr<void> p6(get_object(), release_object);
+ }
+ }
+
+ BOOST_TEST(cnt == 0);
+
+ return boost::report_errors();
+}
diff --git a/test/shared_ptr_compare_fail.cpp b/test/shared_ptr_compare_fail.cpp
new file mode 100644
index 0000000..296af14
--- /dev/null
+++ b/test/shared_ptr_compare_fail.cpp
@@ -0,0 +1,27 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#endif
+
+//
+// shared_ptr_compare_fail.cpp - a negative test for "p > q"
+//
+// Copyright 2006 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)
+//
+
+#include <boost/shared_ptr.hpp>
+
+int main()
+{
+ boost::shared_ptr<int> p, q;
+ p > q; // must fail
+ return 0;
+}
diff --git a/test/shared_ptr_convertible_test.cpp b/test/shared_ptr_convertible_test.cpp
new file mode 100644
index 0000000..7f49e1f
--- /dev/null
+++ b/test/shared_ptr_convertible_test.cpp
@@ -0,0 +1,71 @@
+#include <boost/config.hpp>
+
+// sp_convertible_test.cpp
+//
+// Copyright (c) 2008 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/shared_ptr.hpp>
+
+//
+
+class incomplete;
+
+struct X
+{
+};
+
+struct Y
+{
+};
+
+struct Z: public X
+{
+};
+
+int f( boost::shared_ptr<void const> )
+{
+ return 1;
+}
+
+int f( boost::shared_ptr<int> )
+{
+ return 2;
+}
+
+int f( boost::shared_ptr<incomplete> )
+{
+ return 3;
+}
+
+int g( boost::shared_ptr<X> )
+{
+ return 4;
+}
+
+int g( boost::shared_ptr<Y> )
+{
+ return 5;
+}
+
+int g( boost::shared_ptr<incomplete> )
+{
+ return 6;
+}
+
+int main()
+{
+ boost::shared_ptr<double> p1;
+ BOOST_TEST( 1 == f( p1 ) );
+ BOOST_TEST( 1 == f( boost::shared_ptr<double>() ) );
+
+ boost::shared_ptr<Z> p2;
+ BOOST_TEST( 4 == g( p2 ) );
+ BOOST_TEST( 4 == g( boost::shared_ptr<Z>() ) );
+
+ return boost::report_errors();
+}
diff --git a/test/shared_ptr_delete_fail.cpp b/test/shared_ptr_delete_fail.cpp
new file mode 100644
index 0000000..66cfafe
--- /dev/null
+++ b/test/shared_ptr_delete_fail.cpp
@@ -0,0 +1,27 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#endif
+
+//
+// shared_ptr_delete_fail.cpp - a negative test for "delete sp;"
+//
+// Copyright 2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/shared_ptr.hpp>
+
+int main()
+{
+ boost::shared_ptr<int> p;
+ delete p; // must fail
+ return 0;
+}
diff --git a/test/shared_ptr_fn_test.cpp b/test/shared_ptr_fn_test.cpp
new file mode 100644
index 0000000..dfbdf18
--- /dev/null
+++ b/test/shared_ptr_fn_test.cpp
@@ -0,0 +1,43 @@
+//
+// shared_ptr_fn_test.cpp
+//
+// 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+static void f()
+{
+}
+
+struct null_deleter
+{
+ template<class Y> void operator()( Y* ) {}
+};
+
+int main()
+{
+ boost::shared_ptr<void()> pf( f, null_deleter() );
+
+ BOOST_TEST( pf.get() == f );
+ BOOST_TEST_EQ( pf.use_count(), 1 );
+ BOOST_TEST( boost::get_deleter<null_deleter>( pf ) != 0 );
+
+ boost::weak_ptr<void()> wp( pf );
+
+ BOOST_TEST( wp.lock().get() == f );
+ BOOST_TEST_EQ( wp.use_count(), 1 );
+
+ pf.reset();
+
+ BOOST_TEST( wp.lock().get() == 0 );
+ BOOST_TEST_EQ( wp.use_count(), 0 );
+
+ return boost::report_errors();
+}
diff --git a/test/shared_ptr_move_test.cpp b/test/shared_ptr_move_test.cpp
new file mode 100644
index 0000000..e659b24
--- /dev/null
+++ b/test/shared_ptr_move_test.cpp
@@ -0,0 +1,107 @@
+//
+// shared_ptr_move_test.cpp
+//
+// Copyright (c) 2007 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <utility>
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+struct X
+{
+ static long instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+};
+
+long X::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X> p( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ boost::shared_ptr<X> p2( std::move( p ) );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ boost::shared_ptr<void> p3( std::move( p2 ) );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p2.get() == 0 );
+
+ p3.reset();
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr<X> p( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ boost::shared_ptr<X> p2;
+ p2 = std::move( p );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ boost::shared_ptr<void> p3;
+ p3 = std::move( p2 );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p2.get() == 0 );
+
+ p3.reset();
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ boost::shared_ptr<X> p( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ boost::shared_ptr<X> p2( new X );
+ BOOST_TEST( X::instances == 2 );
+ p2 = std::move( p );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ boost::shared_ptr<void> p3( new X );
+ BOOST_TEST( X::instances == 2 );
+ p3 = std::move( p2 );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p2.get() == 0 );
+
+ p3.reset();
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ return boost::report_errors();
+}
+
+#else // defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+int main()
+{
+ return 0;
+}
+
+#endif
diff --git a/test/shared_ptr_pv_fail.cpp b/test/shared_ptr_pv_fail.cpp
new file mode 100644
index 0000000..924e657
--- /dev/null
+++ b/test/shared_ptr_pv_fail.cpp
@@ -0,0 +1,31 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#endif
+
+//
+// shared_ptr_pv_fail.cpp - a negative test for converting a shared_ptr to void*
+//
+// Copyright 2007 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+void f( void* )
+{
+}
+
+int main()
+{
+ boost::shared_ptr<int> p;
+ f( p ); // must fail
+ return 0;
+}
diff --git a/test/shared_ptr_reinterpret_pointer_cast_test.cpp b/test/shared_ptr_reinterpret_pointer_cast_test.cpp
new file mode 100644
index 0000000..e7076df
--- /dev/null
+++ b/test/shared_ptr_reinterpret_pointer_cast_test.cpp
@@ -0,0 +1,55 @@
+//
+// shared_pointer_reinterpret_pointer_cast_test.cpp
+//
+// Copyright (c) 2016 Chris Glover
+//
+// 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+struct X
+{};
+
+int main()
+{
+ {
+ boost::shared_ptr<char> pc;
+
+ boost::shared_ptr<int> pi = boost::reinterpret_pointer_cast<int>(pc);
+ BOOST_TEST(pi.get() == 0);
+
+ boost::shared_ptr<X> px = boost::reinterpret_pointer_cast<X>(pc);
+ BOOST_TEST(px.get() == 0);
+ }
+
+ {
+ boost::shared_ptr<int> pi(new int);
+ boost::shared_ptr<char> pc = boost::reinterpret_pointer_cast<char>(pi);
+
+ boost::shared_ptr<int> pi2 = boost::reinterpret_pointer_cast<int>(pc);
+ BOOST_TEST(pi.get() == pi2.get());
+ BOOST_TEST(!(pi < pi2 || pi2 < pi));
+ BOOST_TEST(pi.use_count() == 3);
+ BOOST_TEST(pc.use_count() == 3);
+ BOOST_TEST(pi2.use_count() == 3);
+ }
+
+ {
+ boost::shared_ptr<X> px(new X);
+ boost::shared_ptr<char> pc = boost::reinterpret_pointer_cast<char>(px);
+
+ boost::shared_ptr<X> px2 = boost::reinterpret_pointer_cast<X>(pc);
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+ BOOST_TEST(px.use_count() == 3);
+ BOOST_TEST(pc.use_count() == 3);
+ BOOST_TEST(px2.use_count() == 3);
+ }
+
+ return boost::report_errors();
+}
+
diff --git a/test/shared_ptr_rv_pointer_cast_test.cpp b/test/shared_ptr_rv_pointer_cast_test.cpp
new file mode 100644
index 0000000..c471bda
--- /dev/null
+++ b/test/shared_ptr_rv_pointer_cast_test.cpp
@@ -0,0 +1,106 @@
+//
+// shared_ptr_rv_pointer_cast_test.cpp
+//
+// Copyright (c) 2016 Chris Glover
+//
+// 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+struct X
+{};
+
+struct Y: public X
+{};
+
+struct U
+{
+ virtual ~U() {}
+};
+
+struct V: public U
+{};
+
+struct W : public U
+{};
+
+int main()
+{
+ {
+ boost::shared_ptr<X> px(new Y);
+
+ boost::shared_ptr<Y> py1 = boost::static_pointer_cast<Y>(px);
+ boost::shared_ptr<Y> py2 = boost::static_pointer_cast<Y>(std::move(px));
+ BOOST_TEST(!px);
+ BOOST_TEST(px.use_count() == 0);
+ BOOST_TEST(py1.get() == py2.get());
+ BOOST_TEST(!(py1 < py2 || py2 < py1));
+ BOOST_TEST(py1.use_count() == 2);
+ BOOST_TEST(py2.use_count() == 2);
+ }
+
+ {
+ boost::shared_ptr<int const volatile> px(new int);
+
+ boost::shared_ptr<int> px2 = boost::const_pointer_cast<int>(px);
+ boost::shared_ptr<int> px3 = boost::const_pointer_cast<int>(std::move(px));
+ BOOST_TEST(!px);
+ BOOST_TEST(px.use_count() == 0);
+ BOOST_TEST(px2.get() == px3.get());
+ BOOST_TEST(!(px2 < px3 || px2 < px3));
+ BOOST_TEST(px2.use_count() == 2);
+ BOOST_TEST(px3.use_count() == 2);
+ }
+
+ {
+ boost::shared_ptr<char> pv(reinterpret_cast<char*>(new Y));
+
+ boost::shared_ptr<Y> py1 = boost::reinterpret_pointer_cast<Y>(pv);
+ boost::shared_ptr<Y> py2 = boost::reinterpret_pointer_cast<Y>(std::move(pv));
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.use_count() == 0);
+ BOOST_TEST(py1.get() == py2.get());
+ BOOST_TEST(!(py1 < py2 || py2 < py1));
+ BOOST_TEST(py1.use_count() == 2);
+ BOOST_TEST(py2.use_count() == 2);
+ }
+
+#if !defined( BOOST_NO_RTTI )
+ {
+ boost::shared_ptr<U> pu(new V);
+
+ boost::shared_ptr<V> pv1 = boost::dynamic_pointer_cast<V>(pu);
+ boost::shared_ptr<V> pv2 = boost::dynamic_pointer_cast<V>(std::move(pu));
+ BOOST_TEST(!pu);
+ BOOST_TEST(pu.use_count() == 0);
+ BOOST_TEST(pv1.get() == pv2.get());
+ BOOST_TEST(!(pv1 < pv2 || pv2 < pv1));
+ BOOST_TEST(pv1.use_count() == 2);
+ BOOST_TEST(pv2.use_count() == 2);
+ }
+
+ {
+ boost::shared_ptr<U> pu(new V);
+ boost::shared_ptr<W> pw = boost::dynamic_pointer_cast<W>(std::move(pu));
+ BOOST_TEST(!pw);
+ BOOST_TEST(pu);
+ }
+#endif // !defined( BOOST_NO_RTTI )
+
+ return boost::report_errors();
+}
+
+#else // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+int main()
+{
+ return 0;
+}
+
+#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
diff --git a/test/shared_ptr_rv_test.cpp b/test/shared_ptr_rv_test.cpp
new file mode 100644
index 0000000..fe77259
--- /dev/null
+++ b/test/shared_ptr_rv_test.cpp
@@ -0,0 +1,110 @@
+//
+// shared_ptr_rv_test.cpp
+//
+// Copyright (c) 2007 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+struct X
+{
+ static long instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+ static boost::shared_ptr<X> create()
+ {
+ return boost::shared_ptr<X>( new X );
+ }
+
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+};
+
+long X::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X> p( X::create() );
+ BOOST_TEST( X::instances == 1 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+
+ p.reset();
+ BOOST_TEST( X::instances == 0 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X const> p( X::create() );
+ BOOST_TEST( X::instances == 1 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+
+ p.reset();
+ BOOST_TEST( X::instances == 0 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<void> p( X::create() );
+ BOOST_TEST( X::instances == 1 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+
+ p.reset();
+ BOOST_TEST( X::instances == 0 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<void const> p( X::create() );
+ BOOST_TEST( X::instances == 1 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+
+ p.reset();
+ BOOST_TEST( X::instances == 0 );
+
+ p = X::create();
+ BOOST_TEST( X::instances == 1 );
+ }
+
+ BOOST_TEST( X::instances == 0 );
+
+ return boost::report_errors();
+}
diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp
new file mode 100644
index 0000000..fdfb215
--- /dev/null
+++ b/test/shared_ptr_test.cpp
@@ -0,0 +1,3396 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#pragma warning(disable: 4355) // 'this' : used in base member initializer list
+
+#if (BOOST_MSVC >= 1310)
+#pragma warning(disable: 4675) // resolved overload found with Koenig lookup
+#endif
+
+#endif
+
+//
+// shared_ptr_test.cpp
+//
+// Copyright (c) 2002, 2003 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/detail/lightweight_test.hpp>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+#include <map>
+#include <vector>
+
+//
+
+namespace n_element_type
+{
+
+void f(int &)
+{
+}
+
+void test()
+{
+ typedef boost::shared_ptr<int>::element_type T;
+ T t;
+ f(t);
+}
+
+} // namespace n_element_type
+
+namespace n_constructors
+{
+
+class incomplete;
+
+void default_constructor()
+{
+ {
+ boost::shared_ptr<int> pi;
+ BOOST_TEST(pi? false: true);
+ BOOST_TEST(!pi);
+ BOOST_TEST(pi.get() == 0);
+ BOOST_TEST(pi.use_count() == 0);
+ }
+
+ {
+ boost::shared_ptr<void> pv;
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 0);
+ }
+
+ {
+ boost::shared_ptr<incomplete> px;
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 0);
+ }
+}
+
+struct A
+{
+ int dummy;
+};
+
+struct X
+{
+ static long instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X(X const &);
+ X & operator= (X const &);
+};
+
+long X::instances = 0;
+
+// virtual inheritance stresses the implementation
+
+struct Y: public A, public virtual X
+{
+ static long instances;
+
+ Y()
+ {
+ ++instances;
+ }
+
+ ~Y()
+ {
+ --instances;
+ }
+
+private:
+
+ Y(Y const &);
+ Y & operator= (Y const &);
+};
+
+long Y::instances = 0;
+
+template<class T> void pc0_test(T * p)
+{
+ BOOST_TEST(p == 0);
+ boost::shared_ptr<T> pt(p);
+ BOOST_TEST(pt? false: true);
+ BOOST_TEST(!pt);
+ BOOST_TEST(pt.get() == 0);
+ BOOST_TEST(pt.use_count() == 1);
+ BOOST_TEST(pt.unique());
+}
+
+void pointer_constructor()
+{
+ pc0_test(static_cast<int*>(0));
+
+#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1300)
+
+ pc0_test(static_cast<int const*>(0));
+ pc0_test(static_cast<int volatile*>(0));
+ pc0_test(static_cast<int const volatile*>(0));
+
+#endif
+
+ {
+ boost::shared_ptr<int const> pi(static_cast<int*>(0));
+ BOOST_TEST(pi? false: true);
+ BOOST_TEST(!pi);
+ BOOST_TEST(pi.get() == 0);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+ }
+
+ {
+ boost::shared_ptr<int volatile> pi(static_cast<int*>(0));
+ BOOST_TEST(pi? false: true);
+ BOOST_TEST(!pi);
+ BOOST_TEST(pi.get() == 0);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+ }
+
+ {
+ boost::shared_ptr<void> pv(static_cast<int*>(0));
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ }
+
+ {
+ boost::shared_ptr<void const> pv(static_cast<int*>(0));
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ }
+
+ pc0_test(static_cast<X*>(0));
+ pc0_test(static_cast<X const*>(0));
+ pc0_test(static_cast<X volatile*>(0));
+ pc0_test(static_cast<X const volatile*>(0));
+
+ {
+ boost::shared_ptr<X const> px(static_cast<X*>(0));
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ }
+
+ {
+ boost::shared_ptr<X> px(static_cast<Y*>(0));
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ }
+
+ {
+ boost::shared_ptr<X const> px(static_cast<Y*>(0));
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ }
+
+ {
+ boost::shared_ptr<void> pv(static_cast<X*>(0));
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ }
+
+ {
+ boost::shared_ptr<void const> pv(static_cast<X*>(0));
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ }
+
+ {
+ int * p = new int(7);
+ boost::shared_ptr<int> pi(p);
+ BOOST_TEST(pi? true: false);
+ BOOST_TEST(!!pi);
+ BOOST_TEST(pi.get() == p);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+ BOOST_TEST(*pi == 7);
+ }
+
+ {
+ int * p = new int(7);
+ boost::shared_ptr<int const> pi(p);
+ BOOST_TEST(pi? true: false);
+ BOOST_TEST(!!pi);
+ BOOST_TEST(pi.get() == p);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+ BOOST_TEST(*pi == 7);
+ }
+
+ {
+ int * p = new int(7);
+ boost::shared_ptr<void> pv(p);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == p);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ }
+
+ {
+ int * p = new int(7);
+ boost::shared_ptr<void const> pv(p);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == p);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ }
+
+ BOOST_TEST(X::instances == 0);
+
+ {
+ X * p = new X;
+ boost::shared_ptr<X> px(p);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(px.get() == p);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(X::instances == 1);
+ }
+
+ BOOST_TEST(X::instances == 0);
+
+ {
+ X * p = new X;
+ boost::shared_ptr<X const> px(p);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(px.get() == p);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(X::instances == 1);
+ }
+
+ BOOST_TEST(X::instances == 0);
+
+ {
+ X * p = new X;
+ boost::shared_ptr<void> pv(p);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == p);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ BOOST_TEST(X::instances == 1);
+ }
+
+ BOOST_TEST(X::instances == 0);
+
+ {
+ X * p = new X;
+ boost::shared_ptr<void const> pv(p);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == p);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ BOOST_TEST(X::instances == 1);
+ }
+
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+
+ {
+ Y * p = new Y;
+ boost::shared_ptr<X> px(p);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(px.get() == p);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(X::instances == 1);
+ BOOST_TEST(Y::instances == 1);
+ }
+
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+
+ {
+ Y * p = new Y;
+ boost::shared_ptr<X const> px(p);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(px.get() == p);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(X::instances == 1);
+ BOOST_TEST(Y::instances == 1);
+ }
+
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+}
+
+int m = 0;
+
+void deleter(int * p)
+{
+ BOOST_TEST(p == 0);
+}
+
+void deleter2(int * p)
+{
+ BOOST_TEST(p == &m);
+ ++*p;
+}
+
+struct deleter3
+{
+ void operator()(incomplete * p)
+ {
+ BOOST_TEST(p == 0);
+ }
+};
+
+// Borland C++ 5.5.1 fails on static_cast<incomplete*>(0)
+
+incomplete * p0 = 0;
+
+void deleter_constructor()
+{
+ {
+ boost::shared_ptr<int> pi(static_cast<int*>(0), deleter);
+ BOOST_TEST(pi? false: true);
+ BOOST_TEST(!pi);
+ BOOST_TEST(pi.get() == 0);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+ }
+
+ {
+ boost::shared_ptr<void> pv(static_cast<int*>(0), &deleter);
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ }
+
+ {
+ boost::shared_ptr<void const> pv(static_cast<int*>(0), deleter);
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ }
+
+ {
+ boost::shared_ptr<incomplete> px(p0, deleter3());
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ }
+
+ {
+ boost::shared_ptr<void> pv(p0, deleter3());
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ }
+
+ {
+ boost::shared_ptr<void const> pv(p0, deleter3());
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ }
+
+ BOOST_TEST(m == 0);
+
+ {
+ boost::shared_ptr<int> pi(&m, deleter2);
+ BOOST_TEST(pi? true: false);
+ BOOST_TEST(!!pi);
+ BOOST_TEST(pi.get() == &m);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+ }
+
+ BOOST_TEST(m == 1);
+
+ {
+ boost::shared_ptr<int const> pi(&m, &deleter2);
+ BOOST_TEST(pi? true: false);
+ BOOST_TEST(!!pi);
+ BOOST_TEST(pi.get() == &m);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+ }
+
+ BOOST_TEST(m == 2);
+
+ {
+ boost::shared_ptr<void> pv(&m, deleter2);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == &m);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ }
+
+ BOOST_TEST(m == 3);
+
+ {
+ boost::shared_ptr<void const> pv(&m, &deleter2);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == &m);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ }
+
+ BOOST_TEST(m == 4);
+}
+
+void copy_constructor()
+{
+ {
+ boost::shared_ptr<int> pi;
+
+ boost::shared_ptr<int> pi2(pi);
+ BOOST_TEST(pi2 == pi);
+ BOOST_TEST(pi2? false: true);
+ BOOST_TEST(!pi2);
+ BOOST_TEST(pi2.get() == 0);
+ BOOST_TEST(pi2.use_count() == pi.use_count());
+
+ boost::shared_ptr<void> pi3(pi);
+ BOOST_TEST(pi3 == pi);
+ BOOST_TEST(pi3? false: true);
+ BOOST_TEST(!pi3);
+ BOOST_TEST(pi3.get() == 0);
+ BOOST_TEST(pi3.use_count() == pi.use_count());
+
+ boost::shared_ptr<void> pi4(pi3);
+ BOOST_TEST(pi4 == pi3);
+ BOOST_TEST(pi4? false: true);
+ BOOST_TEST(!pi4);
+ BOOST_TEST(pi4.get() == 0);
+ BOOST_TEST(pi4.use_count() == pi3.use_count());
+ }
+
+ {
+ boost::shared_ptr<void> pv;
+
+ boost::shared_ptr<void> pv2(pv);
+ BOOST_TEST(pv2 == pv);
+ BOOST_TEST(pv2? false: true);
+ BOOST_TEST(!pv2);
+ BOOST_TEST(pv2.get() == 0);
+ BOOST_TEST(pv2.use_count() == pv.use_count());
+ }
+
+ {
+ boost::shared_ptr<incomplete> px;
+
+ boost::shared_ptr<incomplete> px2(px);
+ BOOST_TEST(px2 == px);
+ BOOST_TEST(px2? false: true);
+ BOOST_TEST(!px2);
+ BOOST_TEST(px2.get() == 0);
+ BOOST_TEST(px2.use_count() == px.use_count());
+
+ boost::shared_ptr<void> px3(px);
+ BOOST_TEST(px3 == px);
+ BOOST_TEST(px3? false: true);
+ BOOST_TEST(!px3);
+ BOOST_TEST(px3.get() == 0);
+ BOOST_TEST(px3.use_count() == px.use_count());
+ }
+
+ {
+ boost::shared_ptr<int> pi(static_cast<int*>(0));
+
+ boost::shared_ptr<int> pi2(pi);
+ BOOST_TEST(pi2 == pi);
+ BOOST_TEST(pi2? false: true);
+ BOOST_TEST(!pi2);
+ BOOST_TEST(pi2.get() == 0);
+ BOOST_TEST(pi2.use_count() == 2);
+ BOOST_TEST(!pi2.unique());
+ BOOST_TEST(pi2.use_count() == pi.use_count());
+ BOOST_TEST(!(pi < pi2 || pi2 < pi)); // shared ownership test
+
+ boost::shared_ptr<void> pi3(pi);
+ BOOST_TEST(pi3 == pi);
+ BOOST_TEST(pi3? false: true);
+ BOOST_TEST(!pi3);
+ BOOST_TEST(pi3.get() == 0);
+ BOOST_TEST(pi3.use_count() == 3);
+ BOOST_TEST(!pi3.unique());
+ BOOST_TEST(pi3.use_count() == pi.use_count());
+ BOOST_TEST(!(pi < pi3 || pi3 < pi)); // shared ownership test
+
+ boost::shared_ptr<void> pi4(pi2);
+ BOOST_TEST(pi4 == pi2);
+ BOOST_TEST(pi4? false: true);
+ BOOST_TEST(!pi4);
+ BOOST_TEST(pi4.get() == 0);
+ BOOST_TEST(pi4.use_count() == 4);
+ BOOST_TEST(!pi4.unique());
+ BOOST_TEST(pi4.use_count() == pi2.use_count());
+ BOOST_TEST(!(pi2 < pi4 || pi4 < pi2)); // shared ownership test
+
+ BOOST_TEST(pi3.use_count() == pi4.use_count());
+ BOOST_TEST(!(pi3 < pi4 || pi4 < pi3)); // shared ownership test
+ }
+
+ {
+ boost::shared_ptr<X> px(static_cast<X*>(0));
+
+ boost::shared_ptr<X> px2(px);
+ BOOST_TEST(px2 == px);
+ BOOST_TEST(px2? false: true);
+ BOOST_TEST(!px2);
+ BOOST_TEST(px2.get() == 0);
+ BOOST_TEST(px2.use_count() == 2);
+ BOOST_TEST(!px2.unique());
+ BOOST_TEST(px2.use_count() == px.use_count());
+ BOOST_TEST(!(px < px2 || px2 < px)); // shared ownership test
+
+ boost::shared_ptr<void> px3(px);
+ BOOST_TEST(px3 == px);
+ BOOST_TEST(px3? false: true);
+ BOOST_TEST(!px3);
+ BOOST_TEST(px3.get() == 0);
+ BOOST_TEST(px3.use_count() == 3);
+ BOOST_TEST(!px3.unique());
+ BOOST_TEST(px3.use_count() == px.use_count());
+ BOOST_TEST(!(px < px3 || px3 < px)); // shared ownership test
+
+ boost::shared_ptr<void> px4(px2);
+ BOOST_TEST(px4 == px2);
+ BOOST_TEST(px4? false: true);
+ BOOST_TEST(!px4);
+ BOOST_TEST(px4.get() == 0);
+ BOOST_TEST(px4.use_count() == 4);
+ BOOST_TEST(!px4.unique());
+ BOOST_TEST(px4.use_count() == px2.use_count());
+ BOOST_TEST(!(px2 < px4 || px4 < px2)); // shared ownership test
+
+ BOOST_TEST(px3.use_count() == px4.use_count());
+ BOOST_TEST(!(px3 < px4 || px4 < px3)); // shared ownership test
+ }
+
+ {
+ int * p = new int(7);
+ boost::shared_ptr<int> pi(p);
+
+ boost::shared_ptr<int> pi2(pi);
+ BOOST_TEST(pi2 == pi);
+ BOOST_TEST(pi2? true: false);
+ BOOST_TEST(!!pi2);
+ BOOST_TEST(pi2.get() == p);
+ BOOST_TEST(pi2.use_count() == 2);
+ BOOST_TEST(!pi2.unique());
+ BOOST_TEST(*pi2 == 7);
+ BOOST_TEST(pi2.use_count() == pi.use_count());
+ BOOST_TEST(!(pi < pi2 || pi2 < pi)); // shared ownership test
+ }
+
+ {
+ int * p = new int(7);
+ boost::shared_ptr<void> pv(p);
+ BOOST_TEST(pv.get() == p);
+
+ boost::shared_ptr<void> pv2(pv);
+ BOOST_TEST(pv2 == pv);
+ BOOST_TEST(pv2? true: false);
+ BOOST_TEST(!!pv2);
+ BOOST_TEST(pv2.get() == p);
+ BOOST_TEST(pv2.use_count() == 2);
+ BOOST_TEST(!pv2.unique());
+ BOOST_TEST(pv2.use_count() == pv.use_count());
+ BOOST_TEST(!(pv < pv2 || pv2 < pv)); // shared ownership test
+ }
+
+ BOOST_TEST(X::instances == 0);
+
+ {
+ X * p = new X;
+ boost::shared_ptr<X> px(p);
+ BOOST_TEST(px.get() == p);
+
+ boost::shared_ptr<X> px2(px);
+ BOOST_TEST(px2 == px);
+ BOOST_TEST(px2? true: false);
+ BOOST_TEST(!!px2);
+ BOOST_TEST(px2.get() == p);
+ BOOST_TEST(px2.use_count() == 2);
+ BOOST_TEST(!px2.unique());
+
+ BOOST_TEST(X::instances == 1);
+
+ BOOST_TEST(px2.use_count() == px.use_count());
+ BOOST_TEST(!(px < px2 || px2 < px)); // shared ownership test
+
+ boost::shared_ptr<void> px3(px);
+ BOOST_TEST(px3 == px);
+ BOOST_TEST(px3? true: false);
+ BOOST_TEST(!!px3);
+ BOOST_TEST(px3.get() == p);
+ BOOST_TEST(px3.use_count() == 3);
+ BOOST_TEST(!px3.unique());
+ BOOST_TEST(px3.use_count() == px.use_count());
+ BOOST_TEST(!(px < px3 || px3 < px)); // shared ownership test
+
+ boost::shared_ptr<void> px4(px2);
+ BOOST_TEST(px4 == px2);
+ BOOST_TEST(px4? true: false);
+ BOOST_TEST(!!px4);
+ BOOST_TEST(px4.get() == p);
+ BOOST_TEST(px4.use_count() == 4);
+ BOOST_TEST(!px4.unique());
+ BOOST_TEST(px4.use_count() == px2.use_count());
+ BOOST_TEST(!(px2 < px4 || px4 < px2)); // shared ownership test
+
+ BOOST_TEST(px3.use_count() == px4.use_count());
+ BOOST_TEST(!(px3 < px4 || px4 < px3)); // shared ownership test
+ }
+
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+
+ {
+ Y * p = new Y;
+ boost::shared_ptr<Y> py(p);
+ BOOST_TEST(py.get() == p);
+
+ boost::shared_ptr<X> px(py);
+ BOOST_TEST(px == py);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(px.get() == p);
+ BOOST_TEST(px.use_count() == 2);
+ BOOST_TEST(!px.unique());
+ BOOST_TEST(px.use_count() == py.use_count());
+ BOOST_TEST(!(px < py || py < px)); // shared ownership test
+
+ BOOST_TEST(X::instances == 1);
+ BOOST_TEST(Y::instances == 1);
+
+ boost::shared_ptr<void const> pv(px);
+ BOOST_TEST(pv == px);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == px.get());
+ BOOST_TEST(pv.use_count() == 3);
+ BOOST_TEST(!pv.unique());
+ BOOST_TEST(pv.use_count() == px.use_count());
+ BOOST_TEST(!(px < pv || pv < px)); // shared ownership test
+
+ boost::shared_ptr<void const> pv2(py);
+ BOOST_TEST(pv2 == py);
+ BOOST_TEST(pv2? true: false);
+ BOOST_TEST(!!pv2);
+ BOOST_TEST(pv2.get() == py.get());
+ BOOST_TEST(pv2.use_count() == 4);
+ BOOST_TEST(!pv2.unique());
+ BOOST_TEST(pv2.use_count() == py.use_count());
+ BOOST_TEST(!(py < pv2 || pv2 < py)); // shared ownership test
+
+ BOOST_TEST(pv.use_count() == pv2.use_count());
+ BOOST_TEST(!(pv < pv2 || pv2 < pv)); // shared ownership test
+ }
+
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+}
+
+void weak_ptr_constructor()
+{
+ {
+ boost::weak_ptr<Y> wp;
+ BOOST_TEST(wp.use_count() == 0);
+
+ try
+ {
+ boost::shared_ptr<Y> p2(wp);
+ BOOST_ERROR("shared_ptr<Y> p2(wp) failed to throw");
+ }
+ catch(boost::bad_weak_ptr)
+ {
+ }
+
+ try
+ {
+ boost::shared_ptr<X> p3(wp);
+ BOOST_ERROR("shared_ptr<X> p3(wp) failed to throw");
+ }
+ catch(boost::bad_weak_ptr)
+ {
+ }
+ }
+
+ {
+ boost::shared_ptr<Y> p;
+ boost::weak_ptr<Y> wp(p);
+
+ if(wp.use_count() != 0) // 0 allowed but not required
+ {
+ boost::shared_ptr<Y> p2(wp);
+ BOOST_TEST(p2.use_count() == wp.use_count());
+ BOOST_TEST(p2.get() == 0);
+
+ boost::shared_ptr<X> p3(wp);
+ BOOST_TEST(p3.use_count() == wp.use_count());
+ BOOST_TEST(p3.get() == 0);
+ }
+ }
+
+ {
+ boost::shared_ptr<Y> p(new Y);
+ boost::weak_ptr<Y> wp(p);
+
+ {
+ boost::shared_ptr<Y> p2(wp);
+ BOOST_TEST(p2? true: false);
+ BOOST_TEST(!!p2);
+ BOOST_TEST(p2.get() == p.get());
+ BOOST_TEST(p2.use_count() == 2);
+ BOOST_TEST(!p2.unique());
+ BOOST_TEST(p2.use_count() == wp.use_count());
+
+ BOOST_TEST(p.use_count() == p2.use_count());
+ BOOST_TEST(!(p < p2 || p2 < p)); // shared ownership test
+
+ boost::shared_ptr<X> p3(wp);
+ BOOST_TEST(p3? true: false);
+ BOOST_TEST(!!p3);
+ BOOST_TEST(p3.get() == p.get());
+ BOOST_TEST(p3.use_count() == 3);
+ BOOST_TEST(!p3.unique());
+ BOOST_TEST(p3.use_count() == wp.use_count());
+
+ BOOST_TEST(p.use_count() == p3.use_count());
+ }
+
+ p.reset();
+ BOOST_TEST(wp.use_count() == 0);
+
+ try
+ {
+ boost::shared_ptr<Y> p2(wp);
+ BOOST_ERROR("shared_ptr<Y> p2(wp) failed to throw");
+ }
+ catch(boost::bad_weak_ptr)
+ {
+ }
+
+ try
+ {
+ boost::shared_ptr<X> p3(wp);
+ BOOST_ERROR("shared_ptr<X> p3(wp) failed to throw");
+ }
+ catch(boost::bad_weak_ptr)
+ {
+ }
+ }
+}
+
+#if defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB < 306)
+# define BOOST_OLD_AUTO_PTR
+#endif
+
+void auto_ptr_constructor()
+{
+#if !defined( BOOST_NO_AUTO_PTR )
+
+ {
+ std::auto_ptr<int> p;
+ boost::shared_ptr<int> pi(p);
+ BOOST_TEST(pi? false: true);
+ BOOST_TEST(!pi);
+ BOOST_TEST(pi.get() == 0);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+ BOOST_TEST(p.get() == 0);
+ }
+
+ {
+ std::auto_ptr<int> p;
+ boost::shared_ptr<int const> pi(p);
+ BOOST_TEST(pi? false: true);
+ BOOST_TEST(!pi);
+ BOOST_TEST(pi.get() == 0);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+ BOOST_TEST(p.get() == 0);
+ }
+
+ {
+ std::auto_ptr<int> p;
+ boost::shared_ptr<void> pv(p);
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ BOOST_TEST(p.get() == 0);
+ }
+
+ {
+ std::auto_ptr<int> p;
+ boost::shared_ptr<void const> pv(p);
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ BOOST_TEST(p.get() == 0);
+ }
+
+ {
+ std::auto_ptr<X> p;
+ boost::shared_ptr<X> px(p);
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(p.get() == 0);
+ }
+
+ {
+ std::auto_ptr<X> p;
+ boost::shared_ptr<X const> px(p);
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(p.get() == 0);
+ }
+
+ {
+ std::auto_ptr<Y> p;
+ boost::shared_ptr<X> px(p);
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(p.get() == 0);
+ }
+
+ {
+ std::auto_ptr<Y> p;
+ boost::shared_ptr<X const> px(p);
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(p.get() == 0);
+ }
+
+ {
+ std::auto_ptr<Y> p;
+ boost::shared_ptr<void> pv(p);
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ BOOST_TEST(p.get() == 0);
+ }
+
+ {
+ std::auto_ptr<Y> p;
+ boost::shared_ptr<void const> pv(p);
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ BOOST_TEST(p.get() == 0);
+ }
+
+ {
+ std::auto_ptr<int> p(new int(7));
+ int * q = p.get();
+ boost::shared_ptr<int> pi(p);
+ BOOST_TEST(pi? true: false);
+ BOOST_TEST(!!pi);
+ BOOST_TEST(pi.get() == q);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+ BOOST_TEST(*pi == 7);
+
+#if !defined(BOOST_OLD_AUTO_PTR)
+ BOOST_TEST(p.get() == 0);
+#endif
+ }
+
+ {
+ std::auto_ptr<int> p(new int(7));
+ int * q = p.get();
+ boost::shared_ptr<int const> pi(p);
+ BOOST_TEST(pi? true: false);
+ BOOST_TEST(!!pi);
+ BOOST_TEST(pi.get() == q);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+ BOOST_TEST(*pi == 7);
+
+#if !defined(BOOST_OLD_AUTO_PTR)
+ BOOST_TEST(p.get() == 0);
+#endif
+ }
+
+ {
+ std::auto_ptr<int> p(new int(7));
+ int * q = p.get();
+ boost::shared_ptr<void> pv(p);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == q);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+
+#if !defined(BOOST_OLD_AUTO_PTR)
+ BOOST_TEST(p.get() == 0);
+#endif
+ }
+
+ {
+ std::auto_ptr<int> p(new int(7));
+ int * q = p.get();
+ boost::shared_ptr<void const> pv(p);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == q);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+
+#if !defined(BOOST_OLD_AUTO_PTR)
+ BOOST_TEST(p.get() == 0);
+#endif
+ }
+
+ BOOST_TEST(X::instances == 0);
+
+ {
+ std::auto_ptr<X> p(new X);
+ X * q = p.get();
+ boost::shared_ptr<X> px(p);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(px.get() == q);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(X::instances == 1);
+
+#if !defined(BOOST_OLD_AUTO_PTR)
+ BOOST_TEST(p.get() == 0);
+#endif
+ }
+
+ BOOST_TEST(X::instances == 0);
+
+ {
+ std::auto_ptr<X> p(new X);
+ X * q = p.get();
+ boost::shared_ptr<X const> px(p);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(px.get() == q);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(X::instances == 1);
+
+#if !defined(BOOST_OLD_AUTO_PTR)
+ BOOST_TEST(p.get() == 0);
+#endif
+ }
+
+ BOOST_TEST(X::instances == 0);
+
+ {
+ std::auto_ptr<X> p(new X);
+ X * q = p.get();
+ boost::shared_ptr<void> pv(p);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == q);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ BOOST_TEST(X::instances == 1);
+
+#if !defined(BOOST_OLD_AUTO_PTR)
+ BOOST_TEST(p.get() == 0);
+#endif
+ }
+
+ BOOST_TEST(X::instances == 0);
+
+ {
+ std::auto_ptr<X> p(new X);
+ X * q = p.get();
+ boost::shared_ptr<void const> pv(p);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == q);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ BOOST_TEST(X::instances == 1);
+
+#if !defined(BOOST_OLD_AUTO_PTR)
+ BOOST_TEST(p.get() == 0);
+#endif
+ }
+
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+
+ {
+ std::auto_ptr<Y> p(new Y);
+ Y * q = p.get();
+ boost::shared_ptr<X> px(p);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(px.get() == q);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(X::instances == 1);
+ BOOST_TEST(Y::instances == 1);
+
+#if !defined(BOOST_OLD_AUTO_PTR)
+ BOOST_TEST(p.get() == 0);
+#endif
+ }
+
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+
+ {
+ std::auto_ptr<Y> p(new Y);
+ Y * q = p.get();
+ boost::shared_ptr<X const> px(p);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(px.get() == q);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(X::instances == 1);
+ BOOST_TEST(Y::instances == 1);
+
+#if !defined(BOOST_OLD_AUTO_PTR)
+ BOOST_TEST(p.get() == 0);
+#endif
+ }
+
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+
+#endif // #if !defined( BOOST_NO_AUTO_PTR )
+}
+
+void test()
+{
+ default_constructor();
+ pointer_constructor();
+ deleter_constructor();
+ copy_constructor();
+ weak_ptr_constructor();
+ auto_ptr_constructor();
+}
+
+} // namespace n_constructors
+
+namespace n_assignment
+{
+
+class incomplete;
+
+struct A
+{
+ int dummy;
+};
+
+struct X
+{
+ static long instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X(X const &);
+ X & operator= (X const &);
+};
+
+long X::instances = 0;
+
+struct Y: public A, public virtual X
+{
+ static long instances;
+
+ Y()
+ {
+ ++instances;
+ }
+
+ ~Y()
+ {
+ --instances;
+ }
+
+private:
+
+ Y(Y const &);
+ Y & operator= (Y const &);
+};
+
+long Y::instances = 0;
+
+void copy_assignment()
+{
+ {
+ boost::shared_ptr<incomplete> p1;
+
+ p1 = p1;
+
+ BOOST_TEST(p1 == p1);
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+
+ boost::shared_ptr<incomplete> p2;
+
+ p1 = p2;
+
+ BOOST_TEST(p1 == p2);
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+
+ boost::shared_ptr<incomplete> p3(p1);
+
+ p1 = p3;
+
+ BOOST_TEST(p1 == p3);
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+ }
+
+ {
+ boost::shared_ptr<void> p1;
+
+ p1 = p1;
+
+ BOOST_TEST(p1 == p1);
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+
+ boost::shared_ptr<void> p2;
+
+ p1 = p2;
+
+ BOOST_TEST(p1 == p2);
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+
+ boost::shared_ptr<void> p3(p1);
+
+ p1 = p3;
+
+ BOOST_TEST(p1 == p3);
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+
+ boost::shared_ptr<void> p4(new int);
+ BOOST_TEST(p4.use_count() == 1);
+
+ p1 = p4;
+
+ BOOST_TEST(p1 == p4);
+ BOOST_TEST(!(p1 < p4 || p4 < p1));
+ BOOST_TEST(p1.use_count() == 2);
+ BOOST_TEST(p4.use_count() == 2);
+
+ p1 = p3;
+
+ BOOST_TEST(p1 == p3);
+ BOOST_TEST(p4.use_count() == 1);
+ }
+
+ {
+ boost::shared_ptr<X> p1;
+
+ p1 = p1;
+
+ BOOST_TEST(p1 == p1);
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+
+ boost::shared_ptr<X> p2;
+
+ p1 = p2;
+
+ BOOST_TEST(p1 == p2);
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+
+ boost::shared_ptr<X> p3(p1);
+
+ p1 = p3;
+
+ BOOST_TEST(p1 == p3);
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+
+ BOOST_TEST(X::instances == 0);
+
+ boost::shared_ptr<X> p4(new X);
+
+ BOOST_TEST(X::instances == 1);
+
+ p1 = p4;
+
+ BOOST_TEST(X::instances == 1);
+
+ BOOST_TEST(p1 == p4);
+ BOOST_TEST(!(p1 < p4 || p4 < p1));
+
+ BOOST_TEST(p1.use_count() == 2);
+
+ p1 = p2;
+
+ BOOST_TEST(p1 == p2);
+ BOOST_TEST(X::instances == 1);
+
+ p4 = p3;
+
+ BOOST_TEST(p4 == p3);
+ BOOST_TEST(X::instances == 0);
+ }
+}
+
+void conversion_assignment()
+{
+ {
+ boost::shared_ptr<void> p1;
+
+ boost::shared_ptr<incomplete> p2;
+
+ p1 = p2;
+
+ BOOST_TEST(p1 == p2);
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+
+ boost::shared_ptr<int> p4(new int);
+ BOOST_TEST(p4.use_count() == 1);
+
+ boost::shared_ptr<void> p5(p4);
+ BOOST_TEST(p4.use_count() == 2);
+
+ p1 = p4;
+
+ BOOST_TEST(p1 == p4);
+ BOOST_TEST(!(p1 < p5 || p5 < p1));
+ BOOST_TEST(p1.use_count() == 3);
+ BOOST_TEST(p4.use_count() == 3);
+
+ p1 = p2;
+
+ BOOST_TEST(p1 == p2);
+ BOOST_TEST(p4.use_count() == 2);
+ }
+
+ {
+ boost::shared_ptr<X> p1;
+
+ boost::shared_ptr<Y> p2;
+
+ p1 = p2;
+
+ BOOST_TEST(p1 == p2);
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+
+ boost::shared_ptr<Y> p4(new Y);
+
+ BOOST_TEST(X::instances == 1);
+ BOOST_TEST(Y::instances == 1);
+ BOOST_TEST(p4.use_count() == 1);
+
+ boost::shared_ptr<X> p5(p4);
+ BOOST_TEST(p4.use_count() == 2);
+
+ p1 = p4;
+
+ BOOST_TEST(X::instances == 1);
+ BOOST_TEST(Y::instances == 1);
+
+ BOOST_TEST(p1 == p4);
+ BOOST_TEST(!(p1 < p5 || p5 < p1));
+
+ BOOST_TEST(p1.use_count() == 3);
+ BOOST_TEST(p4.use_count() == 3);
+
+ p1 = p2;
+
+ BOOST_TEST(p1 == p2);
+ BOOST_TEST(X::instances == 1);
+ BOOST_TEST(Y::instances == 1);
+ BOOST_TEST(p4.use_count() == 2);
+
+ p4 = p2;
+ p5 = p2;
+
+ BOOST_TEST(p4 == p2);
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+ }
+}
+
+void auto_ptr_assignment()
+{
+#if !defined( BOOST_NO_AUTO_PTR )
+
+ {
+ boost::shared_ptr<int> p1;
+
+ std::auto_ptr<int> p2;
+
+ p1 = p2;
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+ BOOST_TEST(p1.use_count() == 1);
+
+ int * p = new int;
+ std::auto_ptr<int> p3(p);
+
+ p1 = p3;
+ BOOST_TEST(p1.get() == p);
+ BOOST_TEST(p1.use_count() == 1);
+
+#if !defined(BOOST_OLD_AUTO_PTR)
+ BOOST_TEST(p3.get() == 0);
+#endif
+
+ p1 = p2;
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+ BOOST_TEST(p1.use_count() == 1);
+ }
+
+ {
+ boost::shared_ptr<void> p1;
+
+ std::auto_ptr<int> p2;
+
+ p1 = p2;
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+ BOOST_TEST(p1.use_count() == 1);
+
+ int * p = new int;
+ std::auto_ptr<int> p3(p);
+
+ p1 = p3;
+ BOOST_TEST(p1.get() == p);
+ BOOST_TEST(p1.use_count() == 1);
+
+#if !defined(BOOST_OLD_AUTO_PTR)
+ BOOST_TEST(p3.get() == 0);
+#endif
+
+ p1 = p2;
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+ BOOST_TEST(p1.use_count() == 1);
+ }
+
+
+ {
+ boost::shared_ptr<X> p1;
+
+ std::auto_ptr<Y> p2;
+
+ p1 = p2;
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+ BOOST_TEST(p1.use_count() == 1);
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+
+ Y * p = new Y;
+ std::auto_ptr<Y> p3(p);
+
+ BOOST_TEST(X::instances == 1);
+ BOOST_TEST(Y::instances == 1);
+
+ p1 = p3;
+ BOOST_TEST(p1.get() == p);
+ BOOST_TEST(p1.use_count() == 1);
+ BOOST_TEST(X::instances == 1);
+ BOOST_TEST(Y::instances == 1);
+
+#if !defined(BOOST_OLD_AUTO_PTR)
+ BOOST_TEST(p3.get() == 0);
+#endif
+
+ p1 = p2;
+ BOOST_TEST(p1? false: true);
+ BOOST_TEST(!p1);
+ BOOST_TEST(p1.get() == 0);
+ BOOST_TEST(p1.use_count() == 1);
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+ }
+
+#endif // #if !defined( BOOST_NO_AUTO_PTR )
+}
+
+void test()
+{
+ copy_assignment();
+ conversion_assignment();
+ auto_ptr_assignment();
+}
+
+} // namespace n_assignment
+
+namespace n_reset
+{
+
+class incomplete;
+
+incomplete * p0 = 0;
+
+void deleter(incomplete *)
+{
+}
+
+struct X
+{
+ static long instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X(X const &);
+ X & operator= (X const &);
+};
+
+long X::instances = 0;
+
+void plain_reset()
+{
+ {
+ boost::shared_ptr<int> pi;
+ pi.reset();
+ BOOST_TEST(pi? false: true);
+ BOOST_TEST(!pi);
+ BOOST_TEST(pi.get() == 0);
+ BOOST_TEST(pi.use_count() == 0);
+ }
+
+ {
+ boost::shared_ptr<int> pi(static_cast<int*>(0));
+ pi.reset();
+ BOOST_TEST(pi? false: true);
+ BOOST_TEST(!pi);
+ BOOST_TEST(pi.get() == 0);
+ BOOST_TEST(pi.use_count() == 0);
+ }
+
+ {
+ boost::shared_ptr<int> pi(new int);
+ pi.reset();
+ BOOST_TEST(pi? false: true);
+ BOOST_TEST(!pi);
+ BOOST_TEST(pi.get() == 0);
+ BOOST_TEST(pi.use_count() == 0);
+ }
+
+ {
+ boost::shared_ptr<incomplete> px;
+ px.reset();
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 0);
+ }
+
+ {
+ boost::shared_ptr<incomplete> px(p0, deleter);
+ px.reset();
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 0);
+ }
+
+ {
+ boost::shared_ptr<X> px;
+ px.reset();
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 0);
+ }
+
+ {
+ BOOST_TEST(X::instances == 0);
+ boost::shared_ptr<X> px(new X);
+ BOOST_TEST(X::instances == 1);
+ px.reset();
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 0);
+ BOOST_TEST(X::instances == 0);
+ }
+
+ {
+ boost::shared_ptr<void> pv;
+ pv.reset();
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 0);
+ }
+
+ {
+ BOOST_TEST(X::instances == 0);
+ boost::shared_ptr<void> pv(new X);
+ BOOST_TEST(X::instances == 1);
+ pv.reset();
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 0);
+ BOOST_TEST(X::instances == 0);
+ }
+}
+
+struct A
+{
+ int dummy;
+};
+
+struct Y: public A, public virtual X
+{
+ static long instances;
+
+ Y()
+ {
+ ++instances;
+ }
+
+ ~Y()
+ {
+ --instances;
+ }
+
+private:
+
+ Y(Y const &);
+ Y & operator= (Y const &);
+};
+
+long Y::instances = 0;
+
+void pointer_reset()
+{
+ {
+ boost::shared_ptr<int> pi;
+
+ pi.reset(static_cast<int*>(0));
+ BOOST_TEST(pi? false: true);
+ BOOST_TEST(!pi);
+ BOOST_TEST(pi.get() == 0);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+
+ int * p = new int;
+ pi.reset(p);
+ BOOST_TEST(pi? true: false);
+ BOOST_TEST(!!pi);
+ BOOST_TEST(pi.get() == p);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+
+ pi.reset(static_cast<int*>(0));
+ BOOST_TEST(pi? false: true);
+ BOOST_TEST(!pi);
+ BOOST_TEST(pi.get() == 0);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+ }
+
+ {
+ boost::shared_ptr<X> px;
+
+ px.reset(static_cast<X*>(0));
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(X::instances == 0);
+
+ X * p = new X;
+ px.reset(p);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(px.get() == p);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(X::instances == 1);
+
+ px.reset(static_cast<X*>(0));
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+
+ Y * q = new Y;
+ px.reset(q);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(px.get() == q);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(X::instances == 1);
+ BOOST_TEST(Y::instances == 1);
+
+ px.reset(static_cast<Y*>(0));
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+ }
+
+ {
+ boost::shared_ptr<void> pv;
+
+ pv.reset(static_cast<X*>(0));
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ BOOST_TEST(X::instances == 0);
+
+ X * p = new X;
+ pv.reset(p);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == p);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ BOOST_TEST(X::instances == 1);
+
+ pv.reset(static_cast<X*>(0));
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+
+ Y * q = new Y;
+ pv.reset(q);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == q);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ BOOST_TEST(X::instances == 1);
+ BOOST_TEST(Y::instances == 1);
+
+ pv.reset(static_cast<Y*>(0));
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+ BOOST_TEST(X::instances == 0);
+ BOOST_TEST(Y::instances == 0);
+ }
+}
+
+void * deleted = 0;
+
+void deleter2(void * p)
+{
+ deleted = p;
+}
+
+void deleter_reset()
+{
+ {
+ boost::shared_ptr<int> pi;
+
+ pi.reset(static_cast<int*>(0), deleter2);
+ BOOST_TEST(pi? false: true);
+ BOOST_TEST(!pi);
+ BOOST_TEST(pi.get() == 0);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+
+ deleted = π
+
+ int m = 0;
+ pi.reset(&m, deleter2);
+ BOOST_TEST(deleted == 0);
+ BOOST_TEST(pi? true: false);
+ BOOST_TEST(!!pi);
+ BOOST_TEST(pi.get() == &m);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+
+ pi.reset(static_cast<int*>(0), deleter2);
+ BOOST_TEST(deleted == &m);
+ BOOST_TEST(pi? false: true);
+ BOOST_TEST(!pi);
+ BOOST_TEST(pi.get() == 0);
+ BOOST_TEST(pi.use_count() == 1);
+ BOOST_TEST(pi.unique());
+
+ pi.reset();
+ BOOST_TEST(deleted == 0);
+ }
+
+ {
+ boost::shared_ptr<X> px;
+
+ px.reset(static_cast<X*>(0), deleter2);
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+
+ deleted = &px;
+
+ X x;
+ px.reset(&x, deleter2);
+ BOOST_TEST(deleted == 0);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(px.get() == &x);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+
+ px.reset(static_cast<X*>(0), deleter2);
+ BOOST_TEST(deleted == &x);
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+
+ Y y;
+ px.reset(&y, deleter2);
+ BOOST_TEST(deleted == 0);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(px.get() == &y);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+
+ px.reset(static_cast<Y*>(0), deleter2);
+ BOOST_TEST(deleted == &y);
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+
+ px.reset();
+ BOOST_TEST(deleted == 0);
+ }
+
+ {
+ boost::shared_ptr<void> pv;
+
+ pv.reset(static_cast<X*>(0), deleter2);
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+
+ deleted = &pv;
+
+ X x;
+ pv.reset(&x, deleter2);
+ BOOST_TEST(deleted == 0);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == &x);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+
+ pv.reset(static_cast<X*>(0), deleter2);
+ BOOST_TEST(deleted == &x);
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+
+ Y y;
+ pv.reset(&y, deleter2);
+ BOOST_TEST(deleted == 0);
+ BOOST_TEST(pv? true: false);
+ BOOST_TEST(!!pv);
+ BOOST_TEST(pv.get() == &y);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+
+ pv.reset(static_cast<Y*>(0), deleter2);
+ BOOST_TEST(deleted == &y);
+ BOOST_TEST(pv? false: true);
+ BOOST_TEST(!pv);
+ BOOST_TEST(pv.get() == 0);
+ BOOST_TEST(pv.use_count() == 1);
+ BOOST_TEST(pv.unique());
+
+ pv.reset();
+ BOOST_TEST(deleted == 0);
+ }
+
+ {
+ boost::shared_ptr<incomplete> px;
+
+ px.reset(p0, deleter2);
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+
+ deleted = &px;
+ px.reset(p0, deleter2);
+ BOOST_TEST(deleted == 0);
+ }
+}
+
+void test()
+{
+ plain_reset();
+ pointer_reset();
+ deleter_reset();
+}
+
+} // namespace n_reset
+
+namespace n_access
+{
+
+struct X
+{
+};
+
+void test()
+{
+ {
+ boost::shared_ptr<X> px;
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+ using boost::get_pointer;
+#endif
+
+ BOOST_TEST(get_pointer(px) == px.get());
+ }
+
+ {
+ boost::shared_ptr<X> px(static_cast<X*>(0));
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+ using boost::get_pointer;
+#endif
+
+ BOOST_TEST(get_pointer(px) == px.get());
+ }
+
+ {
+ boost::shared_ptr<X> px(static_cast<X*>(0), boost::checked_deleter<X>());
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px? false: true);
+ BOOST_TEST(!px);
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+ using boost::get_pointer;
+#endif
+
+ BOOST_TEST(get_pointer(px) == px.get());
+ }
+
+ {
+ X * p = new X;
+ boost::shared_ptr<X> px(p);
+ BOOST_TEST(px.get() == p);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(&*px == px.get());
+ BOOST_TEST(px.operator ->() == px.get());
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+ using boost::get_pointer;
+#endif
+
+ BOOST_TEST(get_pointer(px) == px.get());
+ }
+
+ {
+ X * p = new X;
+ boost::shared_ptr<X> px(p, boost::checked_deleter<X>());
+ BOOST_TEST(px.get() == p);
+ BOOST_TEST(px? true: false);
+ BOOST_TEST(!!px);
+ BOOST_TEST(&*px == px.get());
+ BOOST_TEST(px.operator ->() == px.get());
+
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
+ using boost::get_pointer;
+#endif
+
+ BOOST_TEST(get_pointer(px) == px.get());
+ }
+}
+
+} // namespace n_access
+
+namespace n_use_count
+{
+
+struct X
+{
+};
+
+void test()
+{
+ {
+ boost::shared_ptr<X> px(static_cast<X*>(0));
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+
+ boost::shared_ptr<X> px2(px);
+ BOOST_TEST(px2.use_count() == 2);
+ BOOST_TEST(!px2.unique());
+ BOOST_TEST(px.use_count() == 2);
+ BOOST_TEST(!px.unique());
+ }
+
+ {
+ boost::shared_ptr<X> px(new X);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+
+ boost::shared_ptr<X> px2(px);
+ BOOST_TEST(px2.use_count() == 2);
+ BOOST_TEST(!px2.unique());
+ BOOST_TEST(px.use_count() == 2);
+ BOOST_TEST(!px.unique());
+ }
+
+ {
+ boost::shared_ptr<X> px(new X, boost::checked_deleter<X>());
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px.unique());
+
+ boost::shared_ptr<X> px2(px);
+ BOOST_TEST(px2.use_count() == 2);
+ BOOST_TEST(!px2.unique());
+ BOOST_TEST(px.use_count() == 2);
+ BOOST_TEST(!px.unique());
+ }
+}
+
+} // namespace n_use_count
+
+namespace n_swap
+{
+
+struct X
+{
+};
+
+void test()
+{
+ {
+ boost::shared_ptr<X> px;
+ boost::shared_ptr<X> px2;
+
+ px.swap(px2);
+
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px2.get() == 0);
+
+ using std::swap;
+ swap(px, px2);
+
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px2.get() == 0);
+ }
+
+ {
+ X * p = new X;
+ boost::shared_ptr<X> px;
+ boost::shared_ptr<X> px2(p);
+ boost::shared_ptr<X> px3(px2);
+
+ px.swap(px2);
+
+ BOOST_TEST(px.get() == p);
+ BOOST_TEST(px.use_count() == 2);
+ BOOST_TEST(px2.get() == 0);
+ BOOST_TEST(px3.get() == p);
+ BOOST_TEST(px3.use_count() == 2);
+
+ using std::swap;
+ swap(px, px2);
+
+ BOOST_TEST(px.get() == 0);
+ BOOST_TEST(px2.get() == p);
+ BOOST_TEST(px2.use_count() == 2);
+ BOOST_TEST(px3.get() == p);
+ BOOST_TEST(px3.use_count() == 2);
+ }
+
+ {
+ X * p1 = new X;
+ X * p2 = new X;
+ boost::shared_ptr<X> px(p1);
+ boost::shared_ptr<X> px2(p2);
+ boost::shared_ptr<X> px3(px2);
+
+ px.swap(px2);
+
+ BOOST_TEST(px.get() == p2);
+ BOOST_TEST(px.use_count() == 2);
+ BOOST_TEST(px2.get() == p1);
+ BOOST_TEST(px2.use_count() == 1);
+ BOOST_TEST(px3.get() == p2);
+ BOOST_TEST(px3.use_count() == 2);
+
+ using std::swap;
+ swap(px, px2);
+
+ BOOST_TEST(px.get() == p1);
+ BOOST_TEST(px.use_count() == 1);
+ BOOST_TEST(px2.get() == p2);
+ BOOST_TEST(px2.use_count() == 2);
+ BOOST_TEST(px3.get() == p2);
+ BOOST_TEST(px3.use_count() == 2);
+ }
+}
+
+} // namespace n_swap
+
+namespace n_comparison
+{
+
+struct X
+{
+ int dummy;
+};
+
+struct Y
+{
+ int dummy2;
+};
+
+struct Z: public X, public virtual Y
+{
+};
+
+void test()
+{
+ {
+ boost::shared_ptr<X> px;
+ BOOST_TEST(px == px);
+ BOOST_TEST(!(px != px));
+ BOOST_TEST(!(px < px));
+
+ boost::shared_ptr<X> px2;
+
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(px == px2);
+ BOOST_TEST(!(px != px2));
+ BOOST_TEST(!(px < px2 && px2 < px));
+ }
+
+ {
+ boost::shared_ptr<X> px;
+ boost::shared_ptr<X> px2(px);
+
+ BOOST_TEST(px2 == px2);
+ BOOST_TEST(!(px2 != px2));
+ BOOST_TEST(!(px2 < px2));
+
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(px == px2);
+ BOOST_TEST(!(px != px2));
+ BOOST_TEST(!(px < px2 && px2 < px));
+ }
+
+ {
+ boost::shared_ptr<X> px;
+ boost::shared_ptr<X> px2(new X);
+
+ BOOST_TEST(px2 == px2);
+ BOOST_TEST(!(px2 != px2));
+ BOOST_TEST(!(px2 < px2));
+
+ BOOST_TEST(px.get() != px2.get());
+ BOOST_TEST(px != px2);
+ BOOST_TEST(!(px == px2));
+ BOOST_TEST(px < px2 || px2 < px);
+ BOOST_TEST(!(px < px2 && px2 < px));
+ }
+
+ {
+ boost::shared_ptr<X> px(new X);
+ boost::shared_ptr<X> px2(new X);
+
+ BOOST_TEST(px.get() != px2.get());
+ BOOST_TEST(px != px2);
+ BOOST_TEST(!(px == px2));
+ BOOST_TEST(px < px2 || px2 < px);
+ BOOST_TEST(!(px < px2 && px2 < px));
+ }
+
+ {
+ boost::shared_ptr<X> px(new X);
+ boost::shared_ptr<X> px2(px);
+
+ BOOST_TEST(px2 == px2);
+ BOOST_TEST(!(px2 != px2));
+ BOOST_TEST(!(px2 < px2));
+
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(px == px2);
+ BOOST_TEST(!(px != px2));
+ BOOST_TEST(!(px < px2 || px2 < px));
+ }
+
+ {
+ boost::shared_ptr<X> px(new X);
+ boost::shared_ptr<Y> py(new Y);
+ boost::shared_ptr<Z> pz(new Z);
+
+ BOOST_TEST(px.get() != pz.get());
+ BOOST_TEST(px != pz);
+ BOOST_TEST(!(px == pz));
+
+ BOOST_TEST(py.get() != pz.get());
+ BOOST_TEST(py != pz);
+ BOOST_TEST(!(py == pz));
+
+ BOOST_TEST(px < py || py < px);
+ BOOST_TEST(px < pz || pz < px);
+ BOOST_TEST(py < pz || pz < py);
+
+ BOOST_TEST(!(px < py && py < px));
+ BOOST_TEST(!(px < pz && pz < px));
+ BOOST_TEST(!(py < pz && pz < py));
+
+ boost::shared_ptr<void> pvx(px);
+
+ BOOST_TEST(pvx == pvx);
+ BOOST_TEST(!(pvx != pvx));
+ BOOST_TEST(!(pvx < pvx));
+
+ boost::shared_ptr<void> pvy(py);
+ boost::shared_ptr<void> pvz(pz);
+
+ BOOST_TEST(pvx < pvy || pvy < pvx);
+ BOOST_TEST(pvx < pvz || pvz < pvx);
+ BOOST_TEST(pvy < pvz || pvz < pvy);
+
+ BOOST_TEST(!(pvx < pvy && pvy < pvx));
+ BOOST_TEST(!(pvx < pvz && pvz < pvx));
+ BOOST_TEST(!(pvy < pvz && pvz < pvy));
+ }
+
+ {
+ boost::shared_ptr<Z> pz(new Z);
+ boost::shared_ptr<X> px(pz);
+
+ BOOST_TEST(px == px);
+ BOOST_TEST(!(px != px));
+ BOOST_TEST(!(px < px));
+
+ boost::shared_ptr<Y> py(pz);
+
+ BOOST_TEST(px.get() == pz.get());
+ BOOST_TEST(px == pz);
+ BOOST_TEST(!(px != pz));
+
+ BOOST_TEST(py.get() == pz.get());
+ BOOST_TEST(py == pz);
+ BOOST_TEST(!(py != pz));
+
+ BOOST_TEST(!(px < py || py < px));
+ BOOST_TEST(!(px < pz || pz < px));
+ BOOST_TEST(!(py < pz || pz < py));
+
+ boost::shared_ptr<void> pvx(px);
+ boost::shared_ptr<void> pvy(py);
+ boost::shared_ptr<void> pvz(pz);
+
+ // pvx and pvy aren't equal...
+ BOOST_TEST(pvx.get() != pvy.get());
+ BOOST_TEST(pvx != pvy);
+ BOOST_TEST(!(pvx == pvy));
+
+ // ... but they share ownership ...
+ BOOST_TEST(!(pvx < pvy || pvy < pvx));
+
+ // ... with pvz
+ BOOST_TEST(!(pvx < pvz || pvz < pvx));
+ BOOST_TEST(!(pvy < pvz || pvz < pvy));
+ }
+}
+
+} // namespace n_comparison
+
+namespace n_static_cast
+{
+
+struct X
+{
+};
+
+struct Y: public X
+{
+};
+
+void test()
+{
+ {
+ boost::shared_ptr<void> pv;
+
+ boost::shared_ptr<int> pi = boost::static_pointer_cast<int>(pv);
+ BOOST_TEST(pi.get() == 0);
+
+ boost::shared_ptr<X> px = boost::static_pointer_cast<X>(pv);
+ BOOST_TEST(px.get() == 0);
+ }
+
+ {
+ boost::shared_ptr<int> pi(new int);
+ boost::shared_ptr<void> pv(pi);
+
+ boost::shared_ptr<int> pi2 = boost::static_pointer_cast<int>(pv);
+ BOOST_TEST(pi.get() == pi2.get());
+ BOOST_TEST(!(pi < pi2 || pi2 < pi));
+ BOOST_TEST(pi.use_count() == 3);
+ BOOST_TEST(pv.use_count() == 3);
+ BOOST_TEST(pi2.use_count() == 3);
+ }
+
+ {
+ boost::shared_ptr<X> px(new X);
+ boost::shared_ptr<void> pv(px);
+
+ boost::shared_ptr<X> px2 = boost::static_pointer_cast<X>(pv);
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+ BOOST_TEST(px.use_count() == 3);
+ BOOST_TEST(pv.use_count() == 3);
+ BOOST_TEST(px2.use_count() == 3);
+ }
+
+ {
+ boost::shared_ptr<X> px(new Y);
+
+ boost::shared_ptr<Y> py = boost::static_pointer_cast<Y>(px);
+ BOOST_TEST(px.get() == py.get());
+ BOOST_TEST(px.use_count() == 2);
+ BOOST_TEST(py.use_count() == 2);
+
+ boost::shared_ptr<X> px2(py);
+ BOOST_TEST(!(px < px2 || px2 < px));
+ }
+}
+
+} // namespace n_static_cast
+
+namespace n_const_cast
+{
+
+struct X;
+
+void test()
+{
+ {
+ boost::shared_ptr<void const volatile> px;
+
+ boost::shared_ptr<void> px2 = boost::const_pointer_cast<void>(px);
+ BOOST_TEST(px2.get() == 0);
+ }
+
+ {
+ boost::shared_ptr<int const volatile> px;
+
+ boost::shared_ptr<int> px2 = boost::const_pointer_cast<int>(px);
+ BOOST_TEST(px2.get() == 0);
+ }
+
+ {
+ boost::shared_ptr<X const volatile> px;
+
+ boost::shared_ptr<X> px2 = boost::const_pointer_cast<X>(px);
+ BOOST_TEST(px2.get() == 0);
+ }
+
+ {
+ boost::shared_ptr<void const volatile> px(new int);
+
+ boost::shared_ptr<void> px2 = boost::const_pointer_cast<void>(px);
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+ BOOST_TEST(px.use_count() == 2);
+ BOOST_TEST(px2.use_count() == 2);
+ }
+
+ {
+ boost::shared_ptr<int const volatile> px(new int);
+
+ boost::shared_ptr<int> px2 = boost::const_pointer_cast<int>(px);
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+ BOOST_TEST(px.use_count() == 2);
+ BOOST_TEST(px2.use_count() == 2);
+ }
+}
+
+} // namespace n_const_cast
+
+#if !defined( BOOST_NO_RTTI )
+
+namespace n_dynamic_cast
+{
+
+struct V
+{
+ virtual ~V() {}
+};
+
+struct W: public V
+{
+};
+
+void test()
+{
+ {
+ boost::shared_ptr<V> pv;
+ boost::shared_ptr<W> pw = boost::dynamic_pointer_cast<W>(pv);
+ BOOST_TEST(pw.get() == 0);
+ }
+
+ {
+ boost::shared_ptr<V> pv(static_cast<V*>(0));
+
+ boost::shared_ptr<W> pw = boost::dynamic_pointer_cast<W>(pv);
+ BOOST_TEST(pw.get() == 0);
+
+ boost::shared_ptr<V> pv2(pw);
+ BOOST_TEST(pv < pv2 || pv2 < pv);
+ }
+
+ {
+ boost::shared_ptr<V> pv(static_cast<W*>(0));
+
+ boost::shared_ptr<W> pw = boost::dynamic_pointer_cast<W>(pv);
+ BOOST_TEST(pw.get() == 0);
+
+ boost::shared_ptr<V> pv2(pw);
+ BOOST_TEST(pv < pv2 || pv2 < pv);
+ }
+
+ {
+ boost::shared_ptr<V> pv(new V);
+
+ boost::shared_ptr<W> pw = boost::dynamic_pointer_cast<W>(pv);
+ BOOST_TEST(pw.get() == 0);
+
+ boost::shared_ptr<V> pv2(pw);
+ BOOST_TEST(pv < pv2 || pv2 < pv);
+ }
+
+ {
+ boost::shared_ptr<V> pv(new W);
+
+ boost::shared_ptr<W> pw = boost::dynamic_pointer_cast<W>(pv);
+ BOOST_TEST(pw.get() == pv.get());
+ BOOST_TEST(pv.use_count() == 2);
+ BOOST_TEST(pw.use_count() == 2);
+
+ boost::shared_ptr<V> pv2(pw);
+ BOOST_TEST(!(pv < pv2 || pv2 < pv));
+ }
+}
+
+} // namespace n_dynamic_cast
+
+#endif
+
+namespace n_map
+{
+
+struct X
+{
+};
+
+void test()
+{
+ std::vector< boost::shared_ptr<int> > vi;
+
+ {
+ boost::shared_ptr<int> pi1(new int);
+ boost::shared_ptr<int> pi2(new int);
+ boost::shared_ptr<int> pi3(new int);
+
+ vi.push_back(pi1);
+ vi.push_back(pi1);
+ vi.push_back(pi1);
+ vi.push_back(pi2);
+ vi.push_back(pi1);
+ vi.push_back(pi2);
+ vi.push_back(pi1);
+ vi.push_back(pi3);
+ vi.push_back(pi3);
+ vi.push_back(pi2);
+ vi.push_back(pi1);
+ }
+
+ std::vector< boost::shared_ptr<X> > vx;
+
+ {
+ boost::shared_ptr<X> px1(new X);
+ boost::shared_ptr<X> px2(new X);
+ boost::shared_ptr<X> px3(new X);
+
+ vx.push_back(px2);
+ vx.push_back(px2);
+ vx.push_back(px1);
+ vx.push_back(px2);
+ vx.push_back(px1);
+ vx.push_back(px1);
+ vx.push_back(px1);
+ vx.push_back(px2);
+ vx.push_back(px1);
+ vx.push_back(px3);
+ vx.push_back(px2);
+ }
+
+ std::map< boost::shared_ptr<void>, long > m;
+
+ {
+ for(std::vector< boost::shared_ptr<int> >::iterator i = vi.begin(); i != vi.end(); ++i)
+ {
+ ++m[*i];
+ }
+ }
+
+ {
+ for(std::vector< boost::shared_ptr<X> >::iterator i = vx.begin(); i != vx.end(); ++i)
+ {
+ ++m[*i];
+ }
+ }
+
+ {
+ for(std::map< boost::shared_ptr<void>, long >::iterator i = m.begin(); i != m.end(); ++i)
+ {
+ BOOST_TEST(i->first.use_count() == i->second + 1);
+ }
+ }
+}
+
+} // namespace n_map
+
+namespace n_transitive
+{
+
+struct X
+{
+ X(): next() {}
+ boost::shared_ptr<X> next;
+};
+
+void test()
+{
+ boost::shared_ptr<X> p(new X);
+ p->next = boost::shared_ptr<X>(new X);
+ BOOST_TEST(!p->next->next);
+ p = p->next;
+ BOOST_TEST(!p->next);
+}
+
+} // namespace n_transitive
+
+namespace n_report_1
+{
+
+class foo
+{
+public:
+
+ foo(): m_self(this)
+ {
+ }
+
+ void suicide()
+ {
+ m_self.reset();
+ }
+
+private:
+
+ boost::shared_ptr<foo> m_self;
+};
+
+void test()
+{
+ foo * foo_ptr = new foo;
+ foo_ptr->suicide();
+}
+
+} // namespace n_report_1
+
+// Test case by Per Kristensen
+namespace n_report_2
+{
+
+class foo
+{
+public:
+
+ void setWeak(boost::shared_ptr<foo> s)
+ {
+ w = s;
+ }
+
+private:
+
+ boost::weak_ptr<foo> w;
+};
+
+class deleter
+{
+public:
+
+ deleter(): lock(0)
+ {
+ }
+
+ ~deleter()
+ {
+ BOOST_TEST(lock == 0);
+ }
+
+ void operator() (foo * p)
+ {
+ ++lock;
+ delete p;
+ --lock;
+ }
+
+private:
+
+ int lock;
+};
+
+void test()
+{
+ boost::shared_ptr<foo> s(new foo, deleter());
+ s->setWeak(s);
+ s.reset();
+}
+
+} // namespace n_report_2
+
+namespace n_spt_incomplete
+{
+
+class file;
+
+boost::shared_ptr<file> fopen(char const * name, char const * mode);
+void fread(boost::shared_ptr<file> f, void * data, long size);
+
+int file_instances = 0;
+
+void test()
+{
+ BOOST_TEST(file_instances == 0);
+
+ {
+ boost::shared_ptr<file> pf = fopen("name", "mode");
+ BOOST_TEST(file_instances == 1);
+ fread(pf, 0, 17041);
+ }
+
+ BOOST_TEST(file_instances == 0);
+}
+
+} // namespace n_spt_incomplete
+
+namespace n_spt_pimpl
+{
+
+class file
+{
+private:
+
+ class impl;
+ boost::shared_ptr<impl> pimpl_;
+
+public:
+
+ file(char const * name, char const * mode);
+
+ // compiler generated members are fine and useful
+
+ void read(void * data, long size);
+
+ long total_size() const;
+};
+
+int file_instances = 0;
+
+void test()
+{
+ BOOST_TEST(file_instances == 0);
+
+ {
+ file f("name", "mode");
+ BOOST_TEST(file_instances == 1);
+ f.read(0, 152);
+
+ file f2(f);
+ BOOST_TEST(file_instances == 1);
+ f2.read(0, 894);
+
+ BOOST_TEST(f.total_size() == 152+894);
+
+ {
+ file f3("name2", "mode2");
+ BOOST_TEST(file_instances == 2);
+ }
+
+ BOOST_TEST(file_instances == 1);
+ }
+
+ BOOST_TEST(file_instances == 0);
+}
+
+} // namespace n_spt_pimpl
+
+namespace n_spt_abstract
+{
+
+class X
+{
+public:
+
+ virtual void f(int) = 0;
+ virtual int g() = 0;
+
+protected:
+
+ ~X() {}
+};
+
+boost::shared_ptr<X> createX();
+
+int X_instances = 0;
+
+void test()
+{
+ BOOST_TEST(X_instances == 0);
+
+ {
+ boost::shared_ptr<X> px = createX();
+
+ BOOST_TEST(X_instances == 1);
+
+ px->f(18);
+ px->f(152);
+
+ BOOST_TEST(px->g() == 170);
+ }
+
+ BOOST_TEST(X_instances == 0);
+}
+
+} // namespace n_spt_abstract
+
+namespace n_spt_preventing_delete
+{
+
+int X_instances = 0;
+
+class X
+{
+private:
+
+ X()
+ {
+ ++X_instances;
+ }
+
+ ~X()
+ {
+ --X_instances;
+ }
+
+ class deleter;
+ friend class deleter;
+
+ class deleter
+ {
+ public:
+
+ void operator()(X * p) { delete p; }
+ };
+
+public:
+
+ static boost::shared_ptr<X> create()
+ {
+ boost::shared_ptr<X> px(new X, X::deleter());
+ return px;
+ }
+};
+
+void test()
+{
+ BOOST_TEST(X_instances == 0);
+
+ {
+ boost::shared_ptr<X> px = X::create();
+ BOOST_TEST(X_instances == 1);
+ }
+
+ BOOST_TEST(X_instances == 0);
+}
+
+} // namespace n_spt_preventing_delete
+
+namespace n_spt_array
+{
+
+int X_instances = 0;
+
+struct X
+{
+ X()
+ {
+ ++X_instances;
+ }
+
+ ~X()
+ {
+ --X_instances;
+ }
+};
+
+void test()
+{
+ BOOST_TEST(X_instances == 0);
+
+ {
+ boost::shared_ptr<X> px(new X[4], boost::checked_array_deleter<X>());
+ BOOST_TEST(X_instances == 4);
+ }
+
+ BOOST_TEST(X_instances == 0);
+}
+
+} // namespace n_spt_array
+
+namespace n_spt_static
+{
+
+class X
+{
+public:
+
+ X()
+ {
+ }
+
+private:
+
+ void operator delete(void *)
+ {
+ // Comeau 4.3.0.1 wants a definition
+ BOOST_ERROR("n_spt_static::X::operator delete() called.");
+ }
+};
+
+struct null_deleter
+{
+ void operator()(void const *) const
+ {
+ }
+};
+
+static X x;
+
+void test()
+{
+ boost::shared_ptr<X> px(&x, null_deleter());
+}
+
+} // namespace n_spt_static
+
+namespace n_spt_intrusive
+{
+
+int X_instances = 0;
+
+struct X
+{
+ long count;
+
+ X(): count(0)
+ {
+ ++X_instances;
+ }
+
+ ~X()
+ {
+ --X_instances;
+ }
+};
+
+void intrusive_ptr_add_ref(X * p)
+{
+ ++p->count;
+}
+
+void intrusive_ptr_release(X * p)
+{
+ if(--p->count == 0) delete p;
+}
+
+template<class T> struct intrusive_deleter
+{
+ void operator()(T * p)
+ {
+ if(p != 0) intrusive_ptr_release(p);
+ }
+};
+
+boost::shared_ptr<X> make_shared_from_intrusive(X * p)
+{
+ if(p != 0) intrusive_ptr_add_ref(p);
+ boost::shared_ptr<X> px(p, intrusive_deleter<X>());
+ return px;
+}
+
+void test()
+{
+ BOOST_TEST(X_instances == 0);
+
+ {
+ X * p = new X;
+ BOOST_TEST(X_instances == 1);
+ BOOST_TEST(p->count == 0);
+ boost::shared_ptr<X> px = make_shared_from_intrusive(p);
+ BOOST_TEST(px.get() == p);
+ BOOST_TEST(p->count == 1);
+ boost::shared_ptr<X> px2(px);
+ BOOST_TEST(px2.get() == p);
+ BOOST_TEST(p->count == 1);
+ }
+
+ BOOST_TEST(X_instances == 0);
+}
+
+} // namespace n_spt_intrusive
+
+namespace n_spt_another_sp
+{
+
+template<class T> class another_ptr: private boost::shared_ptr<T>
+{
+private:
+
+ typedef boost::shared_ptr<T> base_type;
+
+public:
+
+ explicit another_ptr(T * p = 0): base_type(p)
+ {
+ }
+
+ void reset()
+ {
+ base_type::reset();
+ }
+
+ T * get() const
+ {
+ return base_type::get();
+ }
+};
+
+class event_handler
+{
+public:
+
+ virtual ~event_handler() {}
+ virtual void begin() = 0;
+ virtual void handle(int event) = 0;
+ virtual void end() = 0;
+};
+
+int begin_called = 0;
+int handle_called = 0;
+int end_called = 0;
+
+class event_handler_impl: public event_handler
+{
+public:
+
+ virtual void begin()
+ {
+ ++begin_called;
+ }
+
+ virtual void handle(int event)
+ {
+ handle_called = event;
+ }
+
+ virtual void end()
+ {
+ ++end_called;
+ }
+};
+
+another_ptr<event_handler> get_event_handler()
+{
+ another_ptr<event_handler> p(new event_handler_impl);
+ return p;
+}
+
+boost::shared_ptr<event_handler> current_handler;
+
+void install_event_handler(boost::shared_ptr<event_handler> p)
+{
+ p->begin();
+ current_handler = p;
+}
+
+void handle_event(int event)
+{
+ current_handler->handle(event);
+}
+
+void remove_event_handler()
+{
+ current_handler->end();
+ current_handler.reset();
+}
+
+template<class P> class smart_pointer_deleter
+{
+private:
+
+ P p_;
+
+public:
+
+ smart_pointer_deleter(P const & p): p_(p)
+ {
+ }
+
+ void operator()(void const *)
+ {
+ p_.reset();
+ }
+};
+
+void test()
+{
+ another_ptr<event_handler> p = get_event_handler();
+
+ boost::shared_ptr<event_handler> q(p.get(), smart_pointer_deleter< another_ptr<event_handler> >(p));
+
+ p.reset();
+
+ BOOST_TEST(begin_called == 0);
+
+ install_event_handler(q);
+
+ BOOST_TEST(begin_called == 1);
+
+ BOOST_TEST(handle_called == 0);
+
+ handle_event(17041);
+
+ BOOST_TEST(handle_called == 17041);
+
+ BOOST_TEST(end_called == 0);
+
+ remove_event_handler();
+
+ BOOST_TEST(end_called == 1);
+}
+
+} // namespace n_spt_another_sp
+
+namespace n_spt_shared_from_this
+{
+
+class X
+{
+public:
+
+ virtual void f() = 0;
+
+protected:
+
+ ~X() {}
+};
+
+class Y
+{
+public:
+
+ virtual boost::shared_ptr<X> getX() = 0;
+
+protected:
+
+ ~Y() {}
+};
+
+class impl: public X, public Y
+{
+private:
+
+ boost::weak_ptr<impl> weak_this;
+
+ impl(impl const &);
+ impl & operator=(impl const &);
+
+ impl() {}
+
+public:
+
+ static boost::shared_ptr<impl> create()
+ {
+ boost::shared_ptr<impl> pi(new impl);
+ pi->weak_this = pi;
+ return pi;
+ }
+
+ virtual void f() {}
+
+ virtual boost::shared_ptr<X> getX()
+ {
+ boost::shared_ptr<X> px = weak_this.lock();
+ return px;
+ }
+};
+
+void test()
+{
+ boost::shared_ptr<Y> py = impl::create();
+ BOOST_TEST(py.get() != 0);
+ BOOST_TEST(py.use_count() == 1);
+
+ boost::shared_ptr<X> px = py->getX();
+ BOOST_TEST(px.get() != 0);
+ BOOST_TEST(py.use_count() == 2);
+
+#if !defined( BOOST_NO_RTTI )
+ boost::shared_ptr<Y> py2 = boost::dynamic_pointer_cast<Y>(px);
+ BOOST_TEST(py.get() == py2.get());
+ BOOST_TEST(!(py < py2 || py2 < py));
+ BOOST_TEST(py.use_count() == 3);
+#endif
+}
+
+} // namespace n_spt_shared_from_this
+
+namespace n_spt_wrap
+{
+
+void test()
+{
+}
+
+} // namespace n_spt_wrap
+
+int main()
+{
+ n_element_type::test();
+ n_constructors::test();
+ n_assignment::test();
+ n_reset::test();
+ n_access::test();
+ n_use_count::test();
+ n_swap::test();
+ n_comparison::test();
+ n_static_cast::test();
+ n_const_cast::test();
+#if !defined( BOOST_NO_RTTI )
+ n_dynamic_cast::test();
+#endif
+
+ n_map::test();
+
+ n_transitive::test();
+ n_report_1::test();
+ n_report_2::test();
+
+ n_spt_incomplete::test();
+ n_spt_pimpl::test();
+ n_spt_abstract::test();
+ n_spt_preventing_delete::test();
+ n_spt_array::test();
+ n_spt_static::test();
+ n_spt_intrusive::test();
+ n_spt_another_sp::test();
+ n_spt_shared_from_this::test();
+ n_spt_wrap::test();
+
+ return boost::report_errors();
+}
+
+namespace n_spt_incomplete
+{
+
+class file
+{
+public:
+
+ file(): fread_called(false)
+ {
+ ++file_instances;
+ }
+
+ ~file()
+ {
+ BOOST_TEST(fread_called);
+ --file_instances;
+ }
+
+ bool fread_called;
+};
+
+boost::shared_ptr<file> fopen(char const *, char const *)
+{
+ boost::shared_ptr<file> pf(new file);
+ return pf;
+}
+
+void fread(boost::shared_ptr<file> pf, void *, long)
+{
+ pf->fread_called = true;
+}
+
+} // namespace n_spt_incomplete
+
+namespace n_spt_pimpl
+{
+
+class file::impl
+{
+private:
+
+ impl(impl const &);
+ impl & operator=(impl const &);
+
+ long total_size_;
+
+public:
+
+ impl(char const *, char const *): total_size_(0)
+ {
+ ++file_instances;
+ }
+
+ ~impl()
+ {
+ --file_instances;
+ }
+
+ void read(void *, long size)
+ {
+ total_size_ += size;
+ }
+
+ long total_size() const
+ {
+ return total_size_;
+ }
+};
+
+file::file(char const * name, char const * mode): pimpl_(new impl(name, mode))
+{
+}
+
+void file::read(void * data, long size)
+{
+ pimpl_->read(data, size);
+}
+
+long file::total_size() const
+{
+ return pimpl_->total_size();
+}
+
+} // namespace n_spt_pimpl
+
+namespace n_spt_abstract
+{
+
+class X_impl: public X
+{
+private:
+
+ X_impl(X_impl const &);
+ X_impl & operator=(X_impl const &);
+
+ int n_;
+
+public:
+
+ X_impl(): n_(0)
+ {
+ ++X_instances;
+ }
+
+ ~X_impl()
+ {
+ --X_instances;
+ }
+
+ virtual void f(int n)
+ {
+ n_ += n;
+ }
+
+ virtual int g()
+ {
+ return n_;
+ }
+};
+
+boost::shared_ptr<X> createX()
+{
+ boost::shared_ptr<X> px(new X_impl);
+ return px;
+}
+
+} // namespace n_spt_abstract
diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp
new file mode 100644
index 0000000..12120ed
--- /dev/null
+++ b/test/smart_ptr_test.cpp
@@ -0,0 +1,307 @@
+// smart pointer test program ----------------------------------------------//
+
+// Copyright Beman Dawes 1998, 1999. 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)
+
+// See http://www.boost.org/libs/smart_ptr for documentation.
+
+// Revision History
+// 24 May 01 use Boost test library for error detection, reporting, add tests
+// for operations on incomplete types (Beman Dawes)
+// 29 Nov 99 added std::swap and associative container tests (Darin Adler)
+// 25 Sep 99 added swap tests
+// 20 Jul 99 header name changed to .hpp
+// 20 Apr 99 additional error tests added.
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+
+# pragma warning(disable: 4786) // identifier truncated in debug info
+# pragma warning(disable: 4710) // function not inlined
+# pragma warning(disable: 4711) // function selected for automatic inline expansion
+# pragma warning(disable: 4514) // unreferenced inline removed
+
+#if (BOOST_MSVC >= 1310)
+# pragma warning(disable: 4675) // resolved overload found with Koenig lookup
+#endif
+
+#endif
+
+#ifdef __BORLANDC__
+# pragma warn -8092 // template argument passed to 'find' is not an iterator
+#endif
+
+#include <boost/smart_ptr.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+#include <iostream>
+#include <set>
+#include <string.h>
+
+class Incomplete;
+
+Incomplete * get_ptr( boost::shared_ptr<Incomplete>& incomplete )
+{
+ return incomplete.get();
+}
+
+template<class T>
+void ck( const T* v1, T v2 ) { BOOST_TEST( *v1 == v2 ); }
+
+namespace {
+ int UDT_use_count; // independent of pointer maintained counts
+ }
+
+// user defined type -------------------------------------------------------//
+
+class UDT {
+ long value_;
+ public:
+ explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; }
+ ~UDT() {
+ --UDT_use_count;
+ std::cout << "UDT with value " << value_ << " being destroyed\n";
+ }
+ long value() const { return value_; }
+ void value( long v ) { value_ = v;; }
+ }; // UDT
+
+// tests on incomplete types -----------------------------------------------//
+
+// Certain smart pointer operations are specified to work on incomplete types,
+// and some uses depend upon this feature. These tests verify compilation
+// only - the functions aren't actually invoked.
+
+class Incomplete;
+
+Incomplete * check_incomplete( boost::scoped_ptr<Incomplete>& incomplete )
+{
+ return incomplete.get();
+}
+
+Incomplete * check_incomplete( boost::shared_ptr<Incomplete>& incomplete,
+ boost::shared_ptr<Incomplete>& i2 )
+{
+ incomplete.swap(i2);
+ std::cout << incomplete.use_count() << ' ' << incomplete.unique() << '\n';
+ return incomplete.get();
+}
+
+// This isn't a very systematic test; it just hits some of the basics.
+
+void test()
+{
+ BOOST_TEST( UDT_use_count == 0 ); // reality check
+
+ // test scoped_ptr with a built-in type
+ long * lp = new long;
+ boost::scoped_ptr<long> sp ( lp );
+ BOOST_TEST( sp.get() == lp );
+ BOOST_TEST( lp == sp.get() );
+ BOOST_TEST( &*sp == lp );
+
+ *sp = 1234568901L;
+ BOOST_TEST( *sp == 1234568901L );
+ BOOST_TEST( *lp == 1234568901L );
+ ck( static_cast<long*>(sp.get()), 1234568901L );
+ ck( lp, *sp );
+
+ sp.reset();
+ BOOST_TEST( sp.get() == 0 );
+
+ // test scoped_ptr with a user defined type
+ boost::scoped_ptr<UDT> udt_sp ( new UDT( 999888777 ) );
+ BOOST_TEST( udt_sp->value() == 999888777 );
+ udt_sp.reset();
+ udt_sp.reset( new UDT( 111222333 ) );
+ BOOST_TEST( udt_sp->value() == 111222333 );
+ udt_sp.reset( new UDT( 333222111 ) );
+ BOOST_TEST( udt_sp->value() == 333222111 );
+
+ // test scoped_array with a build-in type
+ char * sap = new char [ 100 ];
+ boost::scoped_array<char> sa ( sap );
+ BOOST_TEST( sa.get() == sap );
+ BOOST_TEST( sap == sa.get() );
+
+ strcpy( sa.get(), "Hot Dog with mustard and relish" );
+ BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 );
+ BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 );
+
+ BOOST_TEST( sa[0] == 'H' );
+ BOOST_TEST( sa[30] == 'h' );
+
+ sa[0] = 'N';
+ sa[4] = 'd';
+ BOOST_TEST( strcmp( sap, "Not dog with mustard and relish" ) == 0 );
+
+ sa.reset();
+ BOOST_TEST( sa.get() == 0 );
+
+ // test shared_ptr with a built-in type
+ int * ip = new int;
+ boost::shared_ptr<int> cp ( ip );
+ BOOST_TEST( ip == cp.get() );
+ BOOST_TEST( cp.use_count() == 1 );
+
+ *cp = 54321;
+ BOOST_TEST( *cp == 54321 );
+ BOOST_TEST( *ip == 54321 );
+ ck( static_cast<int*>(cp.get()), 54321 );
+ ck( static_cast<int*>(ip), *cp );
+
+ boost::shared_ptr<int> cp2 ( cp );
+ BOOST_TEST( ip == cp2.get() );
+ BOOST_TEST( cp.use_count() == 2 );
+ BOOST_TEST( cp2.use_count() == 2 );
+
+ BOOST_TEST( *cp == 54321 );
+ BOOST_TEST( *cp2 == 54321 );
+ ck( static_cast<int*>(cp2.get()), 54321 );
+ ck( static_cast<int*>(ip), *cp2 );
+
+ boost::shared_ptr<int> cp3 ( cp );
+ BOOST_TEST( cp.use_count() == 3 );
+ BOOST_TEST( cp2.use_count() == 3 );
+ BOOST_TEST( cp3.use_count() == 3 );
+ cp.reset();
+ BOOST_TEST( cp2.use_count() == 2 );
+ BOOST_TEST( cp3.use_count() == 2 );
+ cp.reset( new int );
+ *cp = 98765;
+ BOOST_TEST( *cp == 98765 );
+ *cp3 = 87654;
+ BOOST_TEST( *cp3 == 87654 );
+ BOOST_TEST( *cp2 == 87654 );
+ cp.swap( cp3 );
+ BOOST_TEST( *cp == 87654 );
+ BOOST_TEST( *cp2 == 87654 );
+ BOOST_TEST( *cp3 == 98765 );
+ cp.swap( cp3 );
+ BOOST_TEST( *cp == 98765 );
+ BOOST_TEST( *cp2 == 87654 );
+ BOOST_TEST( *cp3 == 87654 );
+ cp2 = cp2;
+ BOOST_TEST( cp2.use_count() == 2 );
+ BOOST_TEST( *cp2 == 87654 );
+ cp = cp2;
+ BOOST_TEST( cp2.use_count() == 3 );
+ BOOST_TEST( *cp2 == 87654 );
+ BOOST_TEST( cp.use_count() == 3 );
+ BOOST_TEST( *cp == 87654 );
+
+#if defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP )
+ using boost::swap;
+#endif
+
+ boost::shared_ptr<int> cp4;
+ swap( cp2, cp4 );
+ BOOST_TEST( cp4.use_count() == 3 );
+ BOOST_TEST( *cp4 == 87654 );
+ BOOST_TEST( cp2.get() == 0 );
+
+ std::set< boost::shared_ptr<int> > scp;
+ scp.insert(cp4);
+ BOOST_TEST( scp.find(cp4) != scp.end() );
+ BOOST_TEST( scp.find(cp4) == scp.find( boost::shared_ptr<int>(cp4) ) );
+
+ // test shared_array with a built-in type
+ char * cap = new char [ 100 ];
+ boost::shared_array<char> ca ( cap );
+ BOOST_TEST( ca.get() == cap );
+ BOOST_TEST( cap == ca.get() );
+ BOOST_TEST( &ca[0] == cap );
+
+ strcpy( ca.get(), "Hot Dog with mustard and relish" );
+ BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 );
+ BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 );
+
+ BOOST_TEST( ca[0] == 'H' );
+ BOOST_TEST( ca[30] == 'h' );
+
+ boost::shared_array<char> ca2 ( ca );
+ boost::shared_array<char> ca3 ( ca2 );
+
+ ca[0] = 'N';
+ ca[4] = 'd';
+ BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 );
+ BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 );
+ BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 );
+ BOOST_TEST( ca.use_count() == 3 );
+ BOOST_TEST( ca2.use_count() == 3 );
+ BOOST_TEST( ca3.use_count() == 3 );
+ ca2.reset();
+ BOOST_TEST( ca.use_count() == 2 );
+ BOOST_TEST( ca3.use_count() == 2 );
+ BOOST_TEST( ca2.use_count() == 0 );
+
+ ca.reset();
+ BOOST_TEST( ca.get() == 0 );
+
+ boost::shared_array<char> ca4;
+ swap( ca3, ca4 );
+ BOOST_TEST( ca4.use_count() == 1 );
+ BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 );
+ BOOST_TEST( ca3.get() == 0 );
+
+ std::set< boost::shared_array<char> > sca;
+ sca.insert(ca4);
+ BOOST_TEST( sca.find(ca4) != sca.end() );
+ BOOST_TEST( sca.find(ca4) == sca.find( boost::shared_array<char>(ca4) ) );
+
+ // test shared_array with user defined type
+ boost::shared_array<UDT> udta ( new UDT[3] );
+
+ udta[0].value( 111 );
+ udta[1].value( 222 );
+ udta[2].value( 333 );
+ boost::shared_array<UDT> udta2 ( udta );
+
+ BOOST_TEST( udta[0].value() == 111 );
+ BOOST_TEST( udta[1].value() == 222 );
+ BOOST_TEST( udta[2].value() == 333 );
+ BOOST_TEST( udta2[0].value() == 111 );
+ BOOST_TEST( udta2[1].value() == 222 );
+ BOOST_TEST( udta2[2].value() == 333 );
+ udta2.reset();
+ BOOST_TEST( udta2.get() == 0 );
+ BOOST_TEST( udta.use_count() == 1 );
+ BOOST_TEST( udta2.use_count() == 0 );
+
+ BOOST_TEST( UDT_use_count == 4 ); // reality check
+
+ // test shared_ptr with a user defined type
+ UDT * up = new UDT;
+ boost::shared_ptr<UDT> sup ( up );
+ BOOST_TEST( up == sup.get() );
+ BOOST_TEST( sup.use_count() == 1 );
+
+ sup->value( 54321 ) ;
+ BOOST_TEST( sup->value() == 54321 );
+ BOOST_TEST( up->value() == 54321 );
+
+ boost::shared_ptr<UDT> sup2;
+ sup2 = sup;
+ BOOST_TEST( sup2->value() == 54321 );
+ BOOST_TEST( sup.use_count() == 2 );
+ BOOST_TEST( sup2.use_count() == 2 );
+ sup2 = sup2;
+ BOOST_TEST( sup2->value() == 54321 );
+ BOOST_TEST( sup.use_count() == 2 );
+ BOOST_TEST( sup2.use_count() == 2 );
+
+ std::cout << "OK\n";
+
+ new char[12345]; // deliberate memory leak to verify leaks detected
+}
+
+int main()
+{
+ test();
+ return boost::report_errors();
+}
diff --git a/test/sp_array_cast_test.cpp b/test/sp_array_cast_test.cpp
new file mode 100644
index 0000000..5af7eb5
--- /dev/null
+++ b/test/sp_array_cast_test.cpp
@@ -0,0 +1,202 @@
+//
+// sp_array_cast_test.cpp
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+struct X
+{
+};
+
+void static_cast_test()
+{
+ {
+ boost::shared_ptr<void> pv;
+
+ boost::shared_ptr<int[]> pi = boost::static_pointer_cast<int[]>( pv );
+ BOOST_TEST( pi.get() == 0 );
+
+ boost::shared_ptr<int[3]> pi2 = boost::static_pointer_cast<int[3]>( pv );
+ BOOST_TEST( pi2.get() == 0 );
+
+ boost::shared_ptr<X[]> px = boost::static_pointer_cast<X[]>( pv );
+ BOOST_TEST( px.get() == 0 );
+
+ boost::shared_ptr<X[5]> px2 = boost::static_pointer_cast<X[5]>( pv );
+ BOOST_TEST( px2.get() == 0 );
+ }
+
+ {
+ boost::shared_ptr<int[]> pi( new int[2] );
+ boost::shared_ptr<void> pv( pi );
+
+ boost::shared_ptr<int[]> pi2 = boost::static_pointer_cast<int[]>( pv );
+ BOOST_TEST(pi.get() == pi2.get());
+ BOOST_TEST(!(pi < pi2 || pi2 < pi));
+
+ boost::shared_ptr<int[2]> pi3 = boost::static_pointer_cast<int[2]>( pv );
+ BOOST_TEST(pi.get() == pi3.get());
+ BOOST_TEST(!(pi < pi3 || pi3 < pi));
+
+ boost::shared_ptr<void> pv2( pi3 );
+
+ boost::shared_ptr<int[]> pi4 = boost::static_pointer_cast<int[]>( pv2 );
+ BOOST_TEST(pi.get() == pi4.get());
+ BOOST_TEST(!(pi < pi4 || pi4 < pi));
+ }
+
+ {
+ boost::shared_ptr<X[]> px( new X[4] );
+ boost::shared_ptr<void> pv( px );
+
+ boost::shared_ptr<X[]> px2 = boost::static_pointer_cast<X[]>( pv );
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+
+ boost::shared_ptr<X[4]> px3 = boost::static_pointer_cast<X[4]>( pv );
+ BOOST_TEST(px.get() == px3.get());
+ BOOST_TEST(!(px < px3 || px3 < px));
+
+ boost::shared_ptr<void> pv2( px3 );
+
+ boost::shared_ptr<X[]> px4 = boost::static_pointer_cast<X[]>( pv2 );
+ BOOST_TEST(px.get() == px4.get());
+ BOOST_TEST(!(px < px4 || px4 < px));
+ }
+}
+
+void const_cast_test()
+{
+ {
+ boost::shared_ptr<int const volatile[]> px;
+
+ boost::shared_ptr<int[]> px2 = boost::const_pointer_cast<int[]>(px);
+ BOOST_TEST( px2.get() == 0 );
+ }
+
+ {
+ boost::shared_ptr<int const volatile[2]> px;
+
+ boost::shared_ptr<int[2]> px2 = boost::const_pointer_cast<int[2]>(px);
+ BOOST_TEST( px2.get() == 0 );
+ }
+
+ {
+ boost::shared_ptr<X const volatile[]> px;
+
+ boost::shared_ptr<X[]> px2 = boost::const_pointer_cast<X[]>(px);
+ BOOST_TEST( px2.get() == 0 );
+ }
+
+ {
+ boost::shared_ptr<X const volatile[5]> px;
+
+ boost::shared_ptr<X[5]> px2 = boost::const_pointer_cast<X[5]>(px);
+ BOOST_TEST( px2.get() == 0 );
+ }
+
+ {
+ boost::shared_ptr<int const volatile[]> px( new int[3] );
+
+ boost::shared_ptr<int[]> px2 = boost::const_pointer_cast<int[]>(px);
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+ }
+
+ {
+ boost::shared_ptr<int const volatile[3]> px( new int[3] );
+
+ boost::shared_ptr<int[3]> px2 = boost::const_pointer_cast<int[3]>(px);
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+ }
+
+ {
+ boost::shared_ptr<X const volatile[]> px( new X[4] );
+
+ boost::shared_ptr<X[]> px2 = boost::const_pointer_cast<X[]>(px);
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+ }
+
+ {
+ boost::shared_ptr<X const volatile[4]> px( new X[4] );
+
+ boost::shared_ptr<X[4]> px2 = boost::const_pointer_cast<X[4]>(px);
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+ }
+}
+
+void reinterpret_cast_test()
+{
+ {
+ boost::shared_ptr<int[]> pi;
+ BOOST_TEST( pi.get() == 0 );
+
+ boost::shared_ptr<int[3]> pi2 = boost::reinterpret_pointer_cast<int[3]>( pi );
+ BOOST_TEST( pi2.get() == 0 );
+
+ boost::shared_ptr<int[6]> pi3 = boost::reinterpret_pointer_cast<int[6]>( pi2 );
+ BOOST_TEST( pi3.get() == 0 );
+ }
+
+ {
+ boost::shared_ptr<X[]> px;
+ BOOST_TEST( px.get() == 0 );
+
+ boost::shared_ptr<X[5]> px2 = boost::reinterpret_pointer_cast<X[5]>( px );
+ BOOST_TEST( px2.get() == 0 );
+
+ boost::shared_ptr<X[9]> px3 = boost::reinterpret_pointer_cast<X[9]>( px2 );
+ BOOST_TEST( px3.get() == 0 );
+ }
+
+ {
+ boost::shared_ptr<int[]> pi( new int[2] );
+
+ boost::shared_ptr<int[2]> pi2 = boost::reinterpret_pointer_cast<int[2]>( pi );
+ BOOST_TEST(pi.get() == pi2.get());
+ BOOST_TEST(!(pi < pi2 || pi2 < pi));
+
+ boost::shared_ptr<int[1]> pi3 = boost::reinterpret_pointer_cast<int[1]>( pi2 );
+ BOOST_TEST(pi.get() == pi3.get());
+ BOOST_TEST(!(pi < pi3 || pi3 < pi));
+
+ boost::shared_ptr<int[]> pi4 = boost::reinterpret_pointer_cast<int[]>( pi3 );
+ BOOST_TEST(pi.get() == pi4.get());
+ BOOST_TEST(!(pi < pi4 || pi4 < pi));
+ }
+
+ {
+ boost::shared_ptr<X[]> px( new X[4] );
+
+ boost::shared_ptr<X[7]> px2 = boost::reinterpret_pointer_cast<X[7]>( px );
+ BOOST_TEST(px.get() == px2.get());
+ BOOST_TEST(!(px < px2 || px2 < px));
+
+ boost::shared_ptr<X[4]> px3 = boost::reinterpret_pointer_cast<X[4]>( px2 );
+ BOOST_TEST(px.get() == px3.get());
+ BOOST_TEST(!(px < px3 || px3 < px));
+
+ boost::shared_ptr<X[]> px4 = boost::reinterpret_pointer_cast<X[]>( px3 );
+ BOOST_TEST(px.get() == px4.get());
+ BOOST_TEST(!(px < px4 || px4 < px));
+ }
+}
+
+int main()
+{
+ static_cast_test();
+ const_cast_test();
+ reinterpret_cast_test();
+
+ return boost::report_errors();
+}
diff --git a/test/sp_array_cv_test.cpp b/test/sp_array_cv_test.cpp
new file mode 100644
index 0000000..8618fb0
--- /dev/null
+++ b/test/sp_array_cv_test.cpp
@@ -0,0 +1,60 @@
+//
+// sp_array_cv_test.cpp
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+struct X
+{
+};
+
+class B
+{
+};
+
+class D: public B
+{
+};
+
+#define TEST_CONV( T, U ) \
+ { \
+ boost::shared_ptr< T > p1; \
+ boost::shared_ptr< U > p2( p1 ); \
+ p2 = p1; \
+ boost::shared_ptr< U > p3 = boost::shared_ptr< T >(); \
+ p3 = boost::shared_ptr< T >(); \
+ }
+
+#define TEST_CV_TRUE( T, U ) \
+ TEST_CONV( T, U ) \
+ TEST_CONV( T, const U ) \
+ TEST_CONV( T, volatile U ) \
+ TEST_CONV( T, const volatile U ) \
+ TEST_CONV( const T, const U ) \
+ TEST_CONV( const T, const volatile U ) \
+ TEST_CONV( volatile T, volatile U ) \
+ TEST_CONV( volatile T, const volatile U ) \
+ TEST_CONV( const volatile T, const volatile U )
+
+int main()
+{
+ TEST_CV_TRUE( X, X )
+ TEST_CV_TRUE( X, void )
+ TEST_CV_TRUE( D, B )
+
+ TEST_CV_TRUE( X[], X[] )
+ TEST_CV_TRUE( X[3], X[3] )
+
+ TEST_CV_TRUE( X[3], X[] )
+
+ TEST_CV_TRUE( X[], void )
+ TEST_CV_TRUE( X[3], void )
+
+ return 0;
+}
diff --git a/test/sp_array_n_test.cpp b/test/sp_array_n_test.cpp
new file mode 100644
index 0000000..ccbcc26
--- /dev/null
+++ b/test/sp_array_n_test.cpp
@@ -0,0 +1,248 @@
+//
+// sp_array_n_test.cpp
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <memory>
+#include <utility>
+
+class X: public boost::enable_shared_from_this< X >
+{
+public:
+
+ static int allocations;
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+ void* operator new[]( std::size_t n )
+ {
+ ++allocations;
+ return ::operator new[]( n );
+ }
+
+ void operator delete[]( void* p )
+ {
+ --allocations;
+ ::operator delete[]( p );
+ }
+
+private:
+
+ X( X const& );
+ X& operator=( X const& );
+};
+
+int X::allocations = 0;
+int X::instances = 0;
+
+template< class T> class array_deleter
+{
+public:
+
+ static int calls;
+
+ void operator()( T * p ) const
+ {
+ ++calls;
+ delete[] p;
+ }
+
+private:
+
+ template< class Y > void operator()( Y * p ) const;
+};
+
+template< class T > int array_deleter< T >::calls = 0;
+
+int main()
+{
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X[3]> px;
+ BOOST_TEST( !px );
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ boost::shared_ptr<X[3]> px2( new X[ 3 ] );
+ BOOST_TEST( px2 );
+
+ try
+ {
+ px2[0].shared_from_this();
+ BOOST_ERROR( "px2[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 3 );
+
+ {
+ X & rx = px2[ 0 ];
+ BOOST_TEST( &rx == px2.get() );
+ }
+
+ boost::shared_ptr<X const[3]> px3( px2 );
+ BOOST_TEST( px3 == px2 );
+ BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) );
+
+ {
+ X const & rx = px3[ 1 ];
+ BOOST_TEST( &rx == px3.get() + 1 );
+ }
+
+ px3.reset();
+ px3 = px2;
+ BOOST_TEST( px3 == px2 );
+ BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) );
+
+ boost::shared_ptr<X volatile[3]> px4( px2 );
+ BOOST_TEST( px4 == px2 );
+ BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) );
+
+ {
+ X volatile & rx = px4[ 2 ];
+ BOOST_TEST( &rx == px4.get() + 2 );
+ }
+
+ px4.reset();
+ px4 = px2;
+ BOOST_TEST( px4 == px2 );
+ BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) );
+
+ boost::shared_ptr<void> px5( px2 );
+ BOOST_TEST( px5 == px2 );
+ BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) );
+
+ px5.reset();
+ px5 = px2;
+ BOOST_TEST( px5 == px2 );
+ BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) );
+
+ boost::weak_ptr<X[3]> wp( px );
+ BOOST_TEST( wp.lock() == px );
+
+ boost::weak_ptr<X[3]> wp2( px2 );
+ BOOST_TEST( wp2.lock() == px2 );
+
+ wp2.reset();
+ wp2 = px2;
+ BOOST_TEST( wp2.lock() == px2 );
+
+ boost::weak_ptr<X const[3]> wp3( px2 );
+ BOOST_TEST( wp3.lock() == px2 );
+
+ wp3.reset();
+ wp3 = px2;
+ BOOST_TEST( wp3.lock() == px2 );
+
+ boost::weak_ptr<X volatile[3]> wp4( px2 );
+ BOOST_TEST( wp4.lock() == px2 );
+
+ wp4.reset();
+ wp4 = px2;
+ BOOST_TEST( wp4.lock() == px2 );
+
+ boost::weak_ptr<void> wp5( px2 );
+ BOOST_TEST( wp5.lock() == px2 );
+
+ wp5.reset();
+ wp5 = px2;
+ BOOST_TEST( wp5.lock() == px2 );
+
+ px2.reset();
+
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 3 );
+
+ px3.reset();
+ px4.reset();
+ px5.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ BOOST_TEST( wp2.lock() == 0 );
+ BOOST_TEST( wp3.lock() == 0 );
+ BOOST_TEST( wp4.lock() == 0 );
+ BOOST_TEST( wp5.lock() == 0 );
+ }
+
+ {
+ boost::shared_ptr<X[5]> px( new X[ 5 ], array_deleter< X >() );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 5 );
+
+ try
+ {
+ px[0].shared_from_this();
+ BOOST_ERROR( "px[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ px.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( array_deleter< X >::calls == 1 );
+ }
+
+ {
+ boost::shared_ptr<X[6]> px( new X[ 6 ], array_deleter< X >(), std::allocator< X >() );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 6 );
+
+ try
+ {
+ px[0].shared_from_this();
+ BOOST_ERROR( "px[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ px.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( array_deleter< X >::calls == 2 );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/sp_array_test.cpp b/test/sp_array_test.cpp
new file mode 100644
index 0000000..d508d53
--- /dev/null
+++ b/test/sp_array_test.cpp
@@ -0,0 +1,311 @@
+//
+// sp_array_test.cpp
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <memory>
+#include <utility>
+
+class X: public boost::enable_shared_from_this< X >
+{
+public:
+
+ static int allocations;
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+ void* operator new[]( std::size_t n )
+ {
+ ++allocations;
+ return ::operator new[]( n );
+ }
+
+ void operator delete[]( void* p )
+ {
+ --allocations;
+ ::operator delete[]( p );
+ }
+
+private:
+
+ X( X const& );
+ X& operator=( X const& );
+};
+
+int X::allocations = 0;
+int X::instances = 0;
+
+template< class T> class array_deleter
+{
+public:
+
+ static int calls;
+
+ void operator()( T * p ) const
+ {
+ ++calls;
+ delete[] p;
+ }
+
+private:
+
+ template< class Y > void operator()( Y * p ) const;
+};
+
+template< class T > int array_deleter< T >::calls = 0;
+
+int main()
+{
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X[]> px;
+ BOOST_TEST( !px );
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ boost::shared_ptr<X[]> px2( new X[ 3 ] );
+ BOOST_TEST( px2 );
+
+ try
+ {
+ px2[0].shared_from_this();
+ BOOST_ERROR( "px2[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 3 );
+
+ {
+ X & rx = px2[ 0 ];
+ BOOST_TEST( &rx == px2.get() );
+ }
+
+ boost::shared_ptr<X const[]> px3( px2 );
+ BOOST_TEST( px3 == px2 );
+ BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) );
+
+ {
+ X const & rx = px3[ 1 ];
+ BOOST_TEST( &rx == px3.get() + 1 );
+ }
+
+ px3.reset();
+ px3 = px2;
+ BOOST_TEST( px3 == px2 );
+ BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) );
+
+ boost::shared_ptr<X volatile[]> px4( px2 );
+ BOOST_TEST( px4 == px2 );
+ BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) );
+
+ {
+ X volatile & rx = px4[ 2 ];
+ BOOST_TEST( &rx == px4.get() + 2 );
+ }
+
+ px4.reset();
+ px4 = px2;
+ BOOST_TEST( px4 == px2 );
+ BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) );
+
+ boost::shared_ptr<void> px5( px2 );
+ BOOST_TEST( px5 == px2 );
+ BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) );
+
+ px5.reset();
+ px5 = px2;
+ BOOST_TEST( px5 == px2 );
+ BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) );
+
+ boost::weak_ptr<X[]> wp( px );
+ BOOST_TEST( wp.lock() == px );
+
+ boost::weak_ptr<X[]> wp2( px2 );
+ BOOST_TEST( wp2.lock() == px2 );
+
+ wp2.reset();
+ wp2 = px2;
+ BOOST_TEST( wp2.lock() == px2 );
+
+ boost::weak_ptr<X const[]> wp3( px2 );
+ BOOST_TEST( wp3.lock() == px2 );
+
+ wp3.reset();
+ wp3 = px2;
+ BOOST_TEST( wp3.lock() == px2 );
+
+ boost::weak_ptr<X volatile[]> wp4( px2 );
+ BOOST_TEST( wp4.lock() == px2 );
+
+ wp4.reset();
+ wp4 = px2;
+ BOOST_TEST( wp4.lock() == px2 );
+
+ boost::weak_ptr<void> wp5( px2 );
+ BOOST_TEST( wp5.lock() == px2 );
+
+ wp5.reset();
+ wp5 = px2;
+ BOOST_TEST( wp5.lock() == px2 );
+
+ px2.reset();
+
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 3 );
+
+ px3.reset();
+ px4.reset();
+ px5.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ BOOST_TEST( wp2.lock() == 0 );
+ BOOST_TEST( wp3.lock() == 0 );
+ BOOST_TEST( wp4.lock() == 0 );
+ BOOST_TEST( wp5.lock() == 0 );
+ }
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ {
+ std::unique_ptr<X[]> px( new X[ 4 ] );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 4 );
+
+ boost::shared_ptr<X[]> px2( std::move( px ) );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 4 );
+ BOOST_TEST( px.get() == 0 );
+
+ try
+ {
+ px2[0].shared_from_this();
+ BOOST_ERROR( "px2[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ px2.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ std::unique_ptr<X[]> px( new X[ 4 ] );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 4 );
+
+ boost::shared_ptr<X[]> px2;
+ px2 = std::move( px );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 4 );
+ BOOST_TEST( px.get() == 0 );
+
+ try
+ {
+ px2[0].shared_from_this();
+ BOOST_ERROR( "px2[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ px2.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+ }
+
+#endif
+
+ {
+ boost::shared_ptr<X[]> px( new X[ 5 ], array_deleter< X >() );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 5 );
+
+ try
+ {
+ px[0].shared_from_this();
+ BOOST_ERROR( "px[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ px.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( array_deleter< X >::calls == 1 );
+ }
+
+ {
+ boost::shared_ptr<X[]> px( new X[ 6 ], array_deleter< X >(), std::allocator< X >() );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 6 );
+
+ try
+ {
+ px[0].shared_from_this();
+ BOOST_ERROR( "px[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ px.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( array_deleter< X >::calls == 2 );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/sp_atomic_test.cpp b/test/sp_atomic_test.cpp
new file mode 100644
index 0000000..3201c49
--- /dev/null
+++ b/test/sp_atomic_test.cpp
@@ -0,0 +1,88 @@
+#include <boost/config.hpp>
+
+// sp_atomic_test.cpp
+//
+// Copyright (c) 2008 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
+
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/memory_order.hpp>
+
+//
+
+struct X
+{
+};
+
+#define BOOST_TEST_SP_EQ( p, q ) BOOST_TEST( p == q && !( p < q ) && !( q < p ) )
+
+int main()
+{
+ boost::shared_ptr<X> px( new X );
+
+ {
+ boost::shared_ptr<X> p2 = boost::atomic_load( &px );
+ BOOST_TEST_SP_EQ( p2, px );
+
+ boost::shared_ptr<X> px2( new X );
+ boost::atomic_store( &px, px2 );
+ BOOST_TEST_SP_EQ( px, px2 );
+
+ p2 = boost::atomic_load( &px );
+ BOOST_TEST_SP_EQ( p2, px );
+ BOOST_TEST_SP_EQ( p2, px2 );
+
+ boost::shared_ptr<X> px3( new X );
+ boost::shared_ptr<X> p3 = boost::atomic_exchange( &px, px3 );
+ BOOST_TEST_SP_EQ( p3, px2 );
+ BOOST_TEST_SP_EQ( px, px3 );
+
+ boost::shared_ptr<X> px4( new X );
+ boost::shared_ptr<X> cmp;
+
+ bool r = boost::atomic_compare_exchange( &px, &cmp, px4 );
+ BOOST_TEST( !r );
+ BOOST_TEST_SP_EQ( px, px3 );
+ BOOST_TEST_SP_EQ( cmp, px3 );
+
+ r = boost::atomic_compare_exchange( &px, &cmp, px4 );
+ BOOST_TEST( r );
+ BOOST_TEST_SP_EQ( px, px4 );
+ }
+
+ //
+
+ px.reset();
+
+ {
+ boost::shared_ptr<X> p2 = boost::atomic_load_explicit( &px, boost::memory_order_acquire );
+ BOOST_TEST_SP_EQ( p2, px );
+
+ boost::shared_ptr<X> px2( new X );
+ boost::atomic_store_explicit( &px, px2, boost::memory_order_release );
+ BOOST_TEST_SP_EQ( px, px2 );
+
+ boost::shared_ptr<X> p3 = boost::atomic_exchange_explicit( &px, boost::shared_ptr<X>(), boost::memory_order_acq_rel );
+ BOOST_TEST_SP_EQ( p3, px2 );
+ BOOST_TEST_SP_EQ( px, p2 );
+
+ boost::shared_ptr<X> px4( new X );
+ boost::shared_ptr<X> cmp( px2 );
+
+ bool r = boost::atomic_compare_exchange_explicit( &px, &cmp, px4, boost::memory_order_acquire, boost::memory_order_relaxed );
+ BOOST_TEST( !r );
+ BOOST_TEST_SP_EQ( px, p2 );
+ BOOST_TEST_SP_EQ( cmp, p2 );
+
+ r = boost::atomic_compare_exchange_explicit( &px, &cmp, px4, boost::memory_order_release, boost::memory_order_acquire );
+ BOOST_TEST( r );
+ BOOST_TEST_SP_EQ( px, px4 );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/sp_bml_unique_ptr_test.cpp b/test/sp_bml_unique_ptr_test.cpp
new file mode 100644
index 0000000..e414552
--- /dev/null
+++ b/test/sp_bml_unique_ptr_test.cpp
@@ -0,0 +1,294 @@
+//
+// sp_bml_unique_ptr_test.cpp
+//
+// Copyright (c) 2012, 2015 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/move/unique_ptr.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <memory>
+#include <utility>
+
+struct X: public boost::enable_shared_from_this< X >
+{
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+};
+
+int X::instances = 0;
+
+struct Y
+{
+ static int instances;
+
+ bool deleted_;
+
+ Y(): deleted_( false )
+ {
+ ++instances;
+ }
+
+ ~Y()
+ {
+ BOOST_TEST( deleted_ );
+ --instances;
+ }
+
+private:
+
+ Y( Y const & );
+ Y & operator=( Y const & );
+};
+
+int Y::instances = 0;
+
+struct YD
+{
+ void operator()( Y* p ) const
+ {
+ if( p )
+ {
+ p->deleted_ = true;
+ delete p;
+ }
+ else
+ {
+ BOOST_ERROR( "YD::operator()(0) called" );
+ }
+ }
+};
+
+template<class U, class T, class D> static void test_null_unique_ptr( boost::movelib::unique_ptr<T, D> p1, boost::movelib::unique_ptr<T, D> p2 )
+{
+ BOOST_TEST( T::instances == 0 );
+
+ boost::shared_ptr<U> sp( boost::move( p1 ) );
+
+ BOOST_TEST( sp.get() == 0 );
+ BOOST_TEST( sp.use_count() == 0 );
+
+ sp.reset( new T, typename boost::remove_reference<D>::type() );
+
+ BOOST_TEST( sp.get() != 0 );
+ BOOST_TEST( sp.use_count() == 1 );
+
+ BOOST_TEST( T::instances == 1 );
+
+ sp = boost::move( p2 );
+
+ BOOST_TEST( sp.get() == 0 );
+ BOOST_TEST( sp.use_count() == 0 );
+
+ BOOST_TEST( T::instances == 0 );
+}
+
+int main()
+{
+ {
+ BOOST_TEST( X::instances == 0 );
+
+ boost::movelib::unique_ptr<X> p( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ boost::shared_ptr<X> p2( boost::move( p ) );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ boost::shared_ptr<X> p3 = p2->shared_from_this();
+ BOOST_TEST( p2 == p3 );
+ BOOST_TEST( !(p2 < p3) && !(p3 < p2) );
+
+ p2.reset();
+ p3.reset();
+ BOOST_TEST( X::instances == 0 );
+
+ p2 = boost::movelib::unique_ptr<X>( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ p2 = boost::movelib::unique_ptr<X>( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ p3 = p2->shared_from_this();
+ BOOST_TEST( p2 == p3 );
+ BOOST_TEST( !(p2 < p3) && !(p3 < p2) );
+
+ p2.reset();
+ p3.reset();
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ BOOST_TEST( X::instances == 0 );
+
+ boost::movelib::unique_ptr<X> p( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ boost::shared_ptr<X const> p2( boost::move( p ) );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ boost::shared_ptr<X const> p3 = p2->shared_from_this();
+ BOOST_TEST( p2 == p3 );
+ BOOST_TEST( !(p2 < p3) && !(p3 < p2) );
+
+ p2.reset();
+ p3.reset();
+ BOOST_TEST( X::instances == 0 );
+
+ p2 = boost::movelib::unique_ptr<X>( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ p2 = boost::movelib::unique_ptr<X>( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ p3 = p2->shared_from_this();
+ BOOST_TEST( p2 == p3 );
+ BOOST_TEST( !(p2 < p3) && !(p3 < p2) );
+
+ p2.reset();
+ p3.reset();
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ BOOST_TEST( X::instances == 0 );
+
+ boost::movelib::unique_ptr<X> p( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ boost::shared_ptr<void> p2( boost::move( p ) );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ p2.reset();
+ BOOST_TEST( X::instances == 0 );
+
+ p2 = boost::movelib::unique_ptr<X>( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ p2 = boost::movelib::unique_ptr<X>( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ p2.reset();
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ BOOST_TEST( Y::instances == 0 );
+
+ boost::movelib::unique_ptr<Y, YD> p( new Y, YD() );
+ BOOST_TEST( Y::instances == 1 );
+
+ boost::shared_ptr<Y> p2( boost::move( p ) );
+ BOOST_TEST( Y::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ p2.reset();
+ BOOST_TEST( Y::instances == 0 );
+
+ p2 = boost::movelib::unique_ptr<Y, YD>( new Y, YD() );
+ BOOST_TEST( Y::instances == 1 );
+
+ p2 = boost::movelib::unique_ptr<Y, YD>( new Y, YD() );
+ BOOST_TEST( Y::instances == 1 );
+
+ p2.reset();
+ BOOST_TEST( Y::instances == 0 );
+ }
+
+ {
+ BOOST_TEST( Y::instances == 0 );
+
+ YD yd;
+
+ boost::movelib::unique_ptr<Y, YD&> p( new Y, yd );
+ BOOST_TEST( Y::instances == 1 );
+
+ boost::shared_ptr<Y> p2( boost::move( p ) );
+ BOOST_TEST( Y::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ p2.reset();
+ BOOST_TEST( Y::instances == 0 );
+
+ p2 = boost::movelib::unique_ptr<Y, YD&>( new Y, yd );
+ BOOST_TEST( Y::instances == 1 );
+
+ p2 = boost::movelib::unique_ptr<Y, YD&>( new Y, yd );
+ BOOST_TEST( Y::instances == 1 );
+
+ p2.reset();
+ BOOST_TEST( Y::instances == 0 );
+ }
+
+ {
+ BOOST_TEST( Y::instances == 0 );
+
+ YD yd;
+
+ boost::movelib::unique_ptr<Y, YD const&> p( new Y, yd );
+ BOOST_TEST( Y::instances == 1 );
+
+ boost::shared_ptr<Y> p2( boost::move( p ) );
+ BOOST_TEST( Y::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ p2.reset();
+ BOOST_TEST( Y::instances == 0 );
+
+ p2 = boost::movelib::unique_ptr<Y, YD const&>( new Y, yd );
+ BOOST_TEST( Y::instances == 1 );
+
+ p2 = boost::movelib::unique_ptr<Y, YD const&>( new Y, yd );
+ BOOST_TEST( Y::instances == 1 );
+
+ p2.reset();
+ BOOST_TEST( Y::instances == 0 );
+ }
+
+ {
+ test_null_unique_ptr<X>( boost::movelib::unique_ptr<X>(), boost::movelib::unique_ptr<X>() );
+ test_null_unique_ptr<X const>( boost::movelib::unique_ptr<X>(), boost::movelib::unique_ptr<X>() );
+ test_null_unique_ptr<void>( boost::movelib::unique_ptr<X>(), boost::movelib::unique_ptr<X>() );
+ test_null_unique_ptr<void const>( boost::movelib::unique_ptr<X>(), boost::movelib::unique_ptr<X>() );
+ }
+
+ {
+ test_null_unique_ptr<Y>( boost::movelib::unique_ptr<Y, YD>( 0, YD() ), boost::movelib::unique_ptr<Y, YD>( 0, YD() ) );
+ test_null_unique_ptr<Y const>( boost::movelib::unique_ptr<Y, YD>( 0, YD() ), boost::movelib::unique_ptr<Y, YD>( 0, YD() ) );
+ test_null_unique_ptr<void>( boost::movelib::unique_ptr<Y, YD>( 0, YD() ), boost::movelib::unique_ptr<Y, YD>( 0, YD() ) );
+ test_null_unique_ptr<void const>( boost::movelib::unique_ptr<Y, YD>( 0, YD() ), boost::movelib::unique_ptr<Y, YD>( 0, YD() ) );
+ }
+
+ {
+ YD yd;
+
+ test_null_unique_ptr<Y>( boost::movelib::unique_ptr<Y, YD&>( 0, yd ), boost::movelib::unique_ptr<Y, YD&>( 0, yd ) );
+ test_null_unique_ptr<Y const>( boost::movelib::unique_ptr<Y, YD&>( 0, yd ), boost::movelib::unique_ptr<Y, YD&>( 0, yd ) );
+ test_null_unique_ptr<void>( boost::movelib::unique_ptr<Y, YD&>( 0, yd ), boost::movelib::unique_ptr<Y, YD&>( 0, yd ) );
+ test_null_unique_ptr<void const>( boost::movelib::unique_ptr<Y, YD&>( 0, yd ), boost::movelib::unique_ptr<Y, YD&>( 0, yd ) );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/sp_constexpr_test.cpp b/test/sp_constexpr_test.cpp
new file mode 100644
index 0000000..38c96f4
--- /dev/null
+++ b/test/sp_constexpr_test.cpp
@@ -0,0 +1,86 @@
+//
+// sp_constexpr_test.cpp
+//
+// 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
+//
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#define HAVE_CONSTEXPR_INIT
+
+#if defined( BOOST_NO_CXX11_CONSTEXPR )
+# undef HAVE_CONSTEXPR_INIT
+#endif
+
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+# undef HAVE_CONSTEXPR_INIT
+#endif
+
+#if defined(__clang__) && defined( BOOST_NO_CXX14_CONSTEXPR )
+# undef HAVE_CONSTEXPR_INIT
+#endif
+
+#if !defined( HAVE_CONSTEXPR_INIT )
+
+int main()
+{
+}
+
+#else
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+struct X: public boost::enable_shared_from_this<X>
+{
+};
+
+struct Z
+{
+ Z();
+};
+
+static Z z;
+
+static boost::shared_ptr<X> p1;
+static boost::weak_ptr<X> p2;
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+ static boost::shared_ptr<X> p3( nullptr );
+#endif
+
+Z::Z()
+{
+ p1.reset( new X );
+ p2 = p1;
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+ p3.reset( new X );
+#endif
+}
+
+int main()
+{
+ BOOST_TEST( p1.get() != 0 );
+ BOOST_TEST_EQ( p1.use_count(), 1 );
+
+ BOOST_TEST_EQ( p2.use_count(), 1 );
+ BOOST_TEST_EQ( p2.lock(), p1 );
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ BOOST_TEST( p3.get() != 0 );
+ BOOST_TEST_EQ( p3.use_count(), 1 );
+
+#endif
+
+ return boost::report_errors();
+}
+
+#endif // #if defined( BOOST_NO_CXX11_CONSEXPR )
diff --git a/test/sp_constexpr_test2.cpp b/test/sp_constexpr_test2.cpp
new file mode 100644
index 0000000..dd6e4ac
--- /dev/null
+++ b/test/sp_constexpr_test2.cpp
@@ -0,0 +1,68 @@
+//
+// sp_constexpr_test2.cpp
+//
+// 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
+//
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#define HAVE_CONSTEXPR_INIT
+
+#if defined( BOOST_NO_CXX11_CONSTEXPR )
+# undef HAVE_CONSTEXPR_INIT
+#endif
+
+#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
+# undef HAVE_CONSTEXPR_INIT
+#endif
+
+#if defined(__clang__) && defined( BOOST_NO_CXX14_CONSTEXPR )
+# undef HAVE_CONSTEXPR_INIT
+#endif
+
+#if !defined( HAVE_CONSTEXPR_INIT )
+
+int main()
+{
+}
+
+#else
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+struct X: public boost::enable_shared_from_this<X>
+{
+ int v_;
+
+ constexpr X() BOOST_NOEXCEPT: v_( 1 )
+ {
+ }
+};
+
+struct Z
+{
+ Z();
+};
+
+static Z z;
+static X x;
+
+Z::Z()
+{
+ BOOST_TEST_EQ( x.v_, 1 );
+}
+
+int main()
+{
+ return boost::report_errors();
+}
+
+#endif // #if defined( BOOST_NO_CXX11_CONSEXPR )
diff --git a/test/sp_convertible_test.cpp b/test/sp_convertible_test.cpp
new file mode 100644
index 0000000..05b15c1
--- /dev/null
+++ b/test/sp_convertible_test.cpp
@@ -0,0 +1,93 @@
+#include <boost/config.hpp>
+
+// sp_convertible_test.cpp
+//
+// Copyright (c) 2012 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/smart_ptr/detail/sp_convertible.hpp>
+
+//
+
+class X;
+
+class B
+{
+};
+
+class D: public B
+{
+};
+
+#define TEST_CV_TRUE( T, U ) \
+ BOOST_TEST(( sp_convertible< T, U >::value == true )); \
+ BOOST_TEST(( sp_convertible< T, const U >::value == true )); \
+ BOOST_TEST(( sp_convertible< T, volatile U >::value == true )); \
+ BOOST_TEST(( sp_convertible< T, const volatile U >::value == true )); \
+ BOOST_TEST(( sp_convertible< const T, U >::value == false )); \
+ BOOST_TEST(( sp_convertible< const T, const U >::value == true )); \
+ BOOST_TEST(( sp_convertible< const T, volatile U >::value == false )); \
+ BOOST_TEST(( sp_convertible< const T, const volatile U >::value == true )); \
+ BOOST_TEST(( sp_convertible< volatile T, U >::value == false )); \
+ BOOST_TEST(( sp_convertible< volatile T, const U >::value == false )); \
+ BOOST_TEST(( sp_convertible< volatile T, volatile U >::value == true )); \
+ BOOST_TEST(( sp_convertible< volatile T, const volatile U >::value == true )); \
+ BOOST_TEST(( sp_convertible< const volatile T, U >::value == false )); \
+ BOOST_TEST(( sp_convertible< const volatile T, const U >::value == false )); \
+ BOOST_TEST(( sp_convertible< const volatile T, volatile U >::value == false )); \
+ BOOST_TEST(( sp_convertible< const volatile T, const volatile U >::value == true ));
+
+#define TEST_CV_FALSE( T, U ) \
+ BOOST_TEST(( sp_convertible< T, U >::value == false )); \
+ BOOST_TEST(( sp_convertible< T, const U >::value == false )); \
+ BOOST_TEST(( sp_convertible< T, volatile U >::value == false )); \
+ BOOST_TEST(( sp_convertible< T, const volatile U >::value == false )); \
+ BOOST_TEST(( sp_convertible< const T, U >::value == false )); \
+ BOOST_TEST(( sp_convertible< const T, const U >::value == false )); \
+ BOOST_TEST(( sp_convertible< const T, volatile U >::value == false )); \
+ BOOST_TEST(( sp_convertible< const T, const volatile U >::value == false )); \
+ BOOST_TEST(( sp_convertible< volatile T, U >::value == false )); \
+ BOOST_TEST(( sp_convertible< volatile T, const U >::value == false )); \
+ BOOST_TEST(( sp_convertible< volatile T, volatile U >::value == false )); \
+ BOOST_TEST(( sp_convertible< volatile T, const volatile U >::value == false )); \
+ BOOST_TEST(( sp_convertible< const volatile T, U >::value == false )); \
+ BOOST_TEST(( sp_convertible< const volatile T, const U >::value == false )); \
+ BOOST_TEST(( sp_convertible< const volatile T, volatile U >::value == false )); \
+ BOOST_TEST(( sp_convertible< const volatile T, const volatile U >::value == false ));
+
+int main()
+{
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ using boost::detail::sp_convertible;
+
+ TEST_CV_TRUE( X, X )
+ TEST_CV_TRUE( X, void )
+ TEST_CV_FALSE( void, X )
+ TEST_CV_TRUE( D, B )
+ TEST_CV_FALSE( B, D )
+
+ TEST_CV_TRUE( X[], X[] )
+ TEST_CV_FALSE( D[], B[] )
+
+ TEST_CV_TRUE( X[3], X[3] )
+ TEST_CV_FALSE( X[3], X[4] )
+ TEST_CV_FALSE( D[3], B[3] )
+
+ TEST_CV_TRUE( X[3], X[] )
+ TEST_CV_FALSE( X[], X[3] )
+
+ TEST_CV_TRUE( X[], void )
+ TEST_CV_FALSE( void, X[] )
+
+ TEST_CV_TRUE( X[3], void )
+ TEST_CV_FALSE( void, X[3] )
+
+#endif
+
+ return boost::report_errors();
+}
diff --git a/test/sp_convertible_test2.cpp b/test/sp_convertible_test2.cpp
new file mode 100644
index 0000000..7635d82
--- /dev/null
+++ b/test/sp_convertible_test2.cpp
@@ -0,0 +1,108 @@
+#include <boost/config.hpp>
+
+// sp_convertible_test2.cpp
+//
+// Copyright 2012, 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
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+
+//
+
+class X;
+
+class B
+{
+};
+
+class D: public B
+{
+};
+
+using boost::is_convertible;
+
+#define TEST_CV_TRUE_( S1, T, S2, U ) \
+ BOOST_TEST(( is_convertible< S1<T>, S2<U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<const U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<const volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<const U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<const volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<const volatile U> >::value == true )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<const volatile U> >::value == true ));
+
+#define TEST_CV_FALSE_( S1, T, S2, U ) \
+ BOOST_TEST(( is_convertible< S1<T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<T>, S2<const volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const T>, S2<const volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<volatile T>, S2<const volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<const U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<volatile U> >::value == false )); \
+ BOOST_TEST(( is_convertible< S1<const volatile T>, S2<const volatile U> >::value == false ));
+
+using boost::shared_ptr;
+using boost::weak_ptr;
+
+#define TEST_CV_TRUE( T, U ) \
+ TEST_CV_TRUE_( shared_ptr, T, shared_ptr, U ) \
+ TEST_CV_TRUE_( shared_ptr, T, weak_ptr, U ) \
+ TEST_CV_TRUE_( weak_ptr, T, weak_ptr, U )
+
+#define TEST_CV_FALSE( T, U ) \
+ TEST_CV_FALSE_( shared_ptr, T, shared_ptr, U ) \
+ TEST_CV_FALSE_( shared_ptr, T, weak_ptr, U ) \
+ TEST_CV_FALSE_( weak_ptr, T, weak_ptr, U )
+
+int main()
+{
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ TEST_CV_TRUE( X, X )
+ TEST_CV_TRUE( X, void )
+ TEST_CV_FALSE( void, X )
+ TEST_CV_TRUE( D, B )
+ TEST_CV_FALSE( B, D )
+
+ TEST_CV_TRUE( X[], X[] )
+ TEST_CV_FALSE( D[], B[] )
+
+ TEST_CV_TRUE( X[3], X[3] )
+ TEST_CV_FALSE( X[3], X[4] )
+ TEST_CV_FALSE( D[3], B[3] )
+
+ TEST_CV_TRUE( X[3], X[] )
+ TEST_CV_FALSE( X[], X[3] )
+
+ TEST_CV_TRUE( X[], void )
+ TEST_CV_FALSE( void, X[] )
+
+ TEST_CV_TRUE( X[3], void )
+ TEST_CV_FALSE( void, X[3] )
+
+#endif
+
+ return boost::report_errors();
+}
diff --git a/test/sp_explicit_inst_test.cpp b/test/sp_explicit_inst_test.cpp
new file mode 100644
index 0000000..d8de782
--- /dev/null
+++ b/test/sp_explicit_inst_test.cpp
@@ -0,0 +1,23 @@
+//
+// Explicit instantiations are reported to exist in user code
+//
+// Copyright (c) 2014 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
+//
+
+#include <boost/shared_ptr.hpp>
+
+template class boost::shared_ptr< int >;
+
+struct X
+{
+};
+
+template class boost::shared_ptr< X >;
+
+int main()
+{
+}
diff --git a/test/sp_hash_test.cpp b/test/sp_hash_test.cpp
new file mode 100644
index 0000000..b67f547
--- /dev/null
+++ b/test/sp_hash_test.cpp
@@ -0,0 +1,34 @@
+//
+// sp_hash_test.cpp
+//
+// Copyright 2011 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/functional/hash.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ boost::hash< boost::shared_ptr<int> > hasher;
+
+ boost::shared_ptr< int > p1, p2( p1 ), p3( new int ), p4( p3 ), p5( new int );
+
+ BOOST_TEST_EQ( p1, p2 );
+ BOOST_TEST_EQ( hasher( p1 ), hasher( p2 ) );
+
+ BOOST_TEST_NE( p1, p3 );
+ BOOST_TEST_NE( hasher( p1 ), hasher( p3 ) );
+
+ BOOST_TEST_EQ( p3, p4 );
+ BOOST_TEST_EQ( hasher( p3 ), hasher( p4 ) );
+
+ BOOST_TEST_NE( p3, p5 );
+ BOOST_TEST_NE( hasher( p3 ), hasher( p5 ) );
+
+ return boost::report_errors();
+}
diff --git a/test/sp_hash_test2.cpp b/test/sp_hash_test2.cpp
new file mode 100644
index 0000000..c1cbf70
--- /dev/null
+++ b/test/sp_hash_test2.cpp
@@ -0,0 +1,34 @@
+//
+// sp_hash_test2.cpp
+//
+// Copyright 2011, 2015 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/functional/hash.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ boost::hash< boost::shared_ptr<int[]> > hasher;
+
+ boost::shared_ptr< int[] > p1, p2( p1 ), p3( new int[1] ), p4( p3 ), p5( new int[1] );
+
+ BOOST_TEST_EQ( p1, p2 );
+ BOOST_TEST_EQ( hasher( p1 ), hasher( p2 ) );
+
+ BOOST_TEST_NE( p1, p3 );
+ BOOST_TEST_NE( hasher( p1 ), hasher( p3 ) );
+
+ BOOST_TEST_EQ( p3, p4 );
+ BOOST_TEST_EQ( hasher( p3 ), hasher( p4 ) );
+
+ BOOST_TEST_NE( p3, p5 );
+ BOOST_TEST_NE( hasher( p3 ), hasher( p5 ) );
+
+ return boost::report_errors();
+}
diff --git a/test/sp_hash_test3.cpp b/test/sp_hash_test3.cpp
new file mode 100644
index 0000000..4d4acad
--- /dev/null
+++ b/test/sp_hash_test3.cpp
@@ -0,0 +1,34 @@
+//
+// sp_hash_test3.cpp
+//
+// Copyright 2011, 2015 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/functional/hash.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+ boost::hash< boost::shared_ptr<int[1]> > hasher;
+
+ boost::shared_ptr< int[1] > p1, p2( p1 ), p3( new int[1] ), p4( p3 ), p5( new int[1] );
+
+ BOOST_TEST_EQ( p1, p2 );
+ BOOST_TEST_EQ( hasher( p1 ), hasher( p2 ) );
+
+ BOOST_TEST_NE( p1, p3 );
+ BOOST_TEST_NE( hasher( p1 ), hasher( p3 ) );
+
+ BOOST_TEST_EQ( p3, p4 );
+ BOOST_TEST_EQ( hasher( p3 ), hasher( p4 ) );
+
+ BOOST_TEST_NE( p3, p5 );
+ BOOST_TEST_NE( hasher( p3 ), hasher( p5 ) );
+
+ return boost::report_errors();
+}
diff --git a/test/sp_interlocked_test.cpp b/test/sp_interlocked_test.cpp
new file mode 100644
index 0000000..73a57f6
--- /dev/null
+++ b/test/sp_interlocked_test.cpp
@@ -0,0 +1,71 @@
+//
+// sp_interlocked_test.cpp
+//
+// Copyright 2014 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
+//
+
+#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )
+
+#include <boost/smart_ptr/detail/sp_interlocked.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#ifndef __LP64__
+
+typedef long long_type;
+
+#else
+
+// On Cygwin 64, long is 64 bit
+typedef int long_type;
+
+#endif
+
+int main()
+{
+ long_type x = 0, r;
+
+ r = BOOST_SP_INTERLOCKED_INCREMENT( &x );
+
+ BOOST_TEST( x == 1 );
+ BOOST_TEST( r == 1 );
+
+ r = BOOST_SP_INTERLOCKED_DECREMENT( &x );
+
+ BOOST_TEST( x == 0 );
+ BOOST_TEST( r == 0 );
+
+ r = BOOST_SP_INTERLOCKED_EXCHANGE( &x, 3 );
+
+ BOOST_TEST( x == 3 );
+ BOOST_TEST( r == 0 );
+
+ r = BOOST_SP_INTERLOCKED_EXCHANGE_ADD( &x, 2 );
+
+ BOOST_TEST( x == 5 );
+ BOOST_TEST( r == 3 );
+
+ r = BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE( &x, 0, 3 );
+
+ BOOST_TEST( x == 5 );
+ BOOST_TEST( r == 5 );
+
+ r = BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE( &x, 0, 5 );
+
+ BOOST_TEST( x == 0 );
+ BOOST_TEST( r == 5 );
+
+ return boost::report_errors();
+}
+
+#else
+
+int main()
+{
+ return 0;
+}
+
+#endif
diff --git a/test/sp_nothrow_test.cpp b/test/sp_nothrow_test.cpp
new file mode 100644
index 0000000..156e72e
--- /dev/null
+++ b/test/sp_nothrow_test.cpp
@@ -0,0 +1,96 @@
+//
+// sp_nothrow_test.cpp
+//
+// Copyright 2016 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
+//
+
+#include <boost/config.hpp>
+
+#if defined( BOOST_NO_CXX11_HDR_TYPE_TRAITS )
+
+int main()
+{
+}
+
+#else
+
+#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/scoped_array.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/core/lightweight_test_trait.hpp>
+#include <type_traits>
+
+template<class T> void test_copy()
+{
+ BOOST_TEST_TRAIT_TRUE(( std::is_nothrow_copy_constructible<T> ));
+ BOOST_TEST_TRAIT_TRUE(( std::is_nothrow_copy_assignable<T> ));
+}
+
+template<class T> void test_move()
+{
+ BOOST_TEST_TRAIT_TRUE(( std::is_nothrow_move_constructible<T> ));
+ BOOST_TEST_TRAIT_TRUE(( std::is_nothrow_move_assignable<T> ));
+}
+
+template<class T> void test_default()
+{
+ BOOST_TEST_TRAIT_TRUE(( std::is_nothrow_default_constructible<T> ));
+}
+
+template<class T> void test_destroy()
+{
+ BOOST_TEST_TRAIT_TRUE(( std::is_nothrow_destructible<T> ));
+}
+
+template<class T> void test_cmd()
+{
+ test_copy<T>();
+ test_move<T>();
+ test_default<T>();
+}
+
+struct X
+{
+};
+
+struct Y: public boost::enable_shared_from_this<Y>
+{
+};
+
+int main()
+{
+ test_cmd< boost::shared_ptr<X> >();
+ test_cmd< boost::shared_array<X> >();
+ test_cmd< boost::weak_ptr<X> >();
+
+ test_copy< Y >();
+ test_default< Y >();
+ test_destroy< Y >();
+
+ // test_move< Y >();
+ BOOST_TEST_TRAIT_TRUE(( std::is_nothrow_move_constructible<Y> ));
+
+#if !( defined( BOOST_MSVC ) && BOOST_MSVC == 1700 )
+
+ BOOST_TEST_TRAIT_TRUE(( std::is_nothrow_move_assignable<Y> ));
+
+#endif
+
+ test_default< boost::scoped_ptr<X> >();
+ test_default< boost::scoped_array<X> >();
+
+ test_move< boost::intrusive_ptr<X> >();
+ test_default< boost::intrusive_ptr<X> >();
+
+ return boost::report_errors();
+}
+
+#endif // #if defined( BOOST_NO_CXX11_HDR_TYPE_TRAITS )
diff --git a/test/sp_nullptr_test.cpp b/test/sp_nullptr_test.cpp
new file mode 100644
index 0000000..1b3965c
--- /dev/null
+++ b/test/sp_nullptr_test.cpp
@@ -0,0 +1,141 @@
+//
+// sp_nullptr_test.cpp
+//
+// Copyright 2012 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)
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <cstddef>
+#include <memory>
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+struct X
+{
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+};
+
+int X::instances = 0;
+
+void f( boost::detail::sp_nullptr_t )
+{
+}
+
+int main()
+{
+ {
+ boost::shared_ptr<void> p( nullptr );
+
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.use_count() == 0 );
+
+ BOOST_TEST( p == nullptr );
+ BOOST_TEST( nullptr == p );
+ BOOST_TEST( !( p != nullptr ) );
+ BOOST_TEST( !( nullptr != p ) );
+ }
+
+ {
+ boost::shared_ptr<int> p( nullptr, f );
+
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.use_count() == 1 );
+
+ BOOST_TEST( p == nullptr );
+ BOOST_TEST( nullptr == p );
+ BOOST_TEST( !( p != nullptr ) );
+ BOOST_TEST( !( nullptr != p ) );
+ }
+
+ {
+ boost::shared_ptr<int> p( nullptr, f, std::allocator<int>() );
+
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.use_count() == 1 );
+
+ BOOST_TEST( p == nullptr );
+ BOOST_TEST( nullptr == p );
+ BOOST_TEST( !( p != nullptr ) );
+ BOOST_TEST( !( nullptr != p ) );
+ }
+
+ {
+ boost::shared_ptr<int> p( new int );
+
+ BOOST_TEST( p.get() != 0 );
+ BOOST_TEST( p.use_count() == 1 );
+
+ BOOST_TEST( p != nullptr );
+ BOOST_TEST( nullptr != p );
+ BOOST_TEST( !( p == nullptr ) );
+ BOOST_TEST( !( nullptr == p ) );
+
+ p = nullptr;
+
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.use_count() == 0 );
+
+ BOOST_TEST( p == nullptr );
+ BOOST_TEST( nullptr == p );
+ BOOST_TEST( !( p != nullptr ) );
+ BOOST_TEST( !( nullptr != p ) );
+ }
+
+ {
+ BOOST_TEST( X::instances == 0 );
+
+ boost::shared_ptr<X> p( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ BOOST_TEST( p.get() != 0 );
+ BOOST_TEST( p.use_count() == 1 );
+
+ BOOST_TEST( p != nullptr );
+ BOOST_TEST( nullptr != p );
+ BOOST_TEST( !( p == nullptr ) );
+ BOOST_TEST( !( nullptr == p ) );
+
+ p = nullptr;
+ BOOST_TEST( X::instances == 0 );
+
+ BOOST_TEST( p.get() == 0 );
+ BOOST_TEST( p.use_count() == 0 );
+
+ BOOST_TEST( p == nullptr );
+ BOOST_TEST( nullptr == p );
+ BOOST_TEST( !( p != nullptr ) );
+ BOOST_TEST( !( nullptr != p ) );
+ }
+
+ return boost::report_errors();
+}
+
+#else
+
+int main()
+{
+ return 0;
+}
+
+#endif
diff --git a/test/sp_recursive_assign2_rv_test.cpp b/test/sp_recursive_assign2_rv_test.cpp
new file mode 100644
index 0000000..e450c72
--- /dev/null
+++ b/test/sp_recursive_assign2_rv_test.cpp
@@ -0,0 +1,114 @@
+//
+// sp_recursive_assign2_rv_test.cpp
+//
+// Copyright 2009 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
+//
+
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X
+{
+public:
+
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const& );
+};
+
+int X::instances = 0;
+
+class Y
+{
+public:
+
+ static int instances;
+
+ Y()
+ {
+ ++instances;
+ }
+
+ ~Y()
+ {
+ --instances;
+ }
+
+private:
+
+ Y( Y const& );
+};
+
+int Y::instances = 0;
+
+static boost::shared_ptr<void> s_pv;
+
+class Z
+{
+public:
+
+ static int instances;
+
+ Z()
+ {
+ ++instances;
+ }
+
+ ~Z()
+ {
+ --instances;
+ s_pv = boost::shared_ptr<Y>( new Y );
+ }
+
+private:
+
+ Z( Z const& );
+};
+
+int Z::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ s_pv = boost::shared_ptr<Z>( new Z );
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 1 );
+
+ s_pv = boost::shared_ptr<X>( new X );
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 1 );
+ BOOST_TEST( Z::instances == 0 );
+
+ s_pv = boost::shared_ptr<Y>();
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ return boost::report_errors();
+}
diff --git a/test/sp_recursive_assign2_test.cpp b/test/sp_recursive_assign2_test.cpp
new file mode 100644
index 0000000..ef6fa52
--- /dev/null
+++ b/test/sp_recursive_assign2_test.cpp
@@ -0,0 +1,122 @@
+//
+// sp_recursive_assign2_test.cpp
+//
+// Copyright 2009 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
+//
+
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X
+{
+public:
+
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const& );
+};
+
+int X::instances = 0;
+
+class Y
+{
+public:
+
+ static int instances;
+
+ Y()
+ {
+ ++instances;
+ }
+
+ ~Y()
+ {
+ --instances;
+ }
+
+private:
+
+ Y( Y const& );
+};
+
+int Y::instances = 0;
+
+static boost::shared_ptr<void> s_pv;
+
+class Z
+{
+public:
+
+ static int instances;
+
+ Z()
+ {
+ ++instances;
+ }
+
+ ~Z()
+ {
+ --instances;
+
+ boost::shared_ptr<Y> pv( new Y );
+ s_pv = pv;
+ }
+
+private:
+
+ Z( Z const& );
+};
+
+int Z::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ {
+ boost::shared_ptr<Z> pv( new Z );
+ s_pv = pv;
+ }
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 1 );
+
+ {
+ boost::shared_ptr<X> pv( new X );
+ s_pv = pv;
+ }
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 1 );
+ BOOST_TEST( Z::instances == 0 );
+
+ s_pv.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ return boost::report_errors();
+}
diff --git a/test/sp_recursive_assign_rv_test.cpp b/test/sp_recursive_assign_rv_test.cpp
new file mode 100644
index 0000000..8d80e72
--- /dev/null
+++ b/test/sp_recursive_assign_rv_test.cpp
@@ -0,0 +1,114 @@
+//
+// sp_recursive_assign_rv_test.cpp
+//
+// Copyright 2009 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
+//
+
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X
+{
+public:
+
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const& );
+};
+
+int X::instances = 0;
+
+class Y
+{
+public:
+
+ static int instances;
+
+ Y()
+ {
+ ++instances;
+ }
+
+ ~Y()
+ {
+ --instances;
+ }
+
+private:
+
+ Y( Y const& );
+};
+
+int Y::instances = 0;
+
+static boost::shared_ptr<void> s_pv;
+
+class Z
+{
+public:
+
+ static int instances;
+
+ Z()
+ {
+ ++instances;
+ }
+
+ ~Z()
+ {
+ --instances;
+ s_pv = boost::shared_ptr<void>( new Y );
+ }
+
+private:
+
+ Z( Z const& );
+};
+
+int Z::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ s_pv = boost::shared_ptr<void>( new Z );
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 1 );
+
+ s_pv = boost::shared_ptr<void>( new X );
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 1 );
+ BOOST_TEST( Z::instances == 0 );
+
+ s_pv = boost::shared_ptr<void>();
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ return boost::report_errors();
+}
diff --git a/test/sp_recursive_assign_test.cpp b/test/sp_recursive_assign_test.cpp
new file mode 100644
index 0000000..0f36891
--- /dev/null
+++ b/test/sp_recursive_assign_test.cpp
@@ -0,0 +1,122 @@
+//
+// sp_recursive_assign_test.cpp
+//
+// Copyright 2009 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
+//
+
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+//
+
+class X
+{
+public:
+
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const& );
+};
+
+int X::instances = 0;
+
+class Y
+{
+public:
+
+ static int instances;
+
+ Y()
+ {
+ ++instances;
+ }
+
+ ~Y()
+ {
+ --instances;
+ }
+
+private:
+
+ Y( Y const& );
+};
+
+int Y::instances = 0;
+
+static boost::shared_ptr<void> s_pv;
+
+class Z
+{
+public:
+
+ static int instances;
+
+ Z()
+ {
+ ++instances;
+ }
+
+ ~Z()
+ {
+ --instances;
+
+ boost::shared_ptr<void> pv( new Y );
+ s_pv = pv;
+ }
+
+private:
+
+ Z( Z const& );
+};
+
+int Z::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ {
+ boost::shared_ptr<void> pv( new Z );
+ s_pv = pv;
+ }
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 1 );
+
+ {
+ boost::shared_ptr<void> pv( new X );
+ s_pv = pv;
+ }
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 1 );
+ BOOST_TEST( Z::instances == 0 );
+
+ s_pv.reset();
+
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( Y::instances == 0 );
+ BOOST_TEST( Z::instances == 0 );
+
+ return boost::report_errors();
+}
diff --git a/test/sp_typeinfo_test.cpp b/test/sp_typeinfo_test.cpp
new file mode 100644
index 0000000..e29e576
--- /dev/null
+++ b/test/sp_typeinfo_test.cpp
@@ -0,0 +1,51 @@
+//
+// sp_typeinfo_test.cpp
+//
+// Copyright (c) 2009 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
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <iostream>
+
+int main()
+{
+ BOOST_TEST( BOOST_SP_TYPEID( int ) == BOOST_SP_TYPEID( int ) );
+ BOOST_TEST( BOOST_SP_TYPEID( int ) != BOOST_SP_TYPEID( long ) );
+ BOOST_TEST( BOOST_SP_TYPEID( int ) != BOOST_SP_TYPEID( void ) );
+
+ boost::detail::sp_typeinfo const & ti = BOOST_SP_TYPEID( int );
+
+ boost::detail::sp_typeinfo const * pti = &BOOST_SP_TYPEID( int );
+ BOOST_TEST( *pti == ti );
+
+ BOOST_TEST( ti == ti );
+ BOOST_TEST( !( ti != ti ) );
+ BOOST_TEST( !ti.before( ti ) );
+
+ char const * nti = ti.name();
+ std::cout << nti << std::endl;
+
+ boost::detail::sp_typeinfo const & tv = BOOST_SP_TYPEID( void );
+
+ boost::detail::sp_typeinfo const * ptv = &BOOST_SP_TYPEID( void );
+ BOOST_TEST( *ptv == tv );
+
+ BOOST_TEST( tv == tv );
+ BOOST_TEST( !( tv != tv ) );
+ BOOST_TEST( !tv.before( tv ) );
+
+ char const * ntv = tv.name();
+ std::cout << ntv << std::endl;
+
+ BOOST_TEST( ti != tv );
+ BOOST_TEST( !( ti == tv ) );
+
+ BOOST_TEST( ti.before( tv ) != tv.before( ti ) );
+
+ return boost::report_errors();
+}
diff --git a/test/sp_unary_addr_test.cpp b/test/sp_unary_addr_test.cpp
new file mode 100644
index 0000000..a4007a2
--- /dev/null
+++ b/test/sp_unary_addr_test.cpp
@@ -0,0 +1,67 @@
+//
+// sp_unary_addr_test.cpp
+//
+// Copyright (c) 2007 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)
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <memory>
+
+struct deleter
+{
+private:
+
+ void operator& ();
+ void operator& () const;
+
+public:
+
+ int data;
+
+ deleter(): data( 17041 )
+ {
+ }
+
+ void operator()( void * )
+ {
+ }
+};
+
+struct X
+{
+};
+
+int main()
+{
+ X x;
+
+ {
+ boost::shared_ptr<X> p( &x, deleter() );
+
+ deleter * q = boost::get_deleter<deleter>( p );
+
+ BOOST_TEST( q != 0 );
+ BOOST_TEST( q != 0 && q->data == 17041 );
+ }
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 )
+#else
+
+ {
+ boost::shared_ptr<X> p( &x, deleter(), std::allocator<X>() );
+
+ deleter * q = boost::get_deleter<deleter>( p );
+
+ BOOST_TEST( q != 0 );
+ BOOST_TEST( q != 0 && q->data == 17041 );
+ }
+
+#endif
+
+ return boost::report_errors();
+}
diff --git a/test/sp_unique_ptr_test.cpp b/test/sp_unique_ptr_test.cpp
new file mode 100644
index 0000000..8e82959
--- /dev/null
+++ b/test/sp_unique_ptr_test.cpp
@@ -0,0 +1,294 @@
+//
+// sp_unique_ptr_test.cpp
+//
+// Copyright (c) 2012 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <memory>
+#include <utility>
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+struct X: public boost::enable_shared_from_this< X >
+{
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+};
+
+int X::instances = 0;
+
+struct Y
+{
+ static int instances;
+
+ bool deleted_;
+
+ Y(): deleted_( false )
+ {
+ ++instances;
+ }
+
+ ~Y()
+ {
+ BOOST_TEST( deleted_ );
+ --instances;
+ }
+
+private:
+
+ Y( Y const & );
+ Y & operator=( Y const & );
+};
+
+int Y::instances = 0;
+
+struct YD
+{
+ void operator()( Y* p ) const
+ {
+ if( p )
+ {
+ p->deleted_ = true;
+ delete p;
+ }
+ else
+ {
+ BOOST_ERROR( "YD::operator()(0) called" );
+ }
+ }
+};
+
+template<class U, class T, class D> static void test_null_unique_ptr( std::unique_ptr<T, D> p1, std::unique_ptr<T, D> p2 )
+{
+ BOOST_TEST( T::instances == 0 );
+
+ boost::shared_ptr<U> sp( std::move( p1 ) );
+
+ BOOST_TEST( sp.get() == 0 );
+ BOOST_TEST( sp.use_count() == 0 );
+
+ sp.reset( new T, typename boost::remove_reference<D>::type() );
+
+ BOOST_TEST( sp.get() != 0 );
+ BOOST_TEST( sp.use_count() == 1 );
+
+ BOOST_TEST( T::instances == 1 );
+
+ sp = std::move( p2 );
+
+ BOOST_TEST( sp.get() == 0 );
+ BOOST_TEST( sp.use_count() == 0 );
+
+ BOOST_TEST( T::instances == 0 );
+}
+
+int main()
+{
+ {
+ BOOST_TEST( X::instances == 0 );
+
+ std::unique_ptr<X> p( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ boost::shared_ptr<X> p2( std::move( p ) );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ boost::shared_ptr<X> p3 = p2->shared_from_this();
+ BOOST_TEST( p2 == p3 );
+ BOOST_TEST( !(p2 < p3) && !(p3 < p2) );
+
+ p2.reset();
+ p3.reset();
+ BOOST_TEST( X::instances == 0 );
+
+ p2 = std::unique_ptr<X>( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ p2 = std::unique_ptr<X>( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ p2.reset();
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ BOOST_TEST( X::instances == 0 );
+
+ std::unique_ptr<X> p( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ boost::shared_ptr<X const> p2( std::move( p ) );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ boost::shared_ptr<X const> p3 = p2->shared_from_this();
+ BOOST_TEST( p2 == p3 );
+ BOOST_TEST( !(p2 < p3) && !(p3 < p2) );
+
+ p2.reset();
+ p3.reset();
+ BOOST_TEST( X::instances == 0 );
+
+ p2 = std::unique_ptr<X>( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ p2 = std::unique_ptr<X>( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ p2.reset();
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ BOOST_TEST( X::instances == 0 );
+
+ std::unique_ptr<X> p( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ boost::shared_ptr<void> p2( std::move( p ) );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ p2.reset();
+ BOOST_TEST( X::instances == 0 );
+
+ p2 = std::unique_ptr<X>( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ p2 = std::unique_ptr<X>( new X );
+ BOOST_TEST( X::instances == 1 );
+
+ p2.reset();
+ BOOST_TEST( X::instances == 0 );
+ }
+
+ {
+ BOOST_TEST( Y::instances == 0 );
+
+ std::unique_ptr<Y, YD> p( new Y, YD() );
+ BOOST_TEST( Y::instances == 1 );
+
+ boost::shared_ptr<Y> p2( std::move( p ) );
+ BOOST_TEST( Y::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ p2.reset();
+ BOOST_TEST( Y::instances == 0 );
+
+ p2 = std::unique_ptr<Y, YD>( new Y, YD() );
+ BOOST_TEST( Y::instances == 1 );
+
+ p2 = std::unique_ptr<Y, YD>( new Y, YD() );
+ BOOST_TEST( Y::instances == 1 );
+
+ p2.reset();
+ BOOST_TEST( Y::instances == 0 );
+ }
+
+ {
+ BOOST_TEST( Y::instances == 0 );
+
+ YD yd;
+
+ std::unique_ptr<Y, YD&> p( new Y, yd );
+ BOOST_TEST( Y::instances == 1 );
+
+ boost::shared_ptr<Y> p2( std::move( p ) );
+ BOOST_TEST( Y::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ p2.reset();
+ BOOST_TEST( Y::instances == 0 );
+
+ p2 = std::unique_ptr<Y, YD&>( new Y, yd );
+ BOOST_TEST( Y::instances == 1 );
+
+ p2 = std::unique_ptr<Y, YD&>( new Y, yd );
+ BOOST_TEST( Y::instances == 1 );
+
+ p2.reset();
+ BOOST_TEST( Y::instances == 0 );
+ }
+
+ {
+ BOOST_TEST( Y::instances == 0 );
+
+ YD yd;
+
+ std::unique_ptr<Y, YD const&> p( new Y, yd );
+ BOOST_TEST( Y::instances == 1 );
+
+ boost::shared_ptr<Y> p2( std::move( p ) );
+ BOOST_TEST( Y::instances == 1 );
+ BOOST_TEST( p.get() == 0 );
+
+ p2.reset();
+ BOOST_TEST( Y::instances == 0 );
+
+ p2 = std::unique_ptr<Y, YD const&>( new Y, yd );
+ BOOST_TEST( Y::instances == 1 );
+
+ p2 = std::unique_ptr<Y, YD const&>( new Y, yd );
+ BOOST_TEST( Y::instances == 1 );
+
+ p2.reset();
+ BOOST_TEST( Y::instances == 0 );
+ }
+
+ {
+ test_null_unique_ptr<X>( std::unique_ptr<X>(), std::unique_ptr<X>() );
+ test_null_unique_ptr<X const>( std::unique_ptr<X>(), std::unique_ptr<X>() );
+ test_null_unique_ptr<void>( std::unique_ptr<X>(), std::unique_ptr<X>() );
+ test_null_unique_ptr<void const>( std::unique_ptr<X>(), std::unique_ptr<X>() );
+ }
+
+ {
+ test_null_unique_ptr<Y>( std::unique_ptr<Y, YD>( 0, YD() ), std::unique_ptr<Y, YD>( 0, YD() ) );
+ test_null_unique_ptr<Y const>( std::unique_ptr<Y, YD>( 0, YD() ), std::unique_ptr<Y, YD>( 0, YD() ) );
+ test_null_unique_ptr<void>( std::unique_ptr<Y, YD>( 0, YD() ), std::unique_ptr<Y, YD>( 0, YD() ) );
+ test_null_unique_ptr<void const>( std::unique_ptr<Y, YD>( 0, YD() ), std::unique_ptr<Y, YD>( 0, YD() ) );
+ }
+
+ {
+ YD yd;
+
+ test_null_unique_ptr<Y>( std::unique_ptr<Y, YD&>( 0, yd ), std::unique_ptr<Y, YD&>( 0, yd ) );
+ test_null_unique_ptr<Y const>( std::unique_ptr<Y, YD&>( 0, yd ), std::unique_ptr<Y, YD&>( 0, yd ) );
+ test_null_unique_ptr<void>( std::unique_ptr<Y, YD&>( 0, yd ), std::unique_ptr<Y, YD&>( 0, yd ) );
+ test_null_unique_ptr<void const>( std::unique_ptr<Y, YD&>( 0, yd ), std::unique_ptr<Y, YD&>( 0, yd ) );
+ }
+
+ return boost::report_errors();
+}
+
+#else // !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+int main()
+{
+ return 0;
+}
+
+#endif
diff --git a/test/sp_windows_h_test.cpp b/test/sp_windows_h_test.cpp
new file mode 100644
index 0000000..b4df132
--- /dev/null
+++ b/test/sp_windows_h_test.cpp
@@ -0,0 +1,11 @@
+// Copyright 2018 Peter Dimov
+// Distributed under the Boost Software License, Version 1.0.
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# include <windows.h>
+# include <boost/shared_ptr.hpp>
+#endif
+
+int main()
+{
+}
diff --git a/test/sp_zero_compare_test.cpp b/test/sp_zero_compare_test.cpp
new file mode 100644
index 0000000..e326d34
--- /dev/null
+++ b/test/sp_zero_compare_test.cpp
@@ -0,0 +1,78 @@
+//
+// sp_zero_compare_test.cpp - == 0, != 0
+//
+// Copyright 2012 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)
+//
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/scoped_array.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+struct W
+{
+};
+
+void intrusive_ptr_add_ref( W* )
+{
+}
+
+void intrusive_ptr_release( W* )
+{
+}
+
+int main()
+{
+ {
+ boost::scoped_ptr<int> p;
+
+ BOOST_TEST( p == 0 );
+ BOOST_TEST( 0 == p );
+ BOOST_TEST( !( p != 0 ) );
+ BOOST_TEST( !( 0 != p ) );
+ }
+
+ {
+ boost::scoped_array<int> p;
+
+ BOOST_TEST( p == 0 );
+ BOOST_TEST( 0 == p );
+ BOOST_TEST( !( p != 0 ) );
+ BOOST_TEST( !( 0 != p ) );
+ }
+
+ {
+ boost::shared_ptr<int> p;
+
+ BOOST_TEST( p == 0 );
+ BOOST_TEST( 0 == p );
+ BOOST_TEST( !( p != 0 ) );
+ BOOST_TEST( !( 0 != p ) );
+ }
+
+ {
+ boost::shared_array<int> p;
+
+ BOOST_TEST( p == 0 );
+ BOOST_TEST( 0 == p );
+ BOOST_TEST( !( p != 0 ) );
+ BOOST_TEST( !( 0 != p ) );
+ }
+
+ {
+ boost::intrusive_ptr<W> p;
+
+ BOOST_TEST( p == 0 );
+ BOOST_TEST( 0 == p );
+ BOOST_TEST( !( p != 0 ) );
+ BOOST_TEST( !( 0 != p ) );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/spinlock_pool_test.cpp b/test/spinlock_pool_test.cpp
new file mode 100644
index 0000000..53f61ca
--- /dev/null
+++ b/test/spinlock_pool_test.cpp
@@ -0,0 +1,30 @@
+//
+// spinlock_pool_test.cpp
+//
+// Copyright 2008 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
+//
+
+#include <boost/smart_ptr/detail/spinlock_pool.hpp>
+
+// Sanity check only
+
+int main()
+{
+ int x = 0;
+
+ {
+ boost::detail::spinlock_pool<0>::scoped_lock lock( &x );
+ ++x;
+ }
+
+ {
+ boost::detail::spinlock_pool<1>::scoped_lock lock( &x );
+ boost::detail::spinlock_pool<2>::scoped_lock lock2( &x );
+ }
+
+ return 0;
+}
diff --git a/test/spinlock_test.cpp b/test/spinlock_test.cpp
new file mode 100644
index 0000000..d2c66c0
--- /dev/null
+++ b/test/spinlock_test.cpp
@@ -0,0 +1,31 @@
+//
+// spinlock_test.cpp
+//
+// Copyright 2008 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)
+//
+
+#include <boost/smart_ptr/detail/spinlock.hpp>
+
+// Sanity check only
+
+static boost::detail::spinlock sp = BOOST_DETAIL_SPINLOCK_INIT;
+static boost::detail::spinlock sp2 = BOOST_DETAIL_SPINLOCK_INIT;
+
+int main()
+{
+ sp.lock();
+ sp2.lock();
+ sp.unlock();
+ sp2.unlock();
+
+ {
+ boost::detail::spinlock::scoped_lock lock( sp );
+ boost::detail::spinlock::scoped_lock lock2( sp2 );
+ }
+
+ return 0;
+}
diff --git a/test/spinlock_try_test.cpp b/test/spinlock_try_test.cpp
new file mode 100644
index 0000000..008b60e
--- /dev/null
+++ b/test/spinlock_try_test.cpp
@@ -0,0 +1,46 @@
+//
+// spinlock_try_test.cpp
+//
+// Copyright 2008 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)
+//
+
+#include <boost/smart_ptr/detail/spinlock.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+// Sanity check only
+
+static boost::detail::spinlock sp = BOOST_DETAIL_SPINLOCK_INIT;
+static boost::detail::spinlock sp2 = BOOST_DETAIL_SPINLOCK_INIT;
+
+int main()
+{
+ BOOST_TEST( sp.try_lock() );
+ BOOST_TEST( !sp.try_lock() );
+ BOOST_TEST( sp2.try_lock() );
+ BOOST_TEST( !sp.try_lock() );
+ BOOST_TEST( !sp2.try_lock() );
+ sp.unlock();
+ sp2.unlock();
+
+ sp.lock();
+ BOOST_TEST( !sp.try_lock() );
+ sp2.lock();
+ BOOST_TEST( !sp.try_lock() );
+ BOOST_TEST( !sp2.try_lock() );
+ sp.unlock();
+ sp2.unlock();
+
+ {
+ boost::detail::spinlock::scoped_lock lock( sp );
+ BOOST_TEST( !sp.try_lock() );
+ boost::detail::spinlock::scoped_lock lock2( sp2 );
+ BOOST_TEST( !sp.try_lock() );
+ BOOST_TEST( !sp2.try_lock() );
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/spinlock_windows_h_test.cpp b/test/spinlock_windows_h_test.cpp
new file mode 100644
index 0000000..68a8781
--- /dev/null
+++ b/test/spinlock_windows_h_test.cpp
@@ -0,0 +1,11 @@
+// Copyright 2018 Peter Dimov
+// Distributed under the Boost Software License, Version 1.0.
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# include <windows.h>
+# include <boost/smart_ptr/detail/spinlock.hpp>
+#endif
+
+int main()
+{
+}
diff --git a/test/weak_from_raw_test.cpp b/test/weak_from_raw_test.cpp
new file mode 100644
index 0000000..34d21eb
--- /dev/null
+++ b/test/weak_from_raw_test.cpp
@@ -0,0 +1,38 @@
+#include <boost/config.hpp>
+
+//
+// weak_from_raw_test.cpp
+//
+// Copyright (c) 2009 Frank Mori Hess
+//
+// 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)
+//
+
+
+#include <boost/smart_ptr/enable_shared_from_raw.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+
+struct X: public boost::enable_shared_from_raw
+{};
+
+void basic_weak_from_raw_test()
+{
+ X *p(new X);
+ boost::weak_ptr<X> weak = boost::weak_from_raw(p);
+ BOOST_TEST(!weak.expired());
+ boost::shared_ptr<X> shared(p);
+ weak = boost::weak_from_raw(p);
+ BOOST_TEST(weak.expired() == false);
+ boost::shared_ptr<X> shared2(weak);
+ BOOST_TEST((shared < shared2 || shared2 < shared) == false);
+ BOOST_TEST(shared.get() == p);
+}
+
+int main()
+{
+ basic_weak_from_raw_test();
+ return boost::report_errors();
+}
diff --git a/test/weak_from_raw_test2.cpp b/test/weak_from_raw_test2.cpp
new file mode 100644
index 0000000..c1da6f0
--- /dev/null
+++ b/test/weak_from_raw_test2.cpp
@@ -0,0 +1,67 @@
+//
+// weak_from_raw_test2.cpp
+//
+// Test that weak_from_raw returns consistent values
+// throughout the object lifetime
+//
+// Copyright (c) 2014 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
+//
+
+#include <boost/smart_ptr/enable_shared_from_raw.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+class X;
+
+static boost::weak_ptr< X > r_;
+
+void register_( boost::weak_ptr< X > const & r )
+{
+ r_ = r;
+}
+
+void check_( boost::weak_ptr< X > const & r )
+{
+ BOOST_TEST( !( r < r_ ) && !( r_ < r ) );
+}
+
+void unregister_( boost::weak_ptr< X > const & r )
+{
+ BOOST_TEST( !( r < r_ ) && !( r_ < r ) );
+ r_.reset();
+}
+
+class X: public boost::enable_shared_from_raw
+{
+public:
+
+ X()
+ {
+ register_( boost::shared_from_raw( this ) );
+ }
+
+ ~X()
+ {
+ unregister_( boost::weak_from_raw( this ) );
+ }
+
+ void check()
+ {
+ check_( boost::weak_from_raw( this ) );
+ }
+};
+
+int main()
+{
+ {
+ boost::shared_ptr< X > px( new X );
+ px->check();
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/weak_from_raw_test3.cpp b/test/weak_from_raw_test3.cpp
new file mode 100644
index 0000000..ee73b4c
--- /dev/null
+++ b/test/weak_from_raw_test3.cpp
@@ -0,0 +1,46 @@
+//
+// weak_from_raw_test3.cpp
+//
+// Test that weak_from_raw and shared_from_raw
+// return consistent values from a constructor
+//
+// Copyright (c) 2015 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
+//
+
+#include <boost/smart_ptr/enable_shared_from_raw.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+class X: public boost::enable_shared_from_raw
+{
+public:
+
+ X()
+ {
+ boost::weak_ptr<X> p1 = boost::weak_from_raw( this );
+ BOOST_TEST( !p1.expired() );
+
+ boost::weak_ptr<X> p2 = boost::weak_from_raw( this );
+ BOOST_TEST( !p2.expired() );
+ BOOST_TEST( !( p1 < p2 ) && !( p2 < p1 ) );
+
+ boost::weak_ptr<X> p3 = boost::shared_from_raw( this );
+ BOOST_TEST( !( p1 < p3 ) && !( p3 < p1 ) );
+
+ boost::weak_ptr<X> p4 = boost::weak_from_raw( this );
+ BOOST_TEST( !p4.expired() );
+ BOOST_TEST( !( p3 < p4 ) && !( p4 < p3 ) );
+ BOOST_TEST( !( p1 < p4 ) && !( p4 < p1 ) );
+ }
+};
+
+int main()
+{
+ boost::shared_ptr< X > px( new X );
+ return boost::report_errors();
+}
diff --git a/test/weak_from_raw_test4.cpp b/test/weak_from_raw_test4.cpp
new file mode 100644
index 0000000..2408f00
--- /dev/null
+++ b/test/weak_from_raw_test4.cpp
@@ -0,0 +1,67 @@
+//
+// weak_from_raw_test4.cpp
+//
+// As weak_from_raw_test2.cpp, but uses weak_from_raw
+// in the constructor
+//
+// Copyright (c) 2014, 2015 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
+//
+
+#include <boost/smart_ptr/enable_shared_from_raw.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+class X;
+
+static boost::weak_ptr< X > r_;
+
+void register_( boost::weak_ptr< X > const & r )
+{
+ r_ = r;
+}
+
+void check_( boost::weak_ptr< X > const & r )
+{
+ BOOST_TEST( !( r < r_ ) && !( r_ < r ) );
+}
+
+void unregister_( boost::weak_ptr< X > const & r )
+{
+ BOOST_TEST( !( r < r_ ) && !( r_ < r ) );
+ r_.reset();
+}
+
+class X: public boost::enable_shared_from_raw
+{
+public:
+
+ X()
+ {
+ register_( boost::weak_from_raw( this ) );
+ }
+
+ ~X()
+ {
+ unregister_( boost::weak_from_raw( this ) );
+ }
+
+ void check()
+ {
+ check_( boost::weak_from_raw( this ) );
+ }
+};
+
+int main()
+{
+ {
+ boost::shared_ptr< X > px( new X );
+ px->check();
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/weak_from_raw_test5.cpp b/test/weak_from_raw_test5.cpp
new file mode 100644
index 0000000..5425c27
--- /dev/null
+++ b/test/weak_from_raw_test5.cpp
@@ -0,0 +1,45 @@
+//
+// weak_from_raw_test5.cpp
+//
+// Tests whether pointers returned from weak_from_raw
+// expire properly
+//
+// Copyright 2015 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
+//
+
+#include <boost/smart_ptr/enable_shared_from_raw.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+class X: public boost::enable_shared_from_raw
+{
+public:
+
+ explicit X( boost::weak_ptr< X > & r )
+ {
+ r = boost::weak_from_raw( this );
+ }
+};
+
+int main()
+{
+ boost::weak_ptr<X> p1, p2;
+
+ {
+ boost::shared_ptr< X > px( new X( p1 ) );
+ p2 = boost::weak_from_raw( px.get() );
+
+ BOOST_TEST( !p1.expired() );
+ BOOST_TEST( !p2.expired() );
+ }
+
+ BOOST_TEST( p1.expired() );
+ BOOST_TEST( p2.expired() );
+
+ return boost::report_errors();
+}
diff --git a/test/weak_from_this_test.cpp b/test/weak_from_this_test.cpp
new file mode 100644
index 0000000..1a874e1
--- /dev/null
+++ b/test/weak_from_this_test.cpp
@@ -0,0 +1,52 @@
+#include <boost/config.hpp>
+
+//
+// weak_from_this_test.cpp
+//
+// Copyright (c) 2002, 2003, 2015 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
+//
+
+
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+class V: public boost::enable_shared_from_this<V>
+{
+};
+
+void test()
+{
+ boost::shared_ptr<V> p( new V );
+
+ boost::weak_ptr<V> q = p;
+ BOOST_TEST( !q.expired() );
+
+ boost::weak_ptr<V> q2 = p->weak_from_this();
+ BOOST_TEST( !q2.expired() );
+ BOOST_TEST( !(q < q2) && !(q2 < q) );
+
+ V v2( *p );
+
+ boost::weak_ptr<V> q3 = v2.weak_from_this();
+ BOOST_TEST( q3.expired() );
+
+ *p = V();
+
+ boost::weak_ptr<V> q4 = p->shared_from_this();
+ BOOST_TEST( !q4.expired() );
+ BOOST_TEST( !(q < q4) && !(q4 < q) );
+ BOOST_TEST( !(q2 < q4) && !(q4 < q2) );
+}
+
+int main()
+{
+ test();
+ return boost::report_errors();
+}
diff --git a/test/weak_from_this_test2.cpp b/test/weak_from_this_test2.cpp
new file mode 100644
index 0000000..05f3df2
--- /dev/null
+++ b/test/weak_from_this_test2.cpp
@@ -0,0 +1,60 @@
+//
+// weak_from_this_test2.cpp
+//
+// Tests weak_from_this in a destructor
+//
+// Copyright (c) 2014, 2015 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
+//
+
+#include <boost/smart_ptr/enable_shared_from_this.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+class X: public boost::enable_shared_from_this< X >
+{
+private:
+
+ boost::weak_ptr<X> px_;
+
+public:
+
+ X()
+ {
+ boost::weak_ptr<X> p1 = weak_from_this();
+ BOOST_TEST( p1._empty() );
+ BOOST_TEST( p1.expired() );
+ }
+
+ void check()
+ {
+ boost::weak_ptr<X> p2 = weak_from_this();
+ BOOST_TEST( !p2.expired() );
+
+ BOOST_TEST( p2.lock().get() == this );
+
+ px_ = p2;
+ }
+
+ ~X()
+ {
+ boost::weak_ptr<X> p3 = weak_from_this();
+ BOOST_TEST( p3.expired() );
+
+ BOOST_TEST( !(px_ < p3) && !(p3 < px_) );
+ }
+};
+
+int main()
+{
+ {
+ boost::shared_ptr< X > px( new X );
+ px->check();
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/weak_ptr_move_test.cpp b/test/weak_ptr_move_test.cpp
new file mode 100644
index 0000000..dbf2629
--- /dev/null
+++ b/test/weak_ptr_move_test.cpp
@@ -0,0 +1,122 @@
+//
+// weak_ptr_move_test.cpp
+//
+// Copyright (c) 2007 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
+//
+
+#include <boost/weak_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <utility>
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+struct X
+{
+ static long instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+private:
+
+ X( X const & );
+ X & operator=( X const & );
+};
+
+long X::instances = 0;
+
+int main()
+{
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X> p_( new X );
+ boost::weak_ptr<X> p( p_ );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.use_count() == 1 );
+
+ boost::weak_ptr<X> p2( std::move( p ) );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p2.use_count() == 1 );
+ BOOST_TEST( p.expired() );
+
+ boost::weak_ptr<void> p3( std::move( p2 ) );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p3.use_count() == 1 );
+ BOOST_TEST( p2.expired() );
+
+ p_.reset();
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( p3.expired() );
+ }
+
+ {
+ boost::shared_ptr<X> p_( new X );
+ boost::weak_ptr<X> p( p_ );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.use_count() == 1 );
+
+ boost::weak_ptr<X> p2;
+ p2 = static_cast< boost::weak_ptr<X> && >( p );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p2.use_count() == 1 );
+ BOOST_TEST( p.expired() );
+
+ boost::weak_ptr<void> p3;
+ p3 = std::move( p2 );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p3.use_count() == 1 );
+ BOOST_TEST( p2.expired() );
+
+ p_.reset();
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( p3.expired() );
+ }
+
+ {
+ boost::shared_ptr<X> p_( new X );
+ boost::weak_ptr<X> p( p_ );
+ BOOST_TEST( X::instances == 1 );
+ BOOST_TEST( p.use_count() == 1 );
+
+ boost::shared_ptr<X> p_2( new X );
+ boost::weak_ptr<X> p2( p_2 );
+ BOOST_TEST( X::instances == 2 );
+ p2 = std::move( p );
+ BOOST_TEST( X::instances == 2 );
+ BOOST_TEST( p2.use_count() == 1 );
+ BOOST_TEST( p.expired() );
+ BOOST_TEST( p2.lock() != p_2 );
+
+ boost::shared_ptr<void> p_3( new X );
+ boost::weak_ptr<void> p3( p_3 );
+ BOOST_TEST( X::instances == 3 );
+ p3 = std::move( p2 );
+ BOOST_TEST( X::instances == 3 );
+ BOOST_TEST( p3.use_count() == 1 );
+ BOOST_TEST( p2.expired() );
+ BOOST_TEST( p3.lock() != p_3 );
+ }
+
+ return boost::report_errors();
+}
+
+#else // defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+int main()
+{
+ return 0;
+}
+
+#endif
diff --git a/test/weak_ptr_test.cpp b/test/weak_ptr_test.cpp
new file mode 100644
index 0000000..a4ad766
--- /dev/null
+++ b/test/weak_ptr_test.cpp
@@ -0,0 +1,1365 @@
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+
+#pragma warning(disable: 4786) // identifier truncated in debug info
+#pragma warning(disable: 4710) // function not inlined
+#pragma warning(disable: 4711) // function selected for automatic inline expansion
+#pragma warning(disable: 4514) // unreferenced inline removed
+#pragma warning(disable: 4355) // 'this' : used in base member initializer list
+
+#if (BOOST_MSVC >= 1310)
+#pragma warning(disable: 4675) // resolved overload found with Koenig lookup
+#endif
+
+#endif
+
+//
+// weak_ptr_test.cpp
+//
+// Copyright (c) 2002-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/detail/lightweight_test.hpp>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+#include <map>
+#include <vector>
+
+//
+
+namespace n_element_type
+{
+
+void f(int &)
+{
+}
+
+void test()
+{
+ typedef boost::weak_ptr<int>::element_type T;
+ T t;
+ f(t);
+}
+
+} // namespace n_element_type
+
+class incomplete;
+
+boost::shared_ptr<incomplete> create_incomplete();
+
+struct X
+{
+ int dummy;
+};
+
+struct Y
+{
+ int dummy2;
+};
+
+struct Z: public X, public virtual Y
+{
+};
+
+namespace n_constructors
+{
+
+void default_constructor()
+{
+ {
+ boost::weak_ptr<int> wp;
+ BOOST_TEST(wp.use_count() == 0);
+ }
+
+ {
+ boost::weak_ptr<void> wp;
+ BOOST_TEST(wp.use_count() == 0);
+ }
+
+ {
+ boost::weak_ptr<incomplete> wp;
+ BOOST_TEST(wp.use_count() == 0);
+ }
+}
+
+void shared_ptr_constructor()
+{
+ {
+ boost::shared_ptr<int> sp;
+
+ boost::weak_ptr<int> wp(sp);
+ BOOST_TEST(wp.use_count() == sp.use_count());
+
+ boost::weak_ptr<void> wp2(sp);
+ BOOST_TEST(wp2.use_count() == sp.use_count());
+ }
+
+ {
+ boost::shared_ptr<int> sp(static_cast<int*>(0));
+
+ {
+ boost::weak_ptr<int> wp(sp);
+ BOOST_TEST(wp.use_count() == sp.use_count());
+ BOOST_TEST(wp.use_count() == 1);
+ boost::shared_ptr<int> sp2(wp);
+ BOOST_TEST(wp.use_count() == 2);
+ BOOST_TEST(!(sp < sp2 || sp2 < sp));
+ }
+
+ {
+ boost::weak_ptr<void> wp(sp);
+ BOOST_TEST(wp.use_count() == sp.use_count());
+ BOOST_TEST(wp.use_count() == 1);
+ boost::shared_ptr<void> sp2(wp);
+ BOOST_TEST(wp.use_count() == 2);
+ BOOST_TEST(!(sp < sp2 || sp2 < sp));
+ }
+ }
+
+ {
+ boost::shared_ptr<int> sp(new int);
+
+ {
+ boost::weak_ptr<int> wp(sp);
+ BOOST_TEST(wp.use_count() == sp.use_count());
+ BOOST_TEST(wp.use_count() == 1);
+ boost::shared_ptr<int> sp2(wp);
+ BOOST_TEST(wp.use_count() == 2);
+ BOOST_TEST(!(sp < sp2 || sp2 < sp));
+ }
+
+ {
+ boost::weak_ptr<void> wp(sp);
+ BOOST_TEST(wp.use_count() == sp.use_count());
+ BOOST_TEST(wp.use_count() == 1);
+ boost::shared_ptr<void> sp2(wp);
+ BOOST_TEST(wp.use_count() == 2);
+ BOOST_TEST(!(sp < sp2 || sp2 < sp));
+ }
+ }
+
+ {
+ boost::shared_ptr<void> sp;
+
+ boost::weak_ptr<void> wp(sp);
+ BOOST_TEST(wp.use_count() == sp.use_count());
+ }
+
+ {
+ boost::shared_ptr<void> sp(static_cast<int*>(0));
+
+ boost::weak_ptr<void> wp(sp);
+ BOOST_TEST(wp.use_count() == sp.use_count());
+ BOOST_TEST(wp.use_count() == 1);
+ boost::shared_ptr<void> sp2(wp);
+ BOOST_TEST(wp.use_count() == 2);
+ BOOST_TEST(!(sp < sp2 || sp2 < sp));
+ }
+
+ {
+ boost::shared_ptr<void> sp(new int);
+
+ boost::weak_ptr<void> wp(sp);
+ BOOST_TEST(wp.use_count() == sp.use_count());
+ BOOST_TEST(wp.use_count() == 1);
+ boost::shared_ptr<void> sp2(wp);
+ BOOST_TEST(wp.use_count() == 2);
+ BOOST_TEST(!(sp < sp2 || sp2 < sp));
+ }
+
+ {
+ boost::shared_ptr<incomplete> sp;
+
+ boost::weak_ptr<incomplete> wp(sp);
+ BOOST_TEST(wp.use_count() == sp.use_count());
+
+ boost::weak_ptr<void> wp2(sp);
+ BOOST_TEST(wp2.use_count() == sp.use_count());
+ }
+
+ {
+ boost::shared_ptr<incomplete> sp = create_incomplete();
+
+ {
+ boost::weak_ptr<incomplete> wp(sp);
+ BOOST_TEST(wp.use_count() == sp.use_count());
+ BOOST_TEST(wp.use_count() == 1);
+ boost::shared_ptr<incomplete> sp2(wp);
+ BOOST_TEST(wp.use_count() == 2);
+ BOOST_TEST(!(sp < sp2 || sp2 < sp));
+ }
+
+ {
+ boost::weak_ptr<void> wp(sp);
+ BOOST_TEST(wp.use_count() == sp.use_count());
+ BOOST_TEST(wp.use_count() == 1);
+ boost::shared_ptr<void> sp2(wp);
+ BOOST_TEST(wp.use_count() == 2);
+ BOOST_TEST(!(sp < sp2 || sp2 < sp));
+ }
+ }
+
+ {
+ boost::shared_ptr<void> sp = create_incomplete();
+
+ boost::weak_ptr<void> wp(sp);
+ BOOST_TEST(wp.use_count() == sp.use_count());
+ BOOST_TEST(wp.use_count() == 1);
+ boost::shared_ptr<void> sp2(wp);
+ BOOST_TEST(wp.use_count() == 2);
+ BOOST_TEST(!(sp < sp2 || sp2 < sp));
+ }
+}
+
+void copy_constructor()
+{
+ {
+ boost::weak_ptr<int> wp;
+ boost::weak_ptr<int> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 0);
+ }
+
+ {
+ boost::weak_ptr<void> wp;
+ boost::weak_ptr<void> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 0);
+ }
+
+ {
+ boost::weak_ptr<incomplete> wp;
+ boost::weak_ptr<incomplete> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 0);
+ }
+
+ {
+ boost::shared_ptr<int> sp(static_cast<int*>(0));
+ boost::weak_ptr<int> wp(sp);
+
+ boost::weak_ptr<int> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ sp.reset();
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ boost::weak_ptr<int> wp3(wp);
+ BOOST_TEST(wp3.use_count() == wp.use_count());
+ BOOST_TEST(wp3.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ }
+
+ {
+ boost::shared_ptr<int> sp(new int);
+ boost::weak_ptr<int> wp(sp);
+
+ boost::weak_ptr<int> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ sp.reset();
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ boost::weak_ptr<int> wp3(wp);
+ BOOST_TEST(wp3.use_count() == wp.use_count());
+ BOOST_TEST(wp3.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ }
+
+ {
+ boost::shared_ptr<void> sp(static_cast<int*>(0));
+ boost::weak_ptr<void> wp(sp);
+
+ boost::weak_ptr<void> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ sp.reset();
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ boost::weak_ptr<void> wp3(wp);
+ BOOST_TEST(wp3.use_count() == wp.use_count());
+ BOOST_TEST(wp3.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ }
+
+ {
+ boost::shared_ptr<void> sp(new int);
+ boost::weak_ptr<void> wp(sp);
+
+ boost::weak_ptr<void> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ sp.reset();
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ boost::weak_ptr<void> wp3(wp);
+ BOOST_TEST(wp3.use_count() == wp.use_count());
+ BOOST_TEST(wp3.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ }
+
+ {
+ boost::shared_ptr<incomplete> sp = create_incomplete();
+ boost::weak_ptr<incomplete> wp(sp);
+
+ boost::weak_ptr<incomplete> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ sp.reset();
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ boost::weak_ptr<incomplete> wp3(wp);
+ BOOST_TEST(wp3.use_count() == wp.use_count());
+ BOOST_TEST(wp3.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ }
+}
+
+void conversion_constructor()
+{
+ {
+ boost::weak_ptr<int> wp;
+ boost::weak_ptr<void> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 0);
+ }
+
+ {
+ boost::weak_ptr<incomplete> wp;
+ boost::weak_ptr<void> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 0);
+ }
+
+ {
+ boost::weak_ptr<Z> wp;
+
+ boost::weak_ptr<X> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 0);
+
+ boost::weak_ptr<Y> wp3(wp);
+ BOOST_TEST(wp3.use_count() == wp.use_count());
+ BOOST_TEST(wp3.use_count() == 0);
+ }
+
+ {
+ boost::shared_ptr<int> sp(static_cast<int*>(0));
+ boost::weak_ptr<int> wp(sp);
+
+ boost::weak_ptr<void> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ sp.reset();
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ boost::weak_ptr<void> wp3(wp);
+ BOOST_TEST(wp3.use_count() == wp.use_count());
+ BOOST_TEST(wp3.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ }
+
+ {
+ boost::shared_ptr<int> sp(new int);
+ boost::weak_ptr<int> wp(sp);
+
+ boost::weak_ptr<void> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ sp.reset();
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ boost::weak_ptr<void> wp3(wp);
+ BOOST_TEST(wp3.use_count() == wp.use_count());
+ BOOST_TEST(wp3.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ }
+
+ {
+ boost::shared_ptr<incomplete> sp = create_incomplete();
+ boost::weak_ptr<incomplete> wp(sp);
+
+ boost::weak_ptr<void> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ sp.reset();
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ boost::weak_ptr<void> wp3(wp);
+ BOOST_TEST(wp3.use_count() == wp.use_count());
+ BOOST_TEST(wp3.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ }
+
+ {
+ boost::shared_ptr<Z> sp(static_cast<Z*>(0));
+ boost::weak_ptr<Z> wp(sp);
+
+ boost::weak_ptr<X> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ sp.reset();
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ boost::weak_ptr<X> wp3(wp);
+ BOOST_TEST(wp3.use_count() == wp.use_count());
+ BOOST_TEST(wp3.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ }
+
+ {
+ boost::shared_ptr<Z> sp(static_cast<Z*>(0));
+ boost::weak_ptr<Z> wp(sp);
+
+ boost::weak_ptr<Y> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ sp.reset();
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ boost::weak_ptr<Y> wp3(wp);
+ BOOST_TEST(wp3.use_count() == wp.use_count());
+ BOOST_TEST(wp3.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ }
+
+ {
+ boost::shared_ptr<Z> sp(new Z);
+ boost::weak_ptr<Z> wp(sp);
+
+ boost::weak_ptr<X> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ sp.reset();
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ boost::weak_ptr<X> wp3(wp);
+ BOOST_TEST(wp3.use_count() == wp.use_count());
+ BOOST_TEST(wp3.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ }
+
+ {
+ boost::shared_ptr<Z> sp(new Z);
+ boost::weak_ptr<Z> wp(sp);
+
+ boost::weak_ptr<Y> wp2(wp);
+ BOOST_TEST(wp2.use_count() == wp.use_count());
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ sp.reset();
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+
+ boost::weak_ptr<Y> wp3(wp);
+ BOOST_TEST(wp3.use_count() == wp.use_count());
+ BOOST_TEST(wp3.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ }
+}
+
+void test()
+{
+ default_constructor();
+ shared_ptr_constructor();
+ copy_constructor();
+ conversion_constructor();
+}
+
+} // namespace n_constructors
+
+namespace n_assignment
+{
+
+template<class T> void copy_assignment(boost::shared_ptr<T> & sp)
+{
+ BOOST_TEST(sp.unique());
+
+ boost::weak_ptr<T> p1;
+
+ p1 = p1;
+ BOOST_TEST(p1.use_count() == 0);
+
+ boost::weak_ptr<T> p2;
+
+ p1 = p2;
+ BOOST_TEST(p1.use_count() == 0);
+
+ boost::weak_ptr<T> p3(p1);
+
+ p1 = p3;
+ BOOST_TEST(p1.use_count() == 0);
+
+ boost::weak_ptr<T> p4(sp);
+
+ p4 = p4;
+ BOOST_TEST(p4.use_count() == 1);
+
+ p1 = p4;
+ BOOST_TEST(p1.use_count() == 1);
+
+ p4 = p2;
+ BOOST_TEST(p4.use_count() == 0);
+
+ sp.reset();
+
+ p1 = p1;
+ BOOST_TEST(p1.use_count() == 0);
+
+ p4 = p1;
+ BOOST_TEST(p4.use_count() == 0);
+}
+
+void conversion_assignment()
+{
+ {
+ boost::weak_ptr<void> p1;
+
+ boost::weak_ptr<incomplete> p2;
+
+ p1 = p2;
+ BOOST_TEST(p1.use_count() == 0);
+
+ boost::shared_ptr<incomplete> sp = create_incomplete();
+ boost::weak_ptr<incomplete> p3(sp);
+
+ p1 = p3;
+ BOOST_TEST(p1.use_count() == 1);
+
+ sp.reset();
+
+ p1 = p3;
+ BOOST_TEST(p1.use_count() == 0);
+
+ p1 = p2;
+ BOOST_TEST(p1.use_count() == 0);
+ }
+
+ {
+ boost::weak_ptr<X> p1;
+
+ boost::weak_ptr<Z> p2;
+
+ p1 = p2;
+ BOOST_TEST(p1.use_count() == 0);
+
+ boost::shared_ptr<Z> sp(new Z);
+ boost::weak_ptr<Z> p3(sp);
+
+ p1 = p3;
+ BOOST_TEST(p1.use_count() == 1);
+
+ sp.reset();
+
+ p1 = p3;
+ BOOST_TEST(p1.use_count() == 0);
+
+ p1 = p2;
+ BOOST_TEST(p1.use_count() == 0);
+ }
+
+ {
+ boost::weak_ptr<Y> p1;
+
+ boost::weak_ptr<Z> p2;
+
+ p1 = p2;
+ BOOST_TEST(p1.use_count() == 0);
+
+ boost::shared_ptr<Z> sp(new Z);
+ boost::weak_ptr<Z> p3(sp);
+
+ p1 = p3;
+ BOOST_TEST(p1.use_count() == 1);
+
+ sp.reset();
+
+ p1 = p3;
+ BOOST_TEST(p1.use_count() == 0);
+
+ p1 = p2;
+ BOOST_TEST(p1.use_count() == 0);
+ }
+}
+
+template<class T, class U> void shared_ptr_assignment(boost::shared_ptr<U> & sp, T * = 0)
+{
+ BOOST_TEST(sp.unique());
+
+ boost::weak_ptr<T> p1;
+ boost::weak_ptr<T> p2(p1);
+ boost::weak_ptr<T> p3(sp);
+ boost::weak_ptr<T> p4(p3);
+
+ p1 = sp;
+ BOOST_TEST(p1.use_count() == 1);
+
+ p2 = sp;
+ BOOST_TEST(p2.use_count() == 1);
+
+ p3 = sp;
+ BOOST_TEST(p3.use_count() == 1);
+
+ p4 = sp;
+ BOOST_TEST(p4.use_count() == 1);
+
+ sp.reset();
+
+ BOOST_TEST(p1.use_count() == 0);
+ BOOST_TEST(p2.use_count() == 0);
+ BOOST_TEST(p3.use_count() == 0);
+ BOOST_TEST(p4.use_count() == 0);
+
+ p1 = sp;
+}
+
+void test()
+{
+ {
+ boost::shared_ptr<int> p( new int );
+ copy_assignment( p );
+ }
+
+ {
+ boost::shared_ptr<X> p( new X );
+ copy_assignment( p );
+ }
+
+ {
+ boost::shared_ptr<void> p( new int );
+ copy_assignment( p );
+ }
+
+ {
+ boost::shared_ptr<incomplete> p = create_incomplete();
+ copy_assignment( p );
+ }
+
+ conversion_assignment();
+
+ {
+ boost::shared_ptr<int> p( new int );
+ shared_ptr_assignment<int>( p );
+ }
+
+ {
+ boost::shared_ptr<int> p( new int );
+ shared_ptr_assignment<void>( p );
+ }
+
+ {
+ boost::shared_ptr<X> p( new X );
+ shared_ptr_assignment<X>( p );
+ }
+
+ {
+ boost::shared_ptr<X> p( new X );
+ shared_ptr_assignment<void>( p );
+ }
+
+ {
+ boost::shared_ptr<void> p( new int );
+ shared_ptr_assignment<void>( p );
+ }
+
+ {
+ boost::shared_ptr<incomplete> p = create_incomplete();
+ shared_ptr_assignment<incomplete>( p );
+ }
+
+ {
+ boost::shared_ptr<incomplete> p = create_incomplete();
+ shared_ptr_assignment<void>( p );
+ }
+}
+
+} // namespace n_assignment
+
+namespace n_reset
+{
+
+template<class T, class U> void test2( boost::shared_ptr<U> & sp, T * = 0 )
+{
+ BOOST_TEST(sp.unique());
+
+ boost::weak_ptr<T> p1;
+ boost::weak_ptr<T> p2(p1);
+ boost::weak_ptr<T> p3(sp);
+ boost::weak_ptr<T> p4(p3);
+ boost::weak_ptr<T> p5(sp);
+ boost::weak_ptr<T> p6(p5);
+
+ p1.reset();
+ BOOST_TEST(p1.use_count() == 0);
+
+ p2.reset();
+ BOOST_TEST(p2.use_count() == 0);
+
+ p3.reset();
+ BOOST_TEST(p3.use_count() == 0);
+
+ p4.reset();
+ BOOST_TEST(p4.use_count() == 0);
+
+ sp.reset();
+
+ p5.reset();
+ BOOST_TEST(p5.use_count() == 0);
+
+ p6.reset();
+ BOOST_TEST(p6.use_count() == 0);
+}
+
+void test()
+{
+ {
+ boost::shared_ptr<int> p( new int );
+ test2<int>( p );
+ }
+
+ {
+ boost::shared_ptr<int> p( new int );
+ test2<void>( p );
+ }
+
+ {
+ boost::shared_ptr<X> p( new X );
+ test2<X>( p );
+ }
+
+ {
+ boost::shared_ptr<X> p( new X );
+ test2<void>( p );
+ }
+
+ {
+ boost::shared_ptr<void> p( new int );
+ test2<void>( p );
+ }
+
+ {
+ boost::shared_ptr<incomplete> p = create_incomplete();
+ test2<incomplete>( p );
+ }
+
+ {
+ boost::shared_ptr<incomplete> p = create_incomplete();
+ test2<void>( p );
+ }
+}
+
+} // namespace n_reset
+
+namespace n_use_count
+{
+
+void test()
+{
+ {
+ boost::weak_ptr<X> wp;
+ BOOST_TEST(wp.use_count() == 0);
+ BOOST_TEST(wp.expired());
+
+ boost::weak_ptr<X> wp2;
+ BOOST_TEST(wp.use_count() == 0);
+ BOOST_TEST(wp.expired());
+
+ boost::weak_ptr<X> wp3(wp);
+ BOOST_TEST(wp.use_count() == 0);
+ BOOST_TEST(wp.expired());
+ BOOST_TEST(wp3.use_count() == 0);
+ BOOST_TEST(wp3.expired());
+ }
+
+ {
+ boost::shared_ptr<X> sp(static_cast<X*>(0));
+
+ boost::weak_ptr<X> wp(sp);
+ BOOST_TEST(wp.use_count() == 1);
+ BOOST_TEST(!wp.expired());
+
+ boost::weak_ptr<X> wp2(sp);
+ BOOST_TEST(wp.use_count() == 1);
+ BOOST_TEST(!wp.expired());
+
+ boost::weak_ptr<X> wp3(wp);
+ BOOST_TEST(wp.use_count() == 1);
+ BOOST_TEST(!wp.expired());
+ BOOST_TEST(wp3.use_count() == 1);
+ BOOST_TEST(!wp3.expired());
+
+ boost::shared_ptr<X> sp2(sp);
+
+ BOOST_TEST(wp.use_count() == 2);
+ BOOST_TEST(!wp.expired());
+ BOOST_TEST(wp2.use_count() == 2);
+ BOOST_TEST(!wp2.expired());
+ BOOST_TEST(wp3.use_count() == 2);
+ BOOST_TEST(!wp3.expired());
+
+ boost::shared_ptr<void> sp3(sp);
+
+ BOOST_TEST(wp.use_count() == 3);
+ BOOST_TEST(!wp.expired());
+ BOOST_TEST(wp2.use_count() == 3);
+ BOOST_TEST(!wp2.expired());
+ BOOST_TEST(wp3.use_count() == 3);
+ BOOST_TEST(!wp3.expired());
+
+ sp.reset();
+
+ BOOST_TEST(wp.use_count() == 2);
+ BOOST_TEST(!wp.expired());
+ BOOST_TEST(wp2.use_count() == 2);
+ BOOST_TEST(!wp2.expired());
+ BOOST_TEST(wp3.use_count() == 2);
+ BOOST_TEST(!wp3.expired());
+
+ sp2.reset();
+
+ BOOST_TEST(wp.use_count() == 1);
+ BOOST_TEST(!wp.expired());
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!wp2.expired());
+ BOOST_TEST(wp3.use_count() == 1);
+ BOOST_TEST(!wp3.expired());
+
+ sp3.reset();
+
+ BOOST_TEST(wp.use_count() == 0);
+ BOOST_TEST(wp.expired());
+ BOOST_TEST(wp2.use_count() == 0);
+ BOOST_TEST(wp2.expired());
+ BOOST_TEST(wp3.use_count() == 0);
+ BOOST_TEST(wp3.expired());
+ }
+}
+
+} // namespace n_use_count
+
+namespace n_swap
+{
+
+void test()
+{
+ {
+ boost::weak_ptr<X> wp;
+ boost::weak_ptr<X> wp2;
+
+ wp.swap(wp2);
+
+ BOOST_TEST(wp.use_count() == 0);
+ BOOST_TEST(wp2.use_count() == 0);
+
+ using std::swap;
+ swap(wp, wp2);
+
+ BOOST_TEST(wp.use_count() == 0);
+ BOOST_TEST(wp2.use_count() == 0);
+ }
+
+ {
+ boost::shared_ptr<X> sp(new X);
+ boost::weak_ptr<X> wp;
+ boost::weak_ptr<X> wp2(sp);
+ boost::weak_ptr<X> wp3(sp);
+
+ wp.swap(wp2);
+
+ BOOST_TEST(wp.use_count() == 1);
+ BOOST_TEST(wp2.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+
+ using std::swap;
+ swap(wp, wp2);
+
+ BOOST_TEST(wp.use_count() == 0);
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp2 < wp3 || wp3 < wp2));
+
+ sp.reset();
+
+ wp.swap(wp2);
+
+ BOOST_TEST(wp.use_count() == 0);
+ BOOST_TEST(wp2.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+
+ swap(wp, wp2);
+
+ BOOST_TEST(wp.use_count() == 0);
+ BOOST_TEST(wp2.use_count() == 0);
+ BOOST_TEST(!(wp2 < wp3 || wp3 < wp2));
+ }
+
+ {
+ boost::shared_ptr<X> sp(new X);
+ boost::shared_ptr<X> sp2(new X);
+ boost::weak_ptr<X> wp(sp);
+ boost::weak_ptr<X> wp2(sp2);
+ boost::weak_ptr<X> wp3(sp2);
+
+ wp.swap(wp2);
+
+ BOOST_TEST(wp.use_count() == 1);
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+
+ using std::swap;
+ swap(wp, wp2);
+
+ BOOST_TEST(wp.use_count() == 1);
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp2 < wp3 || wp3 < wp2));
+
+ sp.reset();
+
+ wp.swap(wp2);
+
+ BOOST_TEST(wp.use_count() == 1);
+ BOOST_TEST(wp2.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+
+ swap(wp, wp2);
+
+ BOOST_TEST(wp.use_count() == 0);
+ BOOST_TEST(wp2.use_count() == 1);
+ BOOST_TEST(!(wp2 < wp3 || wp3 < wp2));
+
+ sp2.reset();
+
+ wp.swap(wp2);
+
+ BOOST_TEST(wp.use_count() == 0);
+ BOOST_TEST(wp2.use_count() == 0);
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+
+ swap(wp, wp2);
+
+ BOOST_TEST(wp.use_count() == 0);
+ BOOST_TEST(wp2.use_count() == 0);
+ BOOST_TEST(!(wp2 < wp3 || wp3 < wp2));
+ }
+}
+
+} // namespace n_swap
+
+namespace n_comparison
+{
+
+void test()
+{
+ {
+ boost::weak_ptr<X> wp;
+ BOOST_TEST(!(wp < wp));
+
+ boost::weak_ptr<X> wp2;
+ BOOST_TEST(!(wp < wp2 && wp2 < wp));
+
+ boost::weak_ptr<X> wp3(wp);
+ BOOST_TEST(!(wp3 < wp3));
+ BOOST_TEST(!(wp < wp3 && wp3 < wp));
+ }
+
+ {
+ boost::shared_ptr<X> sp(new X);
+
+ boost::weak_ptr<X> wp(sp);
+ BOOST_TEST(!(wp < wp));
+
+ boost::weak_ptr<X> wp2;
+ BOOST_TEST(wp < wp2 || wp2 < wp);
+ BOOST_TEST(!(wp < wp2 && wp2 < wp));
+
+ bool b1 = wp < wp2;
+ bool b2 = wp2 < wp;
+
+ {
+ boost::weak_ptr<X> wp3(wp);
+
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ BOOST_TEST(!(wp < wp3 && wp3 < wp));
+
+ BOOST_TEST(wp2 < wp3 || wp3 < wp2);
+ BOOST_TEST(!(wp2 < wp3 && wp3 < wp2));
+
+ boost::weak_ptr<X> wp4(wp2);
+
+ BOOST_TEST(wp4 < wp3 || wp3 < wp4);
+ BOOST_TEST(!(wp4 < wp3 && wp3 < wp4));
+ }
+
+ sp.reset();
+
+ BOOST_TEST(b1 == (wp < wp2));
+ BOOST_TEST(b2 == (wp2 < wp));
+
+ {
+ boost::weak_ptr<X> wp3(wp);
+
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ BOOST_TEST(!(wp < wp3 && wp3 < wp));
+
+ BOOST_TEST(wp2 < wp3 || wp3 < wp2);
+ BOOST_TEST(!(wp2 < wp3 && wp3 < wp2));
+
+ boost::weak_ptr<X> wp4(wp2);
+
+ BOOST_TEST(wp4 < wp3 || wp3 < wp4);
+ BOOST_TEST(!(wp4 < wp3 && wp3 < wp4));
+ }
+ }
+
+ {
+ boost::shared_ptr<X> sp(new X);
+ boost::shared_ptr<X> sp2(new X);
+
+ boost::weak_ptr<X> wp(sp);
+ boost::weak_ptr<X> wp2(sp2);
+
+ BOOST_TEST(wp < wp2 || wp2 < wp);
+ BOOST_TEST(!(wp < wp2 && wp2 < wp));
+
+ bool b1 = wp < wp2;
+ bool b2 = wp2 < wp;
+
+ {
+ boost::weak_ptr<X> wp3(wp);
+
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ BOOST_TEST(!(wp < wp3 && wp3 < wp));
+
+ BOOST_TEST(wp2 < wp3 || wp3 < wp2);
+ BOOST_TEST(!(wp2 < wp3 && wp3 < wp2));
+
+ boost::weak_ptr<X> wp4(wp2);
+
+ BOOST_TEST(wp4 < wp3 || wp3 < wp4);
+ BOOST_TEST(!(wp4 < wp3 && wp3 < wp4));
+ }
+
+ sp.reset();
+
+ BOOST_TEST(b1 == (wp < wp2));
+ BOOST_TEST(b2 == (wp2 < wp));
+
+ {
+ boost::weak_ptr<X> wp3(wp);
+
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ BOOST_TEST(!(wp < wp3 && wp3 < wp));
+
+ BOOST_TEST(wp2 < wp3 || wp3 < wp2);
+ BOOST_TEST(!(wp2 < wp3 && wp3 < wp2));
+
+ boost::weak_ptr<X> wp4(wp2);
+
+ BOOST_TEST(wp4 < wp3 || wp3 < wp4);
+ BOOST_TEST(!(wp4 < wp3 && wp3 < wp4));
+ }
+
+ sp2.reset();
+
+ BOOST_TEST(b1 == (wp < wp2));
+ BOOST_TEST(b2 == (wp2 < wp));
+
+ {
+ boost::weak_ptr<X> wp3(wp);
+
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ BOOST_TEST(!(wp < wp3 && wp3 < wp));
+
+ BOOST_TEST(wp2 < wp3 || wp3 < wp2);
+ BOOST_TEST(!(wp2 < wp3 && wp3 < wp2));
+
+ boost::weak_ptr<X> wp4(wp2);
+
+ BOOST_TEST(wp4 < wp3 || wp3 < wp4);
+ BOOST_TEST(!(wp4 < wp3 && wp3 < wp4));
+ }
+ }
+
+ {
+ boost::shared_ptr<X> sp(new X);
+ boost::shared_ptr<X> sp2(sp);
+
+ boost::weak_ptr<X> wp(sp);
+ boost::weak_ptr<X> wp2(sp2);
+
+ BOOST_TEST(!(wp < wp2 || wp2 < wp));
+ BOOST_TEST(!(wp < wp2 && wp2 < wp));
+
+ bool b1 = wp < wp2;
+ bool b2 = wp2 < wp;
+
+ {
+ boost::weak_ptr<X> wp3(wp);
+
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ BOOST_TEST(!(wp < wp3 && wp3 < wp));
+
+ BOOST_TEST(!(wp2 < wp3 || wp3 < wp2));
+ BOOST_TEST(!(wp2 < wp3 && wp3 < wp2));
+
+ boost::weak_ptr<X> wp4(wp2);
+
+ BOOST_TEST(!(wp4 < wp3 || wp3 < wp4));
+ BOOST_TEST(!(wp4 < wp3 && wp3 < wp4));
+ }
+
+ sp.reset();
+ sp2.reset();
+
+ BOOST_TEST(b1 == (wp < wp2));
+ BOOST_TEST(b2 == (wp2 < wp));
+
+ {
+ boost::weak_ptr<X> wp3(wp);
+
+ BOOST_TEST(!(wp < wp3 || wp3 < wp));
+ BOOST_TEST(!(wp < wp3 && wp3 < wp));
+
+ BOOST_TEST(!(wp2 < wp3 || wp3 < wp2));
+ BOOST_TEST(!(wp2 < wp3 && wp3 < wp2));
+
+ boost::weak_ptr<X> wp4(wp2);
+
+ BOOST_TEST(!(wp4 < wp3 || wp3 < wp4));
+ BOOST_TEST(!(wp4 < wp3 && wp3 < wp4));
+ }
+ }
+
+ {
+ boost::shared_ptr<X> spx(new X);
+ boost::shared_ptr<Y> spy(new Y);
+ boost::shared_ptr<Z> spz(new Z);
+
+ boost::weak_ptr<X> px(spx);
+ boost::weak_ptr<Y> py(spy);
+ boost::weak_ptr<Z> pz(spz);
+
+ BOOST_TEST(px < py || py < px);
+ BOOST_TEST(px < pz || pz < px);
+ BOOST_TEST(py < pz || pz < py);
+
+ BOOST_TEST(!(px < py && py < px));
+ BOOST_TEST(!(px < pz && pz < px));
+ BOOST_TEST(!(py < pz && pz < py));
+
+ boost::weak_ptr<void> pvx(px);
+ BOOST_TEST(!(pvx < pvx));
+
+ boost::weak_ptr<void> pvy(py);
+ BOOST_TEST(!(pvy < pvy));
+
+ boost::weak_ptr<void> pvz(pz);
+ BOOST_TEST(!(pvz < pvz));
+
+ BOOST_TEST(pvx < pvy || pvy < pvx);
+ BOOST_TEST(pvx < pvz || pvz < pvx);
+ BOOST_TEST(pvy < pvz || pvz < pvy);
+
+ BOOST_TEST(!(pvx < pvy && pvy < pvx));
+ BOOST_TEST(!(pvx < pvz && pvz < pvx));
+ BOOST_TEST(!(pvy < pvz && pvz < pvy));
+
+ spx.reset();
+ spy.reset();
+ spz.reset();
+
+ BOOST_TEST(px < py || py < px);
+ BOOST_TEST(px < pz || pz < px);
+ BOOST_TEST(py < pz || pz < py);
+
+ BOOST_TEST(!(px < py && py < px));
+ BOOST_TEST(!(px < pz && pz < px));
+ BOOST_TEST(!(py < pz && pz < py));
+
+ BOOST_TEST(!(pvx < pvx));
+ BOOST_TEST(!(pvy < pvy));
+ BOOST_TEST(!(pvz < pvz));
+
+ BOOST_TEST(pvx < pvy || pvy < pvx);
+ BOOST_TEST(pvx < pvz || pvz < pvx);
+ BOOST_TEST(pvy < pvz || pvz < pvy);
+
+ BOOST_TEST(!(pvx < pvy && pvy < pvx));
+ BOOST_TEST(!(pvx < pvz && pvz < pvx));
+ BOOST_TEST(!(pvy < pvz && pvz < pvy));
+ }
+
+ {
+ boost::shared_ptr<Z> spz(new Z);
+ boost::shared_ptr<X> spx(spz);
+
+ boost::weak_ptr<Z> pz(spz);
+ boost::weak_ptr<X> px(spx);
+ boost::weak_ptr<Y> py(spz);
+
+ BOOST_TEST(!(px < px));
+ BOOST_TEST(!(py < py));
+
+ BOOST_TEST(!(px < py || py < px));
+ BOOST_TEST(!(px < pz || pz < px));
+ BOOST_TEST(!(py < pz || pz < py));
+
+ boost::weak_ptr<void> pvx(px);
+ boost::weak_ptr<void> pvy(py);
+ boost::weak_ptr<void> pvz(pz);
+
+ BOOST_TEST(!(pvx < pvy || pvy < pvx));
+ BOOST_TEST(!(pvx < pvz || pvz < pvx));
+ BOOST_TEST(!(pvy < pvz || pvz < pvy));
+
+ spx.reset();
+ spz.reset();
+
+ BOOST_TEST(!(px < px));
+ BOOST_TEST(!(py < py));
+
+ BOOST_TEST(!(px < py || py < px));
+ BOOST_TEST(!(px < pz || pz < px));
+ BOOST_TEST(!(py < pz || pz < py));
+
+ BOOST_TEST(!(pvx < pvy || pvy < pvx));
+ BOOST_TEST(!(pvx < pvz || pvz < pvx));
+ BOOST_TEST(!(pvy < pvz || pvz < pvy));
+ }
+}
+
+} // namespace n_comparison
+
+namespace n_lock
+{
+
+void test()
+{
+}
+
+} // namespace n_lock
+
+namespace n_map
+{
+
+void test()
+{
+ std::vector< boost::shared_ptr<int> > vi;
+
+ {
+ boost::shared_ptr<int> pi1(new int);
+ boost::shared_ptr<int> pi2(new int);
+ boost::shared_ptr<int> pi3(new int);
+
+ vi.push_back(pi1);
+ vi.push_back(pi1);
+ vi.push_back(pi1);
+ vi.push_back(pi2);
+ vi.push_back(pi1);
+ vi.push_back(pi2);
+ vi.push_back(pi1);
+ vi.push_back(pi3);
+ vi.push_back(pi3);
+ vi.push_back(pi2);
+ vi.push_back(pi1);
+ }
+
+ std::vector< boost::shared_ptr<X> > vx;
+
+ {
+ boost::shared_ptr<X> px1(new X);
+ boost::shared_ptr<X> px2(new X);
+ boost::shared_ptr<X> px3(new X);
+
+ vx.push_back(px2);
+ vx.push_back(px2);
+ vx.push_back(px1);
+ vx.push_back(px2);
+ vx.push_back(px1);
+ vx.push_back(px1);
+ vx.push_back(px1);
+ vx.push_back(px2);
+ vx.push_back(px1);
+ vx.push_back(px3);
+ vx.push_back(px2);
+ }
+
+ std::map< boost::weak_ptr<void>, long > m;
+
+ {
+ for(std::vector< boost::shared_ptr<int> >::iterator i = vi.begin(); i != vi.end(); ++i)
+ {
+ ++m[*i];
+ }
+ }
+
+ {
+ for(std::vector< boost::shared_ptr<X> >::iterator i = vx.begin(); i != vx.end(); ++i)
+ {
+ ++m[*i];
+ }
+ }
+
+ {
+ for(std::map< boost::weak_ptr<void>, long >::iterator i = m.begin(); i != m.end(); ++i)
+ {
+ BOOST_TEST(i->first.use_count() == i->second);
+ }
+ }
+}
+
+} // namespace n_map
+
+int main()
+{
+ n_element_type::test();
+ n_constructors::test();
+ n_assignment::test();
+ n_reset::test();
+ n_use_count::test();
+ n_swap::test();
+ n_comparison::test();
+ n_lock::test();
+
+ n_map::test();
+
+ return boost::report_errors();
+}
+
+class incomplete
+{
+};
+
+boost::shared_ptr<incomplete> create_incomplete()
+{
+ boost::shared_ptr<incomplete> px(new incomplete);
+ return px;
+}
diff --git a/test/wp_convertible_test.cpp b/test/wp_convertible_test.cpp
new file mode 100644
index 0000000..cceacda
--- /dev/null
+++ b/test/wp_convertible_test.cpp
@@ -0,0 +1,68 @@
+#include <boost/config.hpp>
+
+// wp_convertible_test.cpp
+//
+// Copyright (c) 2008 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
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/weak_ptr.hpp>
+
+//
+
+class incomplete;
+
+struct X
+{
+};
+
+struct Y
+{
+};
+
+struct Z: public X
+{
+};
+
+int f( boost::weak_ptr<void const> )
+{
+ return 1;
+}
+
+int f( boost::weak_ptr<int> )
+{
+ return 2;
+}
+
+int f( boost::weak_ptr<incomplete> )
+{
+ return 3;
+}
+
+int g( boost::weak_ptr<X> )
+{
+ return 4;
+}
+
+int g( boost::weak_ptr<Y> )
+{
+ return 5;
+}
+
+int g( boost::weak_ptr<incomplete> )
+{
+ return 6;
+}
+
+int main()
+{
+ BOOST_TEST( 1 == f( boost::weak_ptr<double>() ) );
+ BOOST_TEST( 1 == f( boost::shared_ptr<double>() ) );
+ BOOST_TEST( 4 == g( boost::weak_ptr<Z>() ) );
+ BOOST_TEST( 4 == g( boost::shared_ptr<Z>() ) );
+
+ return boost::report_errors();
+}
diff --git a/test/yield_k_test.cpp b/test/yield_k_test.cpp
new file mode 100644
index 0000000..593c13d
--- /dev/null
+++ b/test/yield_k_test.cpp
@@ -0,0 +1,23 @@
+//
+// yield_k_test.cpp
+//
+// Copyright 2008 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)
+//
+
+#include <boost/smart_ptr/detail/yield_k.hpp>
+
+// Sanity check only
+
+int main()
+{
+ for( unsigned k = 0; k < 256; ++k )
+ {
+ boost::detail::yield( k );
+ }
+
+ return 0;
+}
diff --git a/test/yield_k_windows_h_test.cpp b/test/yield_k_windows_h_test.cpp
new file mode 100644
index 0000000..c2f88b8
--- /dev/null
+++ b/test/yield_k_windows_h_test.cpp
@@ -0,0 +1,11 @@
+// Copyright 2018 Peter Dimov
+// Distributed under the Boost Software License, Version 1.0.
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# include <windows.h>
+# include <boost/smart_ptr/detail/yield_k.hpp>
+#endif
+
+int main()
+{
+}