forked from boostorg/smart_ptr
Compare commits
20 Commits
boost-1.70
...
feature/we
Author | SHA1 | Date | |
---|---|---|---|
|
b6b49ef591 | ||
|
2122c7753c | ||
|
7c76fb385d | ||
|
372fac679b | ||
|
e3adcaed1e | ||
|
016e682af6 | ||
|
78e095d761 | ||
|
eb8a91cb46 | ||
|
513cd15378 | ||
|
7bfa6a1f3d | ||
|
8120bb44cb | ||
|
18974ea2db | ||
|
2a4aca403a | ||
|
4d0d81477c | ||
|
1725e26f70 | ||
|
47fffaf11c | ||
|
7f0323a347 | ||
|
6d8ea0f0c4 | ||
|
d10299159a | ||
|
adcab0e313 |
12
.travis.yml
12
.travis.yml
@@ -107,7 +107,17 @@ matrix:
|
|||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: g++-8
|
compiler: g++-8
|
||||||
env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=03,11,14,17,2a
|
env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=03,11,14
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- g++-8
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: g++-8
|
||||||
|
env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=17,2a
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages:
|
packages:
|
||||||
|
18
appveyor.yml
18
appveyor.yml
@@ -1,4 +1,4 @@
|
|||||||
# Copyright 2016-2018 Peter Dimov
|
# Copyright 2016-2019 Peter Dimov
|
||||||
# Distributed under the Boost Software License, Version 1.0.
|
# 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)
|
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
@@ -14,28 +14,28 @@ branches:
|
|||||||
|
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
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
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
TOOLSET: msvc-14.0
|
TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
|
||||||
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
|
TOOLSET: msvc-12.0,msvc-14.0
|
||||||
ADDRMD: 32,64
|
ADDRMD: 32,64
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
TOOLSET: msvc-14.1
|
TOOLSET: msvc-14.1,clang-win
|
||||||
CXXSTD: 14,17
|
CXXSTD: 14,17
|
||||||
ADDRMD: 32,64
|
ADDRMD: 32,64
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
ADDPATH: C:\cygwin\bin;
|
ADDPATH: C:\cygwin\bin;
|
||||||
TOOLSET: gcc
|
TOOLSET: gcc
|
||||||
CXXSTD: 03,11,14,1z
|
CXXSTD: 03,11,14,1z
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
ADDPATH: C:\cygwin64\bin;
|
ADDPATH: C:\cygwin64\bin;
|
||||||
TOOLSET: gcc
|
TOOLSET: gcc
|
||||||
CXXSTD: 03,11,14,1z
|
CXXSTD: 03,11,14,1z
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
ADDPATH: C:\mingw\bin;
|
ADDPATH: C:\mingw\bin;
|
||||||
TOOLSET: gcc
|
TOOLSET: gcc
|
||||||
CXXSTD: 03,11,14,1z
|
CXXSTD: 03,11,14,1z
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
ADDPATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;
|
ADDPATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;
|
||||||
TOOLSET: gcc
|
TOOLSET: gcc
|
||||||
CXXSTD: 03,11,14,1z
|
CXXSTD: 03,11,14,1z
|
||||||
|
@@ -5,8 +5,6 @@
|
|||||||
# See accompanying file LICENSE_1_0.txt or copy at
|
# See accompanying file LICENSE_1_0.txt or copy at
|
||||||
# http://www.boost.org/LICENSE_1_0.txt
|
# http://www.boost.org/LICENSE_1_0.txt
|
||||||
|
|
||||||
project doc/smart_ptr ;
|
|
||||||
|
|
||||||
import asciidoctor ;
|
import asciidoctor ;
|
||||||
|
|
||||||
html smart_ptr.html : smart_ptr.adoc ;
|
html smart_ptr.html : smart_ptr.adoc ;
|
||||||
|
@@ -19,6 +19,8 @@ Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes
|
|||||||
|
|
||||||
include::smart_ptr/introduction.adoc[]
|
include::smart_ptr/introduction.adoc[]
|
||||||
|
|
||||||
|
include::smart_ptr/changelog.adoc[]
|
||||||
|
|
||||||
include::smart_ptr/scoped_ptr.adoc[]
|
include::smart_ptr/scoped_ptr.adoc[]
|
||||||
|
|
||||||
include::smart_ptr/scoped_array.adoc[]
|
include::smart_ptr/scoped_array.adoc[]
|
||||||
|
19
doc/smart_ptr/changelog.adoc
Normal file
19
doc/smart_ptr/changelog.adoc
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
////
|
||||||
|
Copyright 2019 Peter Dimov
|
||||||
|
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
|
||||||
|
See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt
|
||||||
|
////
|
||||||
|
|
||||||
|
[#changelog]
|
||||||
|
# Revision History
|
||||||
|
:toc:
|
||||||
|
:toc-title:
|
||||||
|
:idprefix: changelog_
|
||||||
|
|
||||||
|
## Changes in 1.71.0
|
||||||
|
|
||||||
|
* Added aliasing constructors to `weak_ptr`
|
||||||
|
* Added `weak_ptr<T>::empty()`
|
@@ -11,7 +11,9 @@ http://www.boost.org/LICENSE_1_0.txt
|
|||||||
|
|
||||||
[#introduction]
|
[#introduction]
|
||||||
# Introduction
|
# Introduction
|
||||||
:idprefix: intro
|
:toc:
|
||||||
|
:toc-title:
|
||||||
|
:idprefix: intro_
|
||||||
|
|
||||||
Smart pointers are objects which store pointers to dynamically allocated (heap) objects.
|
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
|
They behave much like built-in {cpp} pointers except that they automatically delete the object
|
||||||
|
@@ -77,7 +77,7 @@ namespace boost {
|
|||||||
|
|
||||||
explicit operator bool () const noexcept;
|
explicit operator bool () const noexcept;
|
||||||
|
|
||||||
void swap(intrusive_ptr & b) noexept;
|
void swap(intrusive_ptr & b) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T, class U>
|
template<class T, class U>
|
||||||
|
@@ -78,12 +78,13 @@ namespace boost {
|
|||||||
```
|
```
|
||||||
intrusive_ref_counter() noexcept;
|
intrusive_ref_counter() noexcept;
|
||||||
```
|
```
|
||||||
::
|
|
||||||
```
|
```
|
||||||
intrusive_ref_counter(const intrusive_ref_counter&) noexcept;
|
intrusive_ref_counter(const intrusive_ref_counter&) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Postconditions::: `use_count() == 0`.
|
* {blank}
|
||||||
|
+
|
||||||
|
Postconditions:: `use_count() == 0`.
|
||||||
|
|
||||||
NOTE: The pointer to the constructed object is expected to be passed to
|
NOTE: The pointer to the constructed object is expected to be passed to
|
||||||
`intrusive_ptr` constructor, assignment operator or `reset` method, which
|
`intrusive_ptr` constructor, assignment operator or `reset` method, which
|
||||||
@@ -94,8 +95,10 @@ would increment the reference counter.
|
|||||||
```
|
```
|
||||||
~intrusive_ref_counter();
|
~intrusive_ref_counter();
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Effects::: Destroys the counter object.
|
* {blank}
|
||||||
|
+
|
||||||
|
Effects:: Destroys the counter object.
|
||||||
|
|
||||||
NOTE: The destructor is protected so that the object can only be destroyed
|
NOTE: The destructor is protected so that the object can only be destroyed
|
||||||
through the `Derived` class.
|
through the `Derived` class.
|
||||||
@@ -105,16 +108,20 @@ through the `Derived` class.
|
|||||||
```
|
```
|
||||||
intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept;
|
intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Effects::: Does nothing, reference counter is not modified.
|
* {blank}
|
||||||
|
+
|
||||||
|
Effects:: Does nothing, reference counter is not modified.
|
||||||
|
|
||||||
### use_count
|
### use_count
|
||||||
|
|
||||||
```
|
```
|
||||||
unsigned int use_count() const noexcept;
|
unsigned int use_count() const noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: The current value of the reference counter.
|
* {blank}
|
||||||
|
+
|
||||||
|
Returns:: The current value of the reference counter.
|
||||||
|
|
||||||
NOTE: The returned value may not be actual in multi-threaded applications.
|
NOTE: The returned value may not be actual in multi-threaded applications.
|
||||||
|
|
||||||
@@ -127,8 +134,10 @@ template<class Derived, class CounterPolicy>
|
|||||||
void intrusive_ptr_add_ref(
|
void intrusive_ptr_add_ref(
|
||||||
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
|
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Effects::: Increments the reference counter.
|
* {blank}
|
||||||
|
+
|
||||||
|
Effects:: Increments the reference counter.
|
||||||
|
|
||||||
### intrusive_ptr_release
|
### intrusive_ptr_release
|
||||||
|
|
||||||
@@ -137,6 +146,8 @@ template<class Derived, class CounterPolicy>
|
|||||||
void intrusive_ptr_release(
|
void intrusive_ptr_release(
|
||||||
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
|
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Effects::: Decrements the reference counter. If the reference counter reaches
|
* {blank}
|
||||||
|
+
|
||||||
|
Effects:: Decrements the reference counter. If the reference counter reaches
|
||||||
0, calls `delete static_cast<const Derived*>(p)`.
|
0, calls `delete static_cast<const Derived*>(p)`.
|
||||||
|
@@ -716,4 +716,3 @@ template<class D, class T>
|
|||||||
* {blank}
|
* {blank}
|
||||||
+
|
+
|
||||||
Returns:: If `*this` owns a `shared_ptr` instance `p`, `get_deleter<D>( p )`, otherwise 0.
|
Returns:: If `*this` owns a `shared_ptr` instance `p`, `get_deleter<D>( p )`, otherwise 0.
|
||||||
|
|
||||||
|
@@ -174,17 +174,18 @@ the reference counts.
|
|||||||
template<class T, class... Args>
|
template<class T, class... Args>
|
||||||
shared_ptr<T> make_shared(Args&&... args);
|
shared_ptr<T> make_shared(Args&&... args);
|
||||||
```
|
```
|
||||||
::
|
|
||||||
```
|
```
|
||||||
template<class T, class A, class... Args>
|
template<class T, class A, class... Args>
|
||||||
shared_ptr<T> allocate_shared(const A& a, Args&&... args);
|
shared_ptr<T> allocate_shared(const A& a, Args&&... args);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Remarks::: These overloads shall only participate in overload resolution when
|
* {blank}
|
||||||
|
+
|
||||||
|
Remarks:: These overloads shall only participate in overload resolution when
|
||||||
`T` is not an array type.
|
`T` is not an array type.
|
||||||
Returns::: A `shared_ptr` to an object of type `T`, constructed from
|
Returns:: A `shared_ptr` to an object of type `T`, constructed from
|
||||||
`args\...`.
|
`args\...`.
|
||||||
Examples:::
|
Examples::
|
||||||
* `auto p = make_shared<int>();`
|
* `auto p = make_shared<int>();`
|
||||||
* `auto p = make_shared<std::vector<int> >(16, 1);`
|
* `auto p = make_shared<std::vector<int> >(16, 1);`
|
||||||
|
|
||||||
@@ -192,17 +193,18 @@ Examples:::
|
|||||||
template<class T>
|
template<class T>
|
||||||
shared_ptr<T> make_shared(std::size_t n);
|
shared_ptr<T> make_shared(std::size_t n);
|
||||||
```
|
```
|
||||||
::
|
|
||||||
```
|
```
|
||||||
template<class T, class A>
|
template<class T, class A>
|
||||||
shared_ptr<T> allocate_shared(const A& a, std::size_t n);
|
shared_ptr<T> allocate_shared(const A& a, std::size_t n);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Remarks::: These overloads shall only participate in overload resolution when
|
* {blank}
|
||||||
|
+
|
||||||
|
Remarks:: These overloads shall only participate in overload resolution when
|
||||||
`T` is an array type of the form `U[]`.
|
`T` is an array type of the form `U[]`.
|
||||||
Returns::: A `shared_ptr` to a sequence of `n` value-initialized objects of
|
Returns:: A `shared_ptr` to a sequence of `n` value-initialized objects of
|
||||||
type `U`.
|
type `U`.
|
||||||
Examples:::
|
Examples::
|
||||||
* `auto p = make_shared<double[]>(1024);`
|
* `auto p = make_shared<double[]>(1024);`
|
||||||
* `auto p = make_shared<double[][2][2]>(6);`
|
* `auto p = make_shared<double[][2][2]>(6);`
|
||||||
|
|
||||||
@@ -210,17 +212,18 @@ Examples:::
|
|||||||
template<class T>
|
template<class T>
|
||||||
shared_ptr<T> make_shared();
|
shared_ptr<T> make_shared();
|
||||||
```
|
```
|
||||||
::
|
|
||||||
```
|
```
|
||||||
template<class T, class A>
|
template<class T, class A>
|
||||||
shared_ptr<T> allocate_shared(const A& a);
|
shared_ptr<T> allocate_shared(const A& a);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Remarks::: These overloads shall only participate in overload resolution when
|
* {blank}
|
||||||
|
+
|
||||||
|
Remarks:: These overloads shall only participate in overload resolution when
|
||||||
`T` is an array type of the form `U[N]`.
|
`T` is an array type of the form `U[N]`.
|
||||||
Returns::: A `shared_ptr` to a sequence of `N` value-initialized objects of
|
Returns:: A `shared_ptr` to a sequence of `N` value-initialized objects of
|
||||||
type `U`.
|
type `U`.
|
||||||
Examples:::
|
Examples::
|
||||||
* `auto p = make_shared<double[1024]>();`
|
* `auto p = make_shared<double[1024]>();`
|
||||||
* `auto p = make_shared<double[6][2][2]>();`
|
* `auto p = make_shared<double[6][2][2]>();`
|
||||||
|
|
||||||
@@ -228,17 +231,18 @@ Examples:::
|
|||||||
template<class T> shared_ptr<T>
|
template<class T> shared_ptr<T>
|
||||||
make_shared(std::size_t n, const remove_extent_t<T>& v);
|
make_shared(std::size_t n, const remove_extent_t<T>& v);
|
||||||
```
|
```
|
||||||
::
|
|
||||||
```
|
```
|
||||||
template<class T, class A> shared_ptr<T>
|
template<class T, class A> shared_ptr<T>
|
||||||
allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
|
allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Remarks::: These overloads shall only participate in overload resolution when
|
* {blank}
|
||||||
|
+
|
||||||
|
Remarks:: These overloads shall only participate in overload resolution when
|
||||||
`T` is an array type of the form `U[]`.
|
`T` is an array type of the form `U[]`.
|
||||||
Returns::: A `shared_ptr` to a sequence of `n` objects of type `U`, each
|
Returns:: A `shared_ptr` to a sequence of `n` objects of type `U`, each
|
||||||
initialized to `v`.
|
initialized to `v`.
|
||||||
Examples:::
|
Examples::
|
||||||
* `auto p = make_shared<double[]>(1024, 1.0);`
|
* `auto p = make_shared<double[]>(1024, 1.0);`
|
||||||
* `auto p = make_shared<double[][2]>(6, {1.0, 0.0});`
|
* `auto p = make_shared<double[][2]>(6, {1.0, 0.0});`
|
||||||
* `auto p = make_shared<std::vector<int>[]>(4, {1, 2});`
|
* `auto p = make_shared<std::vector<int>[]>(4, {1, 2});`
|
||||||
@@ -247,17 +251,18 @@ Examples:::
|
|||||||
template<class T>
|
template<class T>
|
||||||
shared_ptr<T> make_shared(const remove_extent_t<T>& v);
|
shared_ptr<T> make_shared(const remove_extent_t<T>& v);
|
||||||
```
|
```
|
||||||
::
|
|
||||||
```
|
```
|
||||||
template<class T, class A>
|
template<class T, class A>
|
||||||
shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v);
|
shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Remarks::: These overloads shall only participate in overload resolution when
|
* {blank}
|
||||||
|
+
|
||||||
|
Remarks:: These overloads shall only participate in overload resolution when
|
||||||
`T` is an array type of the form `U[N]`.
|
`T` is an array type of the form `U[N]`.
|
||||||
Returns::: A `shared_ptr` to a sequence of `N` objects of type `U`, each
|
Returns:: A `shared_ptr` to a sequence of `N` objects of type `U`, each
|
||||||
initialized to `v`.
|
initialized to `v`.
|
||||||
Examples:::
|
Examples::
|
||||||
* `auto p = make_shared<double[1024]>(1.0);`
|
* `auto p = make_shared<double[1024]>(1.0);`
|
||||||
* `auto p = make_shared<double[6][2]>({1.0, 0.0});`
|
* `auto p = make_shared<double[6][2]>({1.0, 0.0});`
|
||||||
* `auto p = make_shared<std::vector<int>[4]>({1, 2});`
|
* `auto p = make_shared<std::vector<int>[4]>({1, 2});`
|
||||||
@@ -266,30 +271,32 @@ Examples:::
|
|||||||
template<class T>
|
template<class T>
|
||||||
shared_ptr<T> make_shared_noinit();
|
shared_ptr<T> make_shared_noinit();
|
||||||
```
|
```
|
||||||
::
|
|
||||||
```
|
```
|
||||||
template<class T, class A>
|
template<class T, class A>
|
||||||
shared_ptr<T> allocate_shared_noinit(const A& a);
|
shared_ptr<T> allocate_shared_noinit(const A& a);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Remarks::: These overloads shall only participate in overload resolution when
|
* {blank}
|
||||||
|
+
|
||||||
|
Remarks:: These overloads shall only participate in overload resolution when
|
||||||
`T` is not an array type, or an array type of the `U[N]`.
|
`T` is not an array type, or an array type of the `U[N]`.
|
||||||
Returns::: A `shared_ptr` to a default-initialized object of type `T`, or a
|
Returns:: A `shared_ptr` to a default-initialized object of type `T`, or a
|
||||||
sequence of `N` default-initialized objects of type `U`, respectively.
|
sequence of `N` default-initialized objects of type `U`, respectively.
|
||||||
Example::: `auto p = make_shared_noinit<double[1024]>();`
|
Example:: `auto p = make_shared_noinit<double[1024]>();`
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class T>
|
template<class T>
|
||||||
shared_ptr<T> make_shared_noinit(std::size_t n);
|
shared_ptr<T> make_shared_noinit(std::size_t n);
|
||||||
```
|
```
|
||||||
::
|
|
||||||
```
|
```
|
||||||
template<class T, class A>
|
template<class T, class A>
|
||||||
shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n);
|
shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Remarks::: These overloads shall only participate in overload resolution when
|
* {blank}
|
||||||
|
+
|
||||||
|
Remarks:: These overloads shall only participate in overload resolution when
|
||||||
`T` is an array type of the form `U[]`.
|
`T` is an array type of the form `U[]`.
|
||||||
Returns::: A `shared_ptr` to a sequence of `_n_` default-initialized objects
|
Returns:: A `shared_ptr` to a sequence of `_n_` default-initialized objects
|
||||||
of type `U`.
|
of type `U`.
|
||||||
Example::: `auto p = make_shared_noinit<double[]>(1024);`
|
Example:: `auto p = make_shared_noinit<double[]>(1024);`
|
||||||
|
@@ -68,48 +68,58 @@ namespace boost {
|
|||||||
template<class T, class... Args>
|
template<class T, class... Args>
|
||||||
std::unique_ptr<T> make_unique(Args&&... args);
|
std::unique_ptr<T> make_unique(Args&&... args);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Remarks::: These overloads shall only participate in overload resolution when
|
* {blank}
|
||||||
|
+
|
||||||
|
Remarks:: These overloads shall only participate in overload resolution when
|
||||||
`T` is not an array type.
|
`T` is not an array type.
|
||||||
Returns::: `std::unique_ptr<T>(new T(std::forward<Args>(args)\...)`.
|
Returns:: `std::unique_ptr<T>(new T(std::forward<Args>(args)\...)`.
|
||||||
Example::: `auto p = make_unique<int>();`
|
Example:: `auto p = make_unique<int>();`
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class T>
|
template<class T>
|
||||||
std::unique_ptr<T> make_unique(remove_reference_t<T>&& v);
|
std::unique_ptr<T> make_unique(remove_reference_t<T>&& v);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Remarks::: These overloads shall only participate in overload resolution when
|
* {blank}
|
||||||
|
+
|
||||||
|
Remarks:: These overloads shall only participate in overload resolution when
|
||||||
`T` is not an array type.
|
`T` is not an array type.
|
||||||
Returns::: `std::unique_ptr<T>(new T(std::move(v))`.
|
Returns:: `std::unique_ptr<T>(new T(std::move(v))`.
|
||||||
Example::: `auto p = make_unique<std::vector<int> >({1, 2});`
|
Example:: `auto p = make_unique<std::vector<int> >({1, 2});`
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class T>
|
template<class T>
|
||||||
std::unique_ptr<T> make_unique(std::size_t n);
|
std::unique_ptr<T> make_unique(std::size_t n);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Remarks::: These overloads shall only participate in overload resolution when
|
* {blank}
|
||||||
|
+
|
||||||
|
Remarks:: These overloads shall only participate in overload resolution when
|
||||||
`T` is an array type of the form `U[]`.
|
`T` is an array type of the form `U[]`.
|
||||||
Returns::: `std::unique_ptr<U[]>(new U[n]())`.
|
Returns:: `std::unique_ptr<U[]>(new U[n]())`.
|
||||||
Example::: `auto p = make_unique<double[]>(1024);`
|
Example:: `auto p = make_unique<double[]>(1024);`
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class T>
|
template<class T>
|
||||||
std::unique_ptr<T> make_unique_noinit();
|
std::unique_ptr<T> make_unique_noinit();
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Remarks::: These overloads shall only participate in overload resolution when
|
* {blank}
|
||||||
|
+
|
||||||
|
Remarks:: These overloads shall only participate in overload resolution when
|
||||||
`T` is not an array type.
|
`T` is not an array type.
|
||||||
Returns::: `std::unique_ptr<T>(new T)`.
|
Returns:: `std::unique_ptr<T>(new T)`.
|
||||||
Example::: `auto p = make_unique_noinit<double[1024]>();`
|
Example:: `auto p = make_unique_noinit<double[1024]>();`
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class T>
|
template<class T>
|
||||||
std::unique_ptr<T> make_unique_noinit(std::size_t n);
|
std::unique_ptr<T> make_unique_noinit(std::size_t n);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Remarks::: These overloads shall only participate in overload resolution when
|
* {blank}
|
||||||
|
+
|
||||||
|
Remarks:: These overloads shall only participate in overload resolution when
|
||||||
`T` is an array type of the form `U[]`.
|
`T` is an array type of the form `U[]`.
|
||||||
Returns::: `std::unique_ptr<U[]>(new U[n])`.
|
Returns:: `std::unique_ptr<U[]>(new U[n])`.
|
||||||
Example::: `auto p = make_unique_noinit<double[]>(1024);`
|
Example:: `auto p = make_unique_noinit<double[]>(1024);`
|
||||||
|
@@ -78,23 +78,29 @@ namespace boost {
|
|||||||
```
|
```
|
||||||
template<class T, class U> T* static_pointer_cast(U* p) noexcept;
|
template<class T, class U> T* static_pointer_cast(U* p) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: `static_cast<T*>(p)`
|
* {blank}
|
||||||
|
+
|
||||||
|
Returns:: `static_cast<T*>(p)`
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class T, class U> std::shared_ptr<T>
|
template<class T, class U> std::shared_ptr<T>
|
||||||
static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: `std::static_pointer_cast<T>(p)`
|
* {blank}
|
||||||
|
+
|
||||||
|
Returns:: `std::static_pointer_cast<T>(p)`
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class T, class U> std::unique_ptr<T>
|
template<class T, class U> std::unique_ptr<T>
|
||||||
static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Requires::: The expression `static_cast<T*>((U*)0)` must be well-formed.
|
* {blank}
|
||||||
Returns::: `std::unique_ptr<T>(static_cast<typename
|
+
|
||||||
|
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()))`.
|
std::unique_ptr<T>::element_type*>(p.release()))`.
|
||||||
|
|
||||||
CAUTION: The seemingly equivalent expression
|
CAUTION: The seemingly equivalent expression
|
||||||
@@ -106,25 +112,31 @@ undefined behavior, attempting to delete the same object twice.
|
|||||||
```
|
```
|
||||||
template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
|
template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: `dynamic_cast<T*>(p)`
|
* {blank}
|
||||||
|
+
|
||||||
|
Returns:: `dynamic_cast<T*>(p)`
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class T, class U> std::shared_ptr<T>
|
template<class T, class U> std::shared_ptr<T>
|
||||||
dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: `std::dynamic_pointer_cast<T>(p)`
|
* {blank}
|
||||||
|
+
|
||||||
|
Returns:: `std::dynamic_pointer_cast<T>(p)`
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class T, class U> std::unique_ptr<T>
|
template<class T, class U> std::unique_ptr<T>
|
||||||
dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Requires:::
|
* {blank}
|
||||||
|
+
|
||||||
|
Requires::
|
||||||
* The expression `static_cast<T*>((U*)0)` must be well-formed.
|
* The expression `static_cast<T*>((U*)0)` must be well-formed.
|
||||||
* `T` must have a virtual destructor.
|
* `T` must have a virtual destructor.
|
||||||
Returns:::
|
Returns::
|
||||||
* When `dynamic_cast<typename std::unique_ptr<T>::element_type*>(p.get())`
|
* When `dynamic_cast<typename std::unique_ptr<T>::element_type*>(p.get())`
|
||||||
returns a non-zero value, `std::unique_ptr<T>(dynamic_cast<typename
|
returns a non-zero value, `std::unique_ptr<T>(dynamic_cast<typename
|
||||||
std::unique_ptr<T>::element_type*>(p.release()));`.
|
std::unique_ptr<T>::element_type*>(p.release()));`.
|
||||||
@@ -135,23 +147,29 @@ std::unique_ptr<T>::element_type*>(p.release()));`.
|
|||||||
```
|
```
|
||||||
template<class T, class U> T* const_pointer_cast(U* p) noexcept;
|
template<class T, class U> T* const_pointer_cast(U* p) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: `const_cast<T*>(p)`
|
* {blank}
|
||||||
|
+
|
||||||
|
Returns:: `const_cast<T*>(p)`
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class T, class U> std::shared_ptr<T>
|
template<class T, class U> std::shared_ptr<T>
|
||||||
const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: `std::const_pointer_cast<T>(p)`
|
* {blank}
|
||||||
|
+
|
||||||
|
Returns:: `std::const_pointer_cast<T>(p)`
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class T, class U> std::unique_ptr<T>
|
template<class T, class U> std::unique_ptr<T>
|
||||||
const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Requires::: The expression `const_cast<T*>((U*)0)` must be well-formed.
|
* {blank}
|
||||||
Returns::: `std::unique_ptr<T>(const_cast<typename
|
+
|
||||||
|
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()))`.
|
std::unique_ptr<T>::element_type*>(p.release()))`.
|
||||||
|
|
||||||
### reinterpret_pointer_cast
|
### reinterpret_pointer_cast
|
||||||
@@ -159,23 +177,29 @@ std::unique_ptr<T>::element_type*>(p.release()))`.
|
|||||||
```
|
```
|
||||||
template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
|
template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: `reinterpret_cast<T*>(p)`
|
* {blank}
|
||||||
|
+
|
||||||
|
Returns:: `reinterpret_cast<T*>(p)`
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class T, class U> std::shared_ptr<T>
|
template<class T, class U> std::shared_ptr<T>
|
||||||
reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: `std::reinterpret_pointer_cast<T>(p)`
|
* {blank}
|
||||||
|
+
|
||||||
|
Returns:: `std::reinterpret_pointer_cast<T>(p)`
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class T, class U> std::unique_ptr<T>
|
template<class T, class U> std::unique_ptr<T>
|
||||||
reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Requires::: The expression `reinterpret_cast<T*>((U*)0)` must be well-formed.
|
* {blank}
|
||||||
Returns::: `std::unique_ptr<T>(reinterpret_cast<typename
|
+
|
||||||
|
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()))`.
|
std::unique_ptr<T>::element_type*>(p.release()))`.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
@@ -210,4 +234,4 @@ int main()
|
|||||||
|
|
||||||
delete ptr;
|
delete ptr;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@@ -105,42 +105,50 @@ Type:: Provides the type of the stored pointer.
|
|||||||
```
|
```
|
||||||
explicit shared_array(T* p = 0);
|
explicit shared_array(T* p = 0);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Effects::: Constructs a `shared_array`, storing a copy of `p`, which must be a
|
* {blank}
|
||||||
|
+
|
||||||
|
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.
|
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`).
|
Afterwards, the use count is 1 (even if `p == 0`; see `~shared_array`).
|
||||||
Requires::: `T` is a complete type.
|
Requires:: `T` is a complete type.
|
||||||
Throws::: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called.
|
Throws:: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called.
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class D> shared_array(T* p, D d);
|
template<class D> shared_array(T* p, D d);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Effects::: Constructs a `shared_array`, storing a copy of `p` and of `d`.
|
* {blank}
|
||||||
|
+
|
||||||
|
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
|
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)`.
|
pointed to by `p`, the object `d` is used in the statement `d(p)`.
|
||||||
Requires:::
|
Requires::
|
||||||
* `T` is a complete type.
|
* `T` is a complete type.
|
||||||
* The copy constructor and destructor of `D` must not throw.
|
* The copy constructor and destructor of `D` must not throw.
|
||||||
* Invoking the object `d` with parameter `p` 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.
|
Throws:: `std::bad_alloc`. If an exception is thrown, `d(p)` is called.
|
||||||
|
|
||||||
```
|
```
|
||||||
shared_array(const shared_array& v) noexcept;
|
shared_array(const shared_array& v) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Effects::: Constructs a `shared_array`, as if by storing a copy of the pointer
|
* {blank}
|
||||||
|
+
|
||||||
|
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
|
stored in `v`. Afterwards, the use count for all copies is 1 more than the
|
||||||
initial use count.
|
initial use count.
|
||||||
Requires::: `T` is a complete type.
|
Requires:: `T` is a complete type.
|
||||||
|
|
||||||
### Destructor
|
### Destructor
|
||||||
|
|
||||||
```
|
```
|
||||||
~shared_array() noexcept;
|
~shared_array() noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Effects::: Decrements the use count. Then, if the use count is 0, deletes the
|
* {blank}
|
||||||
|
+
|
||||||
|
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
|
array pointed to by the stored pointer. Note that `delete[]` on a pointer with
|
||||||
a value of 0 is harmless.
|
a value of 0 is harmless.
|
||||||
|
|
||||||
@@ -149,60 +157,70 @@ a value of 0 is harmless.
|
|||||||
```
|
```
|
||||||
shared_array& operator=(const shared_array& v) noexcept;
|
shared_array& operator=(const shared_array& v) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Effects::: Constructs a new `shared_array` as described above, then replaces
|
* {blank}
|
||||||
|
+
|
||||||
|
Effects:: Constructs a new `shared_array` as described above, then replaces
|
||||||
this `shared_array` with the new one, destroying the replaced object.
|
this `shared_array` with the new one, destroying the replaced object.
|
||||||
Requires::: `T` is a complete type.
|
Requires:: `T` is a complete type.
|
||||||
Returns::: `*this`.
|
Returns:: `*this`.
|
||||||
|
|
||||||
### reset
|
### reset
|
||||||
|
|
||||||
```
|
```
|
||||||
void reset(T* p = 0);
|
void reset(T* p = 0);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Effects::: Constructs a new `shared_array` as described above, then replaces
|
* {blank}
|
||||||
|
+
|
||||||
|
Effects:: Constructs a new `shared_array` as described above, then replaces
|
||||||
this `shared_array` with the new one, destroying the replaced object.
|
this `shared_array` with the new one, destroying the replaced object.
|
||||||
Requires::: `T` is a complete type.
|
Requires:: `T` is a complete type.
|
||||||
Throws::: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called.
|
Throws:: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called.
|
||||||
|
|
||||||
```
|
```
|
||||||
template<class D> void reset(T* p, D d);
|
template<class D> void reset(T* p, D d);
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Effects::: Constructs a new `shared_array` as described above, then replaces
|
* {blank}
|
||||||
|
+
|
||||||
|
Effects:: Constructs a new `shared_array` as described above, then replaces
|
||||||
this `shared_array` with the new one, destroying the replaced object.
|
this `shared_array` with the new one, destroying the replaced object.
|
||||||
Requires:::
|
Requires::
|
||||||
* `T` is a complete type.
|
* `T` is a complete type.
|
||||||
* The copy constructor of `D` must not throw.
|
* The copy constructor of `D` must not throw.
|
||||||
Throws::: `std::bad_alloc`. If an exception is thrown, `d(p)` is called.
|
Throws:: `std::bad_alloc`. If an exception is thrown, `d(p)` is called.
|
||||||
|
|
||||||
### Indexing
|
### Indexing
|
||||||
|
|
||||||
```
|
```
|
||||||
T& operator[](std::ptrdiff_t n) const noexcept;
|
T& operator[](std::ptrdiff_t n) const noexcept;
|
||||||
```
|
```
|
||||||
Returns::: A reference to element `n` of the array pointed to by the stored
|
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. 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
|
pointer is 0, or if `n` is less than 0 or is greater than or equal to the
|
||||||
number of elements in the array.
|
number of elements in the array.
|
||||||
Requires::: `T` is a complete type.
|
Requires:: `T` is a complete type.
|
||||||
|
|
||||||
### get
|
### get
|
||||||
|
|
||||||
```
|
```
|
||||||
T* get() const noexcept;
|
T* get() const noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: The stored pointer.
|
* {blank}
|
||||||
|
+
|
||||||
|
Returns:: The stored pointer.
|
||||||
|
|
||||||
### unique
|
### unique
|
||||||
|
|
||||||
```
|
```
|
||||||
bool unique() const noexcept;
|
bool unique() const noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: `true` if no other `shared_array` is sharing ownership of the
|
* {blank}
|
||||||
|
+
|
||||||
|
Returns:: `true` if no other `shared_array` is sharing ownership of the
|
||||||
stored pointer, `false` otherwise.
|
stored pointer, `false` otherwise.
|
||||||
|
|
||||||
### use_count
|
### use_count
|
||||||
@@ -210,8 +228,10 @@ stored pointer, `false` otherwise.
|
|||||||
```
|
```
|
||||||
long use_count() const noexcept;
|
long use_count() const noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: The number of `shared_array` objects sharing ownership of the
|
* {blank}
|
||||||
|
+
|
||||||
|
Returns:: The number of `shared_array` objects sharing ownership of the
|
||||||
stored pointer.
|
stored pointer.
|
||||||
|
|
||||||
### Conversions
|
### Conversions
|
||||||
@@ -219,17 +239,21 @@ stored pointer.
|
|||||||
```
|
```
|
||||||
explicit operator bool() const noexcept;
|
explicit operator bool() const noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: `get() != 0`.
|
* {blank}
|
||||||
Requires::: `T` is a complete type.
|
+
|
||||||
|
Returns:: `get() != 0`.
|
||||||
|
Requires:: `T` is a complete type.
|
||||||
|
|
||||||
### swap
|
### swap
|
||||||
|
|
||||||
```
|
```
|
||||||
void swap(shared_array<T>& b) noexcept;
|
void swap(shared_array<T>& b) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Effects::: Exchanges the contents of the two smart pointers.
|
* {blank}
|
||||||
|
+
|
||||||
|
Effects:: Exchanges the contents of the two smart pointers.
|
||||||
|
|
||||||
## Free Functions
|
## Free Functions
|
||||||
|
|
||||||
@@ -247,8 +271,10 @@ template<class T> bool
|
|||||||
template<class T> bool
|
template<class T> bool
|
||||||
operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept;
|
operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: The result of comparing the stored pointers of the two smart
|
* {blank}
|
||||||
|
+
|
||||||
|
Returns:: The result of comparing the stored pointers of the two smart
|
||||||
pointers.
|
pointers.
|
||||||
|
|
||||||
NOTE: The `operator<` overload is provided to define an ordering so that
|
NOTE: The `operator<` overload is provided to define an ordering so that
|
||||||
@@ -265,6 +291,8 @@ mandates that relational operations on pointers are unspecified (5.9
|
|||||||
template<class T>
|
template<class T>
|
||||||
void swap(shared_array<T>& a, shared_array<T>& b) noexcept;
|
void swap(shared_array<T>& a, shared_array<T>& b) noexcept;
|
||||||
```
|
```
|
||||||
::
|
[none]
|
||||||
Returns::: `a.swap(b)`.
|
* {blank}
|
||||||
Requires::: `T` is a complete type.
|
+
|
||||||
|
Returns:: `a.swap(b)`.
|
||||||
|
Requires:: `T` is a complete type.
|
||||||
|
@@ -132,7 +132,6 @@ namespace boost {
|
|||||||
template<class Y> shared_ptr(shared_ptr<Y> && 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> const & r, element_type * p) noexcept;
|
||||||
|
|
||||||
template<class Y> shared_ptr(shared_ptr<Y> && 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(weak_ptr<Y> const & r);
|
||||||
@@ -373,7 +372,7 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p) noexcept
|
|||||||
[none]
|
[none]
|
||||||
* {blank}
|
* {blank}
|
||||||
+
|
+
|
||||||
Effects:: constructs a `shared_ptr` that shares ownership with `r` and stores `p`.
|
Effects:: Copy-constructs a `shared_ptr` from `r`, while storing `p` instead.
|
||||||
|
|
||||||
Postconditions:: `get() == p && use_count() == r.use_count()`.
|
Postconditions:: `get() == p && use_count() == r.use_count()`.
|
||||||
|
|
||||||
|
@@ -88,6 +88,10 @@ namespace boost {
|
|||||||
|
|
||||||
weak_ptr(weak_ptr && r) noexcept;
|
weak_ptr(weak_ptr && r) noexcept;
|
||||||
|
|
||||||
|
template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
|
||||||
|
template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept;
|
||||||
|
template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept;
|
||||||
|
|
||||||
~weak_ptr() noexcept;
|
~weak_ptr() noexcept;
|
||||||
|
|
||||||
weak_ptr & operator=(weak_ptr const & r) noexcept;
|
weak_ptr & operator=(weak_ptr const & r) noexcept;
|
||||||
@@ -98,6 +102,8 @@ namespace boost {
|
|||||||
long use_count() const noexcept;
|
long use_count() const noexcept;
|
||||||
bool expired() const noexcept;
|
bool expired() const noexcept;
|
||||||
|
|
||||||
|
bool empty() const noexcept;
|
||||||
|
|
||||||
shared_ptr<T> lock() const noexcept;
|
shared_ptr<T> lock() const noexcept;
|
||||||
|
|
||||||
void reset() noexcept;
|
void reset() noexcept;
|
||||||
@@ -157,6 +163,21 @@ weak_ptr(weak_ptr && r) noexcept;
|
|||||||
Effects:: Constructs a `weak_ptr` that has the value `r` held.
|
Effects:: Constructs a `weak_ptr` that has the value `r` held.
|
||||||
Postconditions:: `r` is empty.
|
Postconditions:: `r` is empty.
|
||||||
|
|
||||||
|
### aliasing constructors
|
||||||
|
```
|
||||||
|
template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
|
||||||
|
```
|
||||||
|
```
|
||||||
|
template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept;
|
||||||
|
```
|
||||||
|
```
|
||||||
|
template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept;
|
||||||
|
```
|
||||||
|
Effects:: Constructs a `weak_ptr` from `r` as if by using the corresponding converting/copy/move constructor, but stores `p` instead.
|
||||||
|
Postconditions:: `use_count() == r.use_count()`. When `!expired()`, `shared_ptr<T>(*this).get() == p`.
|
||||||
|
|
||||||
|
NOTE: These constructors are an extension, not present in `std::weak_ptr`.
|
||||||
|
|
||||||
### destructor
|
### destructor
|
||||||
```
|
```
|
||||||
~weak_ptr() noexcept;
|
~weak_ptr() noexcept;
|
||||||
@@ -204,6 +225,17 @@ bool expired() const noexcept;
|
|||||||
+
|
+
|
||||||
Returns:: `use_count() == 0`.
|
Returns:: `use_count() == 0`.
|
||||||
|
|
||||||
|
### empty
|
||||||
|
```
|
||||||
|
bool empty() const noexcept;
|
||||||
|
```
|
||||||
|
[none]
|
||||||
|
* {blank}
|
||||||
|
+
|
||||||
|
Returns:: `true` when `*this` is empty, `false` otherwise.
|
||||||
|
|
||||||
|
NOTE: This function is an extension, not present in `std::weak_ptr`.
|
||||||
|
|
||||||
### lock
|
### lock
|
||||||
```
|
```
|
||||||
shared_ptr<T> lock() const noexcept;
|
shared_ptr<T> lock() const noexcept;
|
||||||
|
@@ -63,6 +63,11 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
|
||||||
|
: p_( std::move( p ) ), l_ BOOST_DETAIL_SPINLOCK_INIT
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
atomic_shared_ptr() BOOST_SP_NOEXCEPT
|
atomic_shared_ptr() BOOST_SP_NOEXCEPT
|
||||||
@@ -71,8 +76,6 @@ public:
|
|||||||
std::memcpy( &l_, &init, sizeof( init ) );
|
std::memcpy( &l_, &init, sizeof( init ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
|
atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
|
||||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||||
: p_( std::move( p ) )
|
: p_( std::move( p ) )
|
||||||
@@ -84,6 +87,8 @@ public:
|
|||||||
std::memcpy( &l_, &init, sizeof( init ) );
|
std::memcpy( &l_, &init, sizeof( init ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
|
atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
|
||||||
{
|
{
|
||||||
boost::detail::spinlock::scoped_lock lock( l_ );
|
boost::detail::spinlock::scoped_lock lock( l_ );
|
||||||
|
@@ -144,8 +144,7 @@ template<typename T>
|
|||||||
boost::weak_ptr<T> weak_from_raw(T *p)
|
boost::weak_ptr<T> weak_from_raw(T *p)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(p != 0);
|
BOOST_ASSERT(p != 0);
|
||||||
boost::weak_ptr<T> result;
|
boost::weak_ptr<T> result(p->enable_shared_from_raw::weak_from_this(), p);
|
||||||
result._internal_aliasing_assign(p->enable_shared_from_raw::weak_from_this(), p);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -297,6 +297,8 @@ template<class T> T * get_pointer(intrusive_ptr<T> const & p) BOOST_SP_NOEXCEPT
|
|||||||
return p.get();
|
return p.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pointer casts
|
||||||
|
|
||||||
template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
|
template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
|
||||||
{
|
{
|
||||||
return static_cast<T *>(p.get());
|
return static_cast<T *>(p.get());
|
||||||
@@ -312,6 +314,31 @@ template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U
|
|||||||
return dynamic_cast<T *>(p.get());
|
return dynamic_cast<T *>(p.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||||
|
|
||||||
|
template<class T, class U> intrusive_ptr<T> static_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
|
||||||
|
{
|
||||||
|
return intrusive_ptr<T>( static_cast<T*>( p.detach() ), false );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> intrusive_ptr<T> const_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
|
||||||
|
{
|
||||||
|
return intrusive_ptr<T>( const_cast<T*>( p.detach() ), false );
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
|
||||||
|
{
|
||||||
|
T * p2 = dynamic_cast<T*>( p.get() );
|
||||||
|
|
||||||
|
intrusive_ptr<T> r( p2, false );
|
||||||
|
|
||||||
|
if( p2 ) p.detach();
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||||
|
|
||||||
// operator<<
|
// operator<<
|
||||||
|
|
||||||
#if !defined(BOOST_NO_IOSTREAM)
|
#if !defined(BOOST_NO_IOSTREAM)
|
||||||
|
@@ -137,6 +137,23 @@ public:
|
|||||||
boost::detail::sp_assert_convertible< Y, T >();
|
boost::detail::sp_assert_convertible< Y, T >();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// aliasing
|
||||||
|
template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) BOOST_SP_NOEXCEPT: px( p ), pn( r.pn )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) BOOST_SP_NOEXCEPT: px( p ), pn( r.pn )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||||
|
|
||||||
|
template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) BOOST_SP_NOEXCEPT: px( p ), pn( std::move( r.pn ) )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
|
#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
|
||||||
|
|
||||||
template<class Y>
|
template<class Y>
|
||||||
@@ -194,6 +211,11 @@ public:
|
|||||||
return pn.empty();
|
return pn.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool empty() const BOOST_SP_NOEXCEPT // extension, not in std::weak_ptr
|
||||||
|
{
|
||||||
|
return pn.empty();
|
||||||
|
}
|
||||||
|
|
||||||
void reset() BOOST_SP_NOEXCEPT
|
void reset() BOOST_SP_NOEXCEPT
|
||||||
{
|
{
|
||||||
this_type().swap(*this);
|
this_type().swap(*this);
|
||||||
@@ -205,13 +227,6 @@ public:
|
|||||||
pn.swap(other.pn);
|
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
|
template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
|
||||||
{
|
{
|
||||||
return pn < rhs.pn;
|
return pn < rhs.pn;
|
||||||
|
25
test/Jamfile
25
test/Jamfile
@@ -158,18 +158,18 @@ compile-fail array_fail_dereference.cpp ;
|
|||||||
compile-fail array_fail_member_access.cpp ;
|
compile-fail array_fail_member_access.cpp ;
|
||||||
compile-fail array_fail_array_access.cpp ;
|
compile-fail array_fail_array_access.cpp ;
|
||||||
|
|
||||||
run make_shared_array_test.cpp ;
|
run make_shared_array_test.cpp : : : <toolset>msvc-8.0:<build>no ;
|
||||||
run make_shared_arrays_test.cpp ; # <cxxflags>-fno-deduce-init-list no longer needed for gcc-4.6
|
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_throws_test.cpp : : : <toolset>msvc-8.0:<build>no ;
|
||||||
run make_shared_array_esft_test.cpp ;
|
run make_shared_array_esft_test.cpp : : : <toolset>msvc-8.0:<build>no ;
|
||||||
run make_shared_array_noinit_test.cpp ;
|
run make_shared_array_noinit_test.cpp : : : <toolset>msvc-8.0:<build>no ;
|
||||||
run make_shared_array_value_test.cpp ;
|
run make_shared_array_value_test.cpp : : : <toolset>msvc-8.0:<build>no ;
|
||||||
run allocate_shared_array_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_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_throws_test.cpp : : : <toolset>msvc-8.0:<build>no ;
|
||||||
run allocate_shared_array_esft_test.cpp ;
|
run allocate_shared_array_esft_test.cpp : : : <toolset>msvc-8.0:<build>no ;
|
||||||
run allocate_shared_array_noinit_test.cpp ;
|
run allocate_shared_array_noinit_test.cpp : : : <toolset>msvc-8.0:<build>no ;
|
||||||
run allocate_shared_array_value_test.cpp ;
|
run allocate_shared_array_value_test.cpp : : : <toolset>msvc-8.0:<build>no ;
|
||||||
run allocate_shared_array_construct_test.cpp ;
|
run allocate_shared_array_construct_test.cpp ;
|
||||||
|
|
||||||
run make_unique_test.cpp ;
|
run make_unique_test.cpp ;
|
||||||
@@ -236,7 +236,7 @@ run shared_ptr_fn_test.cpp ;
|
|||||||
run get_deleter_test2.cpp ;
|
run get_deleter_test2.cpp ;
|
||||||
run get_deleter_test3.cpp ;
|
run get_deleter_test3.cpp ;
|
||||||
run get_deleter_array_test2.cpp ;
|
run get_deleter_array_test2.cpp ;
|
||||||
run get_deleter_array_test3.cpp ;
|
run get_deleter_array_test3.cpp : : : <toolset>msvc-8.0:<build>no ;
|
||||||
|
|
||||||
run sp_convertible_test2.cpp ;
|
run sp_convertible_test2.cpp ;
|
||||||
|
|
||||||
@@ -275,7 +275,7 @@ run local_sp_fn_test.cpp ;
|
|||||||
run lsp_convertible_test.cpp ;
|
run lsp_convertible_test.cpp ;
|
||||||
run lsp_convertible_test2.cpp ;
|
run lsp_convertible_test2.cpp ;
|
||||||
|
|
||||||
run make_shared_array_tmp_test.cpp ;
|
run make_shared_array_tmp_test.cpp : : : <toolset>msvc-8.0:<build>no ;
|
||||||
|
|
||||||
run lw_thread_test.cpp : : : <threading>multi ;
|
run lw_thread_test.cpp : : : <threading>multi ;
|
||||||
|
|
||||||
@@ -306,3 +306,6 @@ run abi_test_main.cpp abi_test_nt : : : : abi_test_mt_nt ;
|
|||||||
|
|
||||||
run abi_test_main.cpp abi_test_mt/<cxxstd>0x : : : <cxxstd>98 : abi_test_03_11 ;
|
run abi_test_main.cpp abi_test_mt/<cxxstd>0x : : : <cxxstd>98 : abi_test_03_11 ;
|
||||||
run abi_test_main.cpp abi_test_mt/<cxxstd>98 : : : <cxxstd>0x : abi_test_11_03 ;
|
run abi_test_main.cpp abi_test_mt/<cxxstd>98 : : : <cxxstd>0x : abi_test_11_03 ;
|
||||||
|
|
||||||
|
run weak_ptr_alias_test.cpp ;
|
||||||
|
run weak_ptr_alias_move_test.cpp ;
|
||||||
|
@@ -18,10 +18,10 @@
|
|||||||
BOOST_PRAGMA_MESSAGE("Skipping test due to BOOST_NO_CXX11_CONSTEXPR")
|
BOOST_PRAGMA_MESSAGE("Skipping test due to BOOST_NO_CXX11_CONSTEXPR")
|
||||||
int main() {}
|
int main() {}
|
||||||
|
|
||||||
#elif BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
|
#elif BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
|
||||||
|
|
||||||
// MSVC does not implement static initialization for constexpr
|
// MSVC does not implement static initialization for constexpr constructors
|
||||||
BOOST_PRAGMA_MESSAGE("Skipping test due to BOOST_MSVC < 1920")
|
BOOST_PRAGMA_MESSAGE("Skipping test due to BOOST_MSVC < 1930")
|
||||||
int main() {}
|
int main() {}
|
||||||
|
|
||||||
#elif defined(__clang__) && defined( BOOST_NO_CXX14_CONSTEXPR )
|
#elif defined(__clang__) && defined( BOOST_NO_CXX14_CONSTEXPR )
|
||||||
|
@@ -41,7 +41,7 @@ class base
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
boost::detail::atomic_count use_count_;
|
mutable boost::detail::atomic_count use_count_;
|
||||||
|
|
||||||
base(base const &);
|
base(base const &);
|
||||||
base & operator=(base const &);
|
base & operator=(base const &);
|
||||||
@@ -69,24 +69,24 @@ public:
|
|||||||
|
|
||||||
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||||
|
|
||||||
inline friend void intrusive_ptr_add_ref(base * p)
|
inline friend void intrusive_ptr_add_ref(base const * p)
|
||||||
{
|
{
|
||||||
++p->use_count_;
|
++p->use_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline friend void intrusive_ptr_release(base * p)
|
inline friend void intrusive_ptr_release(base const * p)
|
||||||
{
|
{
|
||||||
if(--p->use_count_ == 0) delete p;
|
if(--p->use_count_ == 0) delete p;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
void add_ref()
|
void add_ref() const
|
||||||
{
|
{
|
||||||
++use_count_;
|
++use_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void release()
|
void release() const
|
||||||
{
|
{
|
||||||
if(--use_count_ == 0) delete this;
|
if(--use_count_ == 0) delete this;
|
||||||
}
|
}
|
||||||
@@ -103,12 +103,12 @@ long base::instances = 0;
|
|||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
|
|
||||||
inline void intrusive_ptr_add_ref(N::base * p)
|
inline void intrusive_ptr_add_ref(N::base const * p)
|
||||||
{
|
{
|
||||||
p->add_ref();
|
p->add_ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void intrusive_ptr_release(N::base * p)
|
inline void intrusive_ptr_release(N::base const * p)
|
||||||
{
|
{
|
||||||
p->release();
|
p->release();
|
||||||
}
|
}
|
||||||
@@ -209,6 +209,58 @@ int main()
|
|||||||
BOOST_TEST( N::base::instances == 0 );
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> px( new Y );
|
||||||
|
|
||||||
|
X * px2 = px.get();
|
||||||
|
|
||||||
|
boost::intrusive_ptr<Y> py = boost::static_pointer_cast<Y>( std::move( px ) );
|
||||||
|
BOOST_TEST( py.get() == px2 );
|
||||||
|
BOOST_TEST( px.get() == 0 );
|
||||||
|
BOOST_TEST( py->use_count() == 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X const> px( new X );
|
||||||
|
|
||||||
|
X const * px2 = px.get();
|
||||||
|
|
||||||
|
boost::intrusive_ptr<X> px3 = boost::const_pointer_cast<X>( std::move( px ) );
|
||||||
|
BOOST_TEST( px3.get() == px2 );
|
||||||
|
BOOST_TEST( px.get() == 0 );
|
||||||
|
BOOST_TEST( px3->use_count() == 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> px( new Y );
|
||||||
|
|
||||||
|
X * px2 = px.get();
|
||||||
|
|
||||||
|
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( std::move( px ) );
|
||||||
|
BOOST_TEST( py.get() == px2 );
|
||||||
|
BOOST_TEST( px.get() == 0 );
|
||||||
|
BOOST_TEST( py->use_count() == 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> px( new X );
|
||||||
|
|
||||||
|
X * px2 = px.get();
|
||||||
|
|
||||||
|
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( std::move( px ) );
|
||||||
|
BOOST_TEST( py.get() == 0 );
|
||||||
|
BOOST_TEST( px.get() == px2 );
|
||||||
|
BOOST_TEST( px->use_count() == 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
|
|
||||||
return boost::report_errors();
|
return boost::report_errors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -42,7 +42,7 @@ class base
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
boost::detail::atomic_count use_count_;
|
mutable boost::detail::atomic_count use_count_;
|
||||||
|
|
||||||
base(base const &);
|
base(base const &);
|
||||||
base & operator=(base const &);
|
base & operator=(base const &);
|
||||||
@@ -70,24 +70,24 @@ public:
|
|||||||
|
|
||||||
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||||
|
|
||||||
inline friend void intrusive_ptr_add_ref(base * p)
|
inline friend void intrusive_ptr_add_ref(base const * p)
|
||||||
{
|
{
|
||||||
++p->use_count_;
|
++p->use_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline friend void intrusive_ptr_release(base * p)
|
inline friend void intrusive_ptr_release(base const * p)
|
||||||
{
|
{
|
||||||
if(--p->use_count_ == 0) delete p;
|
if(--p->use_count_ == 0) delete p;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
void add_ref()
|
void add_ref() const
|
||||||
{
|
{
|
||||||
++use_count_;
|
++use_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void release()
|
void release() const
|
||||||
{
|
{
|
||||||
if(--use_count_ == 0) delete this;
|
if(--use_count_ == 0) delete this;
|
||||||
}
|
}
|
||||||
@@ -104,12 +104,12 @@ long base::instances = 0;
|
|||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
|
|
||||||
inline void intrusive_ptr_add_ref(N::base * p)
|
inline void intrusive_ptr_add_ref(N::base const * p)
|
||||||
{
|
{
|
||||||
p->add_ref();
|
p->add_ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void intrusive_ptr_release(N::base * p)
|
inline void intrusive_ptr_release(N::base const * p)
|
||||||
{
|
{
|
||||||
p->release();
|
p->release();
|
||||||
}
|
}
|
||||||
@@ -303,14 +303,211 @@ namespace n_assignment
|
|||||||
|
|
||||||
void copy_assignment()
|
void copy_assignment()
|
||||||
{
|
{
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> p1;
|
||||||
|
|
||||||
|
p1 = p1;
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p1);
|
||||||
|
BOOST_TEST(p1? false: true);
|
||||||
|
BOOST_TEST(!p1);
|
||||||
|
BOOST_TEST(p1.get() == 0);
|
||||||
|
|
||||||
|
boost::intrusive_ptr<X> p2;
|
||||||
|
|
||||||
|
p1 = p2;
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p2);
|
||||||
|
BOOST_TEST(p1? false: true);
|
||||||
|
BOOST_TEST(!p1);
|
||||||
|
BOOST_TEST(p1.get() == 0);
|
||||||
|
|
||||||
|
boost::intrusive_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(N::base::instances == 0);
|
||||||
|
|
||||||
|
boost::intrusive_ptr<X> p4(new X);
|
||||||
|
|
||||||
|
BOOST_TEST(N::base::instances == 1);
|
||||||
|
|
||||||
|
p1 = p4;
|
||||||
|
|
||||||
|
BOOST_TEST(N::base::instances == 1);
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p4);
|
||||||
|
|
||||||
|
BOOST_TEST(p1->use_count() == 2);
|
||||||
|
|
||||||
|
p1 = p2;
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p2);
|
||||||
|
BOOST_TEST(N::base::instances == 1);
|
||||||
|
|
||||||
|
p4 = p3;
|
||||||
|
|
||||||
|
BOOST_TEST(p4 == p3);
|
||||||
|
BOOST_TEST(N::base::instances == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void conversion_assignment()
|
void conversion_assignment()
|
||||||
{
|
{
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> p1;
|
||||||
|
|
||||||
|
boost::intrusive_ptr<Y> p2;
|
||||||
|
|
||||||
|
p1 = p2;
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p2);
|
||||||
|
BOOST_TEST(p1? false: true);
|
||||||
|
BOOST_TEST(!p1);
|
||||||
|
BOOST_TEST(p1.get() == 0);
|
||||||
|
|
||||||
|
BOOST_TEST(N::base::instances == 0);
|
||||||
|
|
||||||
|
boost::intrusive_ptr<Y> p4(new Y);
|
||||||
|
|
||||||
|
BOOST_TEST(N::base::instances == 1);
|
||||||
|
BOOST_TEST(p4->use_count() == 1);
|
||||||
|
|
||||||
|
boost::intrusive_ptr<X> p5(p4);
|
||||||
|
BOOST_TEST(p4->use_count() == 2);
|
||||||
|
|
||||||
|
p1 = p4;
|
||||||
|
|
||||||
|
BOOST_TEST(N::base::instances == 1);
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p4);
|
||||||
|
|
||||||
|
BOOST_TEST(p1->use_count() == 3);
|
||||||
|
BOOST_TEST(p4->use_count() == 3);
|
||||||
|
|
||||||
|
p1 = p2;
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p2);
|
||||||
|
BOOST_TEST(N::base::instances == 1);
|
||||||
|
BOOST_TEST(p4->use_count() == 2);
|
||||||
|
|
||||||
|
p4 = p2;
|
||||||
|
p5 = p2;
|
||||||
|
|
||||||
|
BOOST_TEST(p4 == p2);
|
||||||
|
BOOST_TEST(N::base::instances == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pointer_assignment()
|
void pointer_assignment()
|
||||||
{
|
{
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> p1;
|
||||||
|
|
||||||
|
p1 = p1.get();
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p1);
|
||||||
|
BOOST_TEST(p1? false: true);
|
||||||
|
BOOST_TEST(!p1);
|
||||||
|
BOOST_TEST(p1.get() == 0);
|
||||||
|
|
||||||
|
boost::intrusive_ptr<X> p2;
|
||||||
|
|
||||||
|
p1 = p2.get();
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p2);
|
||||||
|
BOOST_TEST(p1? false: true);
|
||||||
|
BOOST_TEST(!p1);
|
||||||
|
BOOST_TEST(p1.get() == 0);
|
||||||
|
|
||||||
|
boost::intrusive_ptr<X> p3(p1);
|
||||||
|
|
||||||
|
p1 = p3.get();
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p3);
|
||||||
|
BOOST_TEST(p1? false: true);
|
||||||
|
BOOST_TEST(!p1);
|
||||||
|
BOOST_TEST(p1.get() == 0);
|
||||||
|
|
||||||
|
BOOST_TEST(N::base::instances == 0);
|
||||||
|
|
||||||
|
boost::intrusive_ptr<X> p4(new X);
|
||||||
|
|
||||||
|
BOOST_TEST(N::base::instances == 1);
|
||||||
|
|
||||||
|
p1 = p4.get();
|
||||||
|
|
||||||
|
BOOST_TEST(N::base::instances == 1);
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p4);
|
||||||
|
|
||||||
|
BOOST_TEST(p1->use_count() == 2);
|
||||||
|
|
||||||
|
p1 = p2.get();
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p2);
|
||||||
|
BOOST_TEST(N::base::instances == 1);
|
||||||
|
|
||||||
|
p4 = p3.get();
|
||||||
|
|
||||||
|
BOOST_TEST(p4 == p3);
|
||||||
|
BOOST_TEST(N::base::instances == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> p1;
|
||||||
|
|
||||||
|
boost::intrusive_ptr<Y> p2;
|
||||||
|
|
||||||
|
p1 = p2.get();
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p2);
|
||||||
|
BOOST_TEST(p1? false: true);
|
||||||
|
BOOST_TEST(!p1);
|
||||||
|
BOOST_TEST(p1.get() == 0);
|
||||||
|
|
||||||
|
BOOST_TEST(N::base::instances == 0);
|
||||||
|
|
||||||
|
boost::intrusive_ptr<Y> p4(new Y);
|
||||||
|
|
||||||
|
BOOST_TEST(N::base::instances == 1);
|
||||||
|
BOOST_TEST(p4->use_count() == 1);
|
||||||
|
|
||||||
|
boost::intrusive_ptr<X> p5(p4);
|
||||||
|
BOOST_TEST(p4->use_count() == 2);
|
||||||
|
|
||||||
|
p1 = p4.get();
|
||||||
|
|
||||||
|
BOOST_TEST(N::base::instances == 1);
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p4);
|
||||||
|
|
||||||
|
BOOST_TEST(p1->use_count() == 3);
|
||||||
|
BOOST_TEST(p4->use_count() == 3);
|
||||||
|
|
||||||
|
p1 = p2.get();
|
||||||
|
|
||||||
|
BOOST_TEST(p1 == p2);
|
||||||
|
BOOST_TEST(N::base::instances == 1);
|
||||||
|
BOOST_TEST(p4->use_count() == 2);
|
||||||
|
|
||||||
|
p4 = p2.get();
|
||||||
|
p5 = p2.get();
|
||||||
|
|
||||||
|
BOOST_TEST(p4 == p2);
|
||||||
|
BOOST_TEST(N::base::instances == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void test()
|
void test()
|
||||||
@@ -707,15 +904,137 @@ namespace n_static_cast
|
|||||||
|
|
||||||
void test()
|
void test()
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> px(new Y);
|
||||||
|
|
||||||
|
boost::intrusive_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::intrusive_ptr<X> px2(py);
|
||||||
|
BOOST_TEST(px2.get() == px.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<Y> py = boost::static_pointer_cast<Y>( boost::intrusive_ptr<X>(new Y) );
|
||||||
|
BOOST_TEST(py.get() != 0);
|
||||||
|
BOOST_TEST(py->use_count() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace n_static_cast
|
} // namespace n_static_cast
|
||||||
|
|
||||||
|
namespace n_const_cast
|
||||||
|
{
|
||||||
|
|
||||||
|
void test()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X const> px;
|
||||||
|
|
||||||
|
boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>(px);
|
||||||
|
BOOST_TEST(px2.get() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>( boost::intrusive_ptr<X const>() );
|
||||||
|
BOOST_TEST(px2.get() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X const> px(new X);
|
||||||
|
|
||||||
|
boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>(px);
|
||||||
|
BOOST_TEST(px2.get() == px.get());
|
||||||
|
BOOST_TEST(px2->use_count() == 2);
|
||||||
|
BOOST_TEST(px->use_count() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> px = boost::const_pointer_cast<X>( boost::intrusive_ptr<X const>(new X) );
|
||||||
|
BOOST_TEST(px.get() != 0);
|
||||||
|
BOOST_TEST(px->use_count() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace n_const_cast
|
||||||
|
|
||||||
namespace n_dynamic_cast
|
namespace n_dynamic_cast
|
||||||
{
|
{
|
||||||
|
|
||||||
void test()
|
void test()
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> px;
|
||||||
|
|
||||||
|
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
|
||||||
|
BOOST_TEST(py.get() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>() );
|
||||||
|
BOOST_TEST(py.get() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> px(static_cast<X*>(0));
|
||||||
|
|
||||||
|
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
|
||||||
|
BOOST_TEST(py.get() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(static_cast<X*>(0)) );
|
||||||
|
BOOST_TEST(py.get() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> px(new X);
|
||||||
|
|
||||||
|
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
|
||||||
|
BOOST_TEST(py.get() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(new X) );
|
||||||
|
BOOST_TEST(py.get() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> px(new Y);
|
||||||
|
|
||||||
|
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
|
||||||
|
BOOST_TEST(py.get() == px.get());
|
||||||
|
BOOST_TEST(py->use_count() == 2);
|
||||||
|
BOOST_TEST(px->use_count() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::intrusive_ptr<X> px(new Y);
|
||||||
|
|
||||||
|
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(new Y) );
|
||||||
|
BOOST_TEST(py.get() != 0);
|
||||||
|
BOOST_TEST(py->use_count() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_TEST( N::base::instances == 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace n_dynamic_cast
|
} // namespace n_dynamic_cast
|
||||||
@@ -779,6 +1098,7 @@ int main()
|
|||||||
n_swap::test();
|
n_swap::test();
|
||||||
n_comparison::test();
|
n_comparison::test();
|
||||||
n_static_cast::test();
|
n_static_cast::test();
|
||||||
|
n_const_cast::test();
|
||||||
n_dynamic_cast::test();
|
n_dynamic_cast::test();
|
||||||
|
|
||||||
n_transitive::test();
|
n_transitive::test();
|
||||||
|
@@ -17,7 +17,7 @@
|
|||||||
# undef HAVE_CONSTEXPR_INIT
|
# undef HAVE_CONSTEXPR_INIT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
|
#if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
|
||||||
# undef HAVE_CONSTEXPR_INIT
|
# undef HAVE_CONSTEXPR_INIT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -17,7 +17,7 @@
|
|||||||
# undef HAVE_CONSTEXPR_INIT
|
# undef HAVE_CONSTEXPR_INIT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
|
#if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
|
||||||
# undef HAVE_CONSTEXPR_INIT
|
# undef HAVE_CONSTEXPR_INIT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
97
test/weak_ptr_alias_move_test.cpp
Normal file
97
test/weak_ptr_alias_move_test.cpp
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
|
||||||
|
// weak_ptr_alias_move_test.cpp
|
||||||
|
//
|
||||||
|
// Copyright 2007, 2019 Peter Dimov
|
||||||
|
//
|
||||||
|
// Distributed under the 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/core/lightweight_test.hpp>
|
||||||
|
#include <boost/weak_ptr.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||||
|
|
||||||
|
class incomplete;
|
||||||
|
|
||||||
|
struct X
|
||||||
|
{
|
||||||
|
int v_;
|
||||||
|
|
||||||
|
explicit X( int v ): v_( v )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~X()
|
||||||
|
{
|
||||||
|
v_ = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class P1, class P2> bool share_ownership( P1 const& p1, P2 const& p2 )
|
||||||
|
{
|
||||||
|
return !p1.owner_before( p2 ) && !p2.owner_before( p1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
boost::shared_ptr<float> p( new float );
|
||||||
|
boost::weak_ptr<float> p2( p );
|
||||||
|
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<int const volatile> p3( std::move( p2 ), &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p2.empty() );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr<incomplete> p;
|
||||||
|
boost::weak_ptr<incomplete> p2( p );
|
||||||
|
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<int const volatile> p3( std::move( p2 ), &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == 0 );
|
||||||
|
|
||||||
|
BOOST_TEST( p2.empty() );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr<X> p( new X( 5 ) );
|
||||||
|
boost::weak_ptr<X> p2( p );
|
||||||
|
|
||||||
|
boost::weak_ptr<int const volatile> p3( std::move( p2 ), &p2.lock()->v_ );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == &p->v_ );
|
||||||
|
|
||||||
|
BOOST_TEST( p2.empty() );
|
||||||
|
|
||||||
|
p.reset();
|
||||||
|
BOOST_TEST( p3.expired() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
203
test/weak_ptr_alias_test.cpp
Normal file
203
test/weak_ptr_alias_test.cpp
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
|
||||||
|
// weak_ptr_alias_test.cpp
|
||||||
|
//
|
||||||
|
// Copyright 2007, 2019 Peter Dimov
|
||||||
|
//
|
||||||
|
// Distributed under the 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/core/lightweight_test.hpp>
|
||||||
|
#include <boost/weak_ptr.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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class P1, class P2> bool share_ownership( P1 const& p1, P2 const& p2 )
|
||||||
|
{
|
||||||
|
return !p1.owner_before( p2 ) && !p2.owner_before( p1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
boost::shared_ptr<double> p( new double );
|
||||||
|
|
||||||
|
float m = 0;
|
||||||
|
boost::weak_ptr<float> p2( p, &m );
|
||||||
|
|
||||||
|
BOOST_TEST( p2.use_count() == p.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p, p2 ) );
|
||||||
|
BOOST_TEST( p2.lock().get() == &m );
|
||||||
|
|
||||||
|
{
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<int> p3( p2, &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p2.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p2, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == &m2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<int const> p3( p, &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == &m2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<int volatile> p3( p2, &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p2.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p2, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == &m2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<void> p3( p, &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == &m2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<void> p3( p2, &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p2.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p2, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == &m2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<void const volatile> p3( p, &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == &m2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<void const volatile> p3( p2, &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p2.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p2, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == &m2 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr<incomplete> p;
|
||||||
|
|
||||||
|
float m = 0;
|
||||||
|
boost::weak_ptr<float> p2( p, &m );
|
||||||
|
|
||||||
|
BOOST_TEST( p2.use_count() == p.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p, p2 ) );
|
||||||
|
|
||||||
|
{
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<int> p3( p2, &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p2.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p2, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<int const> p3( p, &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<int volatile> p3( p2, &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p2.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p2, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<void> p3( p, &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<void> p3( p2, &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p2.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p2, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<void const volatile> p3( p, &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int m2 = 0;
|
||||||
|
boost::weak_ptr<void const volatile> p3( p2, &m2 );
|
||||||
|
|
||||||
|
BOOST_TEST( p3.use_count() == p2.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p2, p3 ) );
|
||||||
|
BOOST_TEST( p3.lock().get() == 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::shared_ptr<X> p( new X( 5 ) );
|
||||||
|
|
||||||
|
boost::weak_ptr<int const> p2( p, &p->v_ );
|
||||||
|
|
||||||
|
BOOST_TEST( p2.use_count() == p.use_count() );
|
||||||
|
BOOST_TEST( share_ownership( p, p2 ) );
|
||||||
|
BOOST_TEST( p2.lock().get() == &p->v_ );
|
||||||
|
|
||||||
|
p.reset();
|
||||||
|
BOOST_TEST( p2.expired() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
Reference in New Issue
Block a user