Compare commits

...

26 Commits

Author SHA1 Message Date
Peter Dimov
b6b49ef591 Split g++ 8 Travis job, because log length 2019-04-22 02:19:27 +03:00
Peter Dimov
2122c7753c Avoid memcpy over a spinlock, because g++ 8 warns 2019-04-22 02:17:28 +03:00
Peter Dimov
7c76fb385d Add clang-win to Appveyor 2019-04-22 00:59:38 +03:00
Peter Dimov
372fac679b Remove _internal_aliasing_assign 2019-04-21 23:13:06 +03:00
Peter Dimov
e3adcaed1e Add revision history 2019-04-21 23:00:24 +03:00
Peter Dimov
016e682af6 Document weak_ptr aliasing constructors and empty 2019-04-21 22:52:44 +03:00
Peter Dimov
78e095d761 Disable tests that don't compile on msvc-8.0 2019-04-21 22:50:24 +03:00
Peter Dimov
eb8a91cb46 Add tests for the weak_ptr aliasing constructors 2019-04-21 22:44:09 +03:00
Peter Dimov
513cd15378 Add aliasing constructors to weak_ptr. Closes #67. 2019-04-21 22:43:04 +03:00
Peter Dimov
7bfa6a1f3d Fix typo 2019-04-21 21:33:55 +03:00
Peter Dimov
8120bb44cb Add rvalue pointer casts (closes #66) 2019-04-21 00:47:36 +03:00
Peter Dimov
18974ea2db Add cast tests to intrusive_ptr_test 2019-04-20 18:54:13 +03:00
Peter Dimov
2a4aca403a Merge branch 'develop' into feature/intrusive-ptr-tests 2019-04-20 18:15:31 +03:00
Peter Dimov
4d0d81477c Update msvc workarounds for 14.2 2019-04-20 18:15:05 +03:00
Peter Dimov
1725e26f70 Add assignment tests to intrusive_ptr_test 2019-04-20 18:02:11 +03:00
Peter Dimov
47fffaf11c Switch Appveyor to 2015 image 2019-04-14 18:24:21 +03:00
Peter Dimov
7f0323a347 Merge branch 'develop' of https://github.com/boostorg/smart_ptr into develop 2019-03-25 19:25:44 +02:00
Peter Dimov
6d8ea0f0c4 Remove project-id from doc/Jamfile 2019-03-25 19:25:33 +02:00
Glen Fernandes
d10299159a More asciidoctor changes
Reinstate the none/blank trick, but remove the blank line after it in local_shared_ptr.adoc that causes the problem. Also use that trick in place of the nested DLs which don't work with Asciidoctor 2
2019-03-24 23:41:08 -04:00
Glen Fernandes
adcab0e313 Update asciidoc to work with Asciidoctor 2.0 2019-03-24 20:28:17 -04:00
Peter Dimov
4fbb9ff076 Merge branch 'develop' 2019-03-02 21:08:43 +02:00
Glen Fernandes
8ccb36dfcf Use traits from TypeTraits 2019-02-22 19:36:32 -05:00
Glen Fernandes
fde2e91443 Use traits from TypeTraits 2019-02-22 19:01:55 -05:00
Peter Dimov
aa1341a6a2 Add BOOST_SP_NOEXCEPT to sp_counted_base_nt.hpp 2019-01-28 21:24:09 +02:00
Peter Dimov
053779f3ee Add BOOST_SP_NOEXCEPT to sp_counted_base_clang.hpp 2019-01-28 20:52:28 +02:00
Peter Dimov
51d8167fbf Add more BOOST_SP_NOEXCEPT 2019-01-28 18:46:39 +02:00
42 changed files with 1313 additions and 561 deletions

View File

@@ -107,7 +107,17 @@ matrix:
- os: linux
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:
apt:
packages:

View File

@@ -1,4 +1,4 @@
# Copyright 2016-2018 Peter Dimov
# Copyright 2016-2019 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)
@@ -14,28 +14,28 @@ branches:
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
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
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1
TOOLSET: msvc-14.1,clang-win
CXXSTD: 14,17
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\cygwin\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\cygwin64\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\mingw\bin;
TOOLSET: gcc
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;
TOOLSET: gcc
CXXSTD: 03,11,14,1z

View File

@@ -5,8 +5,6 @@
# 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 ;

View File

@@ -19,6 +19,8 @@ Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes
include::smart_ptr/introduction.adoc[]
include::smart_ptr/changelog.adoc[]
include::smart_ptr/scoped_ptr.adoc[]
include::smart_ptr/scoped_array.adoc[]

View 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()`

View File

@@ -11,7 +11,9 @@ http://www.boost.org/LICENSE_1_0.txt
[#introduction]
# Introduction
:idprefix: intro
:toc:
:toc-title:
: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

View File

@@ -77,7 +77,7 @@ namespace boost {
explicit operator bool () const noexcept;
void swap(intrusive_ptr & b) noexept;
void swap(intrusive_ptr & b) noexcept;
};
template<class T, class U>

View File

@@ -78,12 +78,13 @@ namespace boost {
```
intrusive_ref_counter() noexcept;
```
::
```
intrusive_ref_counter(const intrusive_ref_counter&) noexcept;
```
::
Postconditions::: `use_count() == 0`.
[none]
* {blank}
+
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
@@ -94,8 +95,10 @@ would increment the reference counter.
```
~intrusive_ref_counter();
```
::
Effects::: Destroys the counter object.
[none]
* {blank}
+
Effects:: Destroys the counter object.
NOTE: The destructor is protected so that the object can only be destroyed
through the `Derived` class.
@@ -105,16 +108,20 @@ through the `Derived` class.
```
intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept;
```
::
Effects::: Does nothing, reference counter is not modified.
[none]
* {blank}
+
Effects:: Does nothing, reference counter is not modified.
### use_count
```
unsigned int use_count() const noexcept;
```
::
Returns::: The current value of the reference counter.
[none]
* {blank}
+
Returns:: The current value of the reference counter.
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(
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
```
::
Effects::: Increments the reference counter.
[none]
* {blank}
+
Effects:: Increments the reference counter.
### intrusive_ptr_release
@@ -137,6 +146,8 @@ 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
[none]
* {blank}
+
Effects:: Decrements the reference counter. If the reference counter reaches
0, calls `delete static_cast<const Derived*>(p)`.

View File

@@ -716,4 +716,3 @@ template<class D, class T>
* {blank}
+
Returns:: If `*this` owns a `shared_ptr` instance `p`, `get_deleter<D>( p )`, otherwise 0.

View File

@@ -174,17 +174,18 @@ the reference counts.
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
[none]
* {blank}
+
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
Returns:: A `shared_ptr` to an object of type `T`, constructed from
`args\...`.
Examples:::
Examples::
* `auto p = make_shared<int>();`
* `auto p = make_shared<std::vector<int> >(16, 1);`
@@ -192,17 +193,18 @@ Examples:::
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
[none]
* {blank}
+
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
Returns:: A `shared_ptr` to a sequence of `n` value-initialized objects of
type `U`.
Examples:::
Examples::
* `auto p = make_shared<double[]>(1024);`
* `auto p = make_shared<double[][2][2]>(6);`
@@ -210,17 +212,18 @@ Examples:::
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
[none]
* {blank}
+
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
Returns:: A `shared_ptr` to a sequence of `N` value-initialized objects of
type `U`.
Examples:::
Examples::
* `auto p = make_shared<double[1024]>();`
* `auto p = make_shared<double[6][2][2]>();`
@@ -228,17 +231,18 @@ Examples:::
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
[none]
* {blank}
+
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
Returns:: A `shared_ptr` to a sequence of `n` objects of type `U`, each
initialized to `v`.
Examples:::
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});`
@@ -247,17 +251,18 @@ Examples:::
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
[none]
* {blank}
+
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
Returns:: A `shared_ptr` to a sequence of `N` objects of type `U`, each
initialized to `v`.
Examples:::
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});`
@@ -266,30 +271,32 @@ Examples:::
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
[none]
* {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]`.
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.
Example::: `auto p = make_shared_noinit<double[1024]>();`
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
[none]
* {blank}
+
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
Returns:: A `shared_ptr` to a sequence of `_n_` default-initialized objects
of type `U`.
Example::: `auto p = make_shared_noinit<double[]>(1024);`
Example:: `auto p = make_shared_noinit<double[]>(1024);`

View File

@@ -68,48 +68,58 @@ namespace boost {
template<class T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args);
```
::
Remarks::: These overloads shall only participate in overload resolution when
[none]
* {blank}
+
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>();`
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
[none]
* {blank}
+
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});`
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
[none]
* {blank}
+
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);`
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
[none]
* {blank}
+
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]>();`
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
[none]
* {blank}
+
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);`
Returns:: `std::unique_ptr<U[]>(new U[n])`.
Example:: `auto p = make_unique_noinit<double[]>(1024);`

View File

@@ -78,23 +78,29 @@ namespace boost {
```
template<class T, class U> T* static_pointer_cast(U* p) noexcept;
```
::
Returns::: `static_cast<T*>(p)`
[none]
* {blank}
+
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)`
[none]
* {blank}
+
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
[none]
* {blank}
+
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
@@ -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;
```
::
Returns::: `dynamic_cast<T*>(p)`
[none]
* {blank}
+
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)`
[none]
* {blank}
+
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:::
[none]
* {blank}
+
Requires::
* The expression `static_cast<T*>((U*)0)` must be well-formed.
* `T` must have a virtual destructor.
Returns:::
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()));`.
@@ -135,23 +147,29 @@ std::unique_ptr<T>::element_type*>(p.release()));`.
```
template<class T, class U> T* const_pointer_cast(U* p) noexcept;
```
::
Returns::: `const_cast<T*>(p)`
[none]
* {blank}
+
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)`
[none]
* {blank}
+
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
[none]
* {blank}
+
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
@@ -159,23 +177,29 @@ std::unique_ptr<T>::element_type*>(p.release()))`.
```
template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
```
::
Returns::: `reinterpret_cast<T*>(p)`
[none]
* {blank}
+
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)`
[none]
* {blank}
+
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
[none]
* {blank}
+
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
@@ -210,4 +234,4 @@ int main()
delete ptr;
}
```
```

View File

@@ -105,42 +105,50 @@ Type:: Provides the type of the stored pointer.
```
explicit shared_array(T* p = 0);
```
::
Effects::: Constructs a `shared_array`, storing a copy of `p`, which must be a
[none]
* {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.
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.
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`.
[none]
* {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
pointed to by `p`, the object `d` is used in the statement `d(p)`.
Requires:::
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.
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
[none]
* {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
initial use count.
Requires::: `T` is a complete type.
Requires:: `T` is a complete type.
### Destructor
```
~shared_array() noexcept;
```
::
Effects::: Decrements the use count. Then, if the use count is 0, deletes the
[none]
* {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
a value of 0 is harmless.
@@ -149,60 +157,70 @@ a value of 0 is harmless.
```
shared_array& operator=(const shared_array& v) noexcept;
```
::
Effects::: Constructs a new `shared_array` as described above, then replaces
[none]
* {blank}
+
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`.
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
[none]
* {blank}
+
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.
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
[none]
* {blank}
+
Effects:: Constructs a new `shared_array` as described above, then replaces
this `shared_array` with the new one, destroying the replaced object.
Requires:::
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.
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
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.
Requires:: `T` is a complete type.
### get
```
T* get() const noexcept;
```
::
Returns::: The stored pointer.
[none]
* {blank}
+
Returns:: The stored pointer.
### unique
```
bool unique() const noexcept;
```
::
Returns::: `true` if no other `shared_array` is sharing ownership of the
[none]
* {blank}
+
Returns:: `true` if no other `shared_array` is sharing ownership of the
stored pointer, `false` otherwise.
### use_count
@@ -210,8 +228,10 @@ stored pointer, `false` otherwise.
```
long use_count() const noexcept;
```
::
Returns::: The number of `shared_array` objects sharing ownership of the
[none]
* {blank}
+
Returns:: The number of `shared_array` objects sharing ownership of the
stored pointer.
### Conversions
@@ -219,17 +239,21 @@ stored pointer.
```
explicit operator bool() const noexcept;
```
::
Returns::: `get() != 0`.
Requires::: `T` is a complete type.
[none]
* {blank}
+
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.
[none]
* {blank}
+
Effects:: Exchanges the contents of the two smart pointers.
## Free Functions
@@ -247,8 +271,10 @@ template<class T> bool
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
[none]
* {blank}
+
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
@@ -265,6 +291,8 @@ mandates that relational operations on pointers are unspecified (5.9
template<class T>
void swap(shared_array<T>& a, shared_array<T>& b) noexcept;
```
::
Returns::: `a.swap(b)`.
Requires::: `T` is a complete type.
[none]
* {blank}
+
Returns:: `a.swap(b)`.
Requires:: `T` is a complete type.

View File

@@ -132,7 +132,6 @@ namespace boost {
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);
@@ -373,7 +372,7 @@ 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`.
Effects:: Copy-constructs a `shared_ptr` from `r`, while storing `p` instead.
Postconditions:: `get() == p && use_count() == r.use_count()`.

View File

@@ -88,6 +88,10 @@ namespace boost {
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 & operator=(weak_ptr const & r) noexcept;
@@ -98,6 +102,8 @@ namespace boost {
long use_count() const noexcept;
bool expired() const noexcept;
bool empty() const noexcept;
shared_ptr<T> lock() const 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.
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
```
~weak_ptr() noexcept;
@@ -204,6 +225,17 @@ bool expired() const noexcept;
+
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
```
shared_ptr<T> lock() const noexcept;

View File

@@ -1,5 +1,5 @@
/*
Copyright 2017 Glen Joseph Fernandes
Copyright 2017-2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
@@ -14,22 +14,6 @@ Distributed under the Boost Software License, Version 1.0.
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 BOOST_SYMBOL_VISIBLE lsp_array_base
: public local_counted_base {
public:
@@ -84,15 +68,16 @@ private:
} /* detail */
template<class T, class A>
inline typename detail::lsp_if_array<T>::type
inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator, std::size_t count)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename remove_extent<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;
std::size_t size = count * detail::sp_array_count<type, scalar>::value;
detail::sp_array_result<other, base> result(allocator, size);
base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node);
@@ -105,15 +90,16 @@ allocate_local_shared(const A& allocator, std::size_t count)
}
template<class T, class A>
inline typename detail::lsp_if_size_array<T>::type
inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<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 remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T, scalar>::value
};
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);
@@ -128,22 +114,25 @@ allocate_local_shared(const A& allocator)
}
template<class T, class A>
inline typename detail::lsp_if_array<T>::type
inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator, std::size_t count,
const typename detail::sp_array_element<T>::type& value)
const typename remove_extent<T>::type& value)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename remove_extent<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;
enum {
total = detail::sp_array_count<type, scalar>::value
};
std::size_t size = count * total;
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);
reinterpret_cast<const scalar*>(&value), total, start);
detail::lsp_array_base& local = node->state().base();
local.set(node);
result.release();
@@ -152,16 +141,17 @@ allocate_local_shared(const A& allocator, std::size_t count,
}
template<class T, class A>
inline typename detail::lsp_if_size_array<T>::type
inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator,
const typename detail::sp_array_element<T>::type& value)
const typename remove_extent<T>::type& value)
{
enum {
size = detail::sp_array_count<T>::value
};
typedef typename detail::sp_array_element<T>::type type;
typedef typename remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T, scalar>::value
};
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);
@@ -169,7 +159,7 @@ allocate_local_shared(const A& allocator,
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::sp_array_count<type, scalar>::value, start);
detail::lsp_array_base& local = node->state().base();
local.set(node);
result.release();
@@ -178,15 +168,16 @@ allocate_local_shared(const A& allocator,
}
template<class T, class A>
inline typename detail::lsp_if_array<T>::type
inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared_noinit(const A& allocator, std::size_t count)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename remove_extent<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;
std::size_t size = count * detail::sp_array_count<type, scalar>::value;
detail::sp_array_result<other, base> result(allocator, size);
base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node);
@@ -200,15 +191,16 @@ allocate_local_shared_noinit(const A& allocator, std::size_t count)
}
template<class T, class A>
inline typename detail::lsp_if_size_array<T>::type
inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<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 remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T, scalar>::value
};
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);

View File

@@ -1,5 +1,5 @@
/*
Copyright 2012-2018 Glen Joseph Fernandes
Copyright 2012-2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
@@ -10,99 +10,30 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/is_bounded_array.hpp>
#include <boost/type_traits/is_unbounded_array.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/remove_all_extents.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_extent.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;
typedef typename boost::remove_cv<typename
boost::remove_all_extents<T>::type>::type 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>
template<class T, class U>
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
value = sizeof(T) / sizeof(U)
};
};
@@ -139,20 +70,13 @@ 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
inline typename boost::enable_if_<!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 &&
inline typename boost::enable_if_<!E &&
!boost::has_trivial_destructor<T>::value>::type
sp_array_destroy(A&, T* ptr, std::size_t size)
{
@@ -163,7 +87,7 @@ sp_array_destroy(A&, T* ptr, std::size_t size)
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<bool E, class A, class T>
inline typename sp_enable<E>::type
inline typename boost::enable_if_<E>::type
sp_array_destroy(A& allocator, T* ptr, std::size_t size)
{
while (size > 0) {
@@ -198,7 +122,7 @@ private:
};
template<bool E, class A, class T>
inline typename sp_enable<!E &&
inline typename boost::enable_if_<!E &&
boost::has_trivial_constructor<T>::value &&
boost::has_trivial_assign<T>::value &&
boost::has_trivial_destructor<T>::value>::type
@@ -210,7 +134,7 @@ sp_array_construct(A&, T* ptr, std::size_t size)
}
template<bool E, class A, class T>
inline typename sp_enable<!E &&
inline typename boost::enable_if_<!E &&
boost::has_trivial_constructor<T>::value &&
boost::has_trivial_assign<T>::value &&
boost::has_trivial_destructor<T>::value>::type
@@ -223,7 +147,7 @@ sp_array_construct(A&, T* ptr, std::size_t size, const T* list,
}
template<bool E, class A, class T>
inline typename sp_enable<!E &&
inline typename boost::enable_if_<!E &&
!(boost::has_trivial_constructor<T>::value &&
boost::has_trivial_assign<T>::value &&
boost::has_trivial_destructor<T>::value)>::type
@@ -237,7 +161,7 @@ sp_array_construct(A& none, T* ptr, std::size_t size)
}
template<bool E, class A, class T>
inline typename sp_enable<!E &&
inline typename boost::enable_if_<!E &&
!(boost::has_trivial_constructor<T>::value &&
boost::has_trivial_assign<T>::value &&
boost::has_trivial_destructor<T>::value)>::type
@@ -253,7 +177,7 @@ sp_array_construct(A& none, T* ptr, std::size_t size, const T* list,
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<bool E, class A, class T>
inline typename sp_enable<E>::type
inline typename boost::enable_if_<E>::type
sp_array_construct(A& allocator, T* ptr, std::size_t size)
{
sp_destroyer<E, A, T> hold(allocator, ptr);
@@ -264,7 +188,7 @@ sp_array_construct(A& allocator, T* ptr, std::size_t size)
}
template<bool E, class A, class T>
inline typename sp_enable<E>::type
inline typename boost::enable_if_<E>::type
sp_array_construct(A& allocator, T* ptr, std::size_t size, const T* list,
std::size_t count)
{
@@ -278,11 +202,13 @@ sp_array_construct(A& allocator, T* ptr, std::size_t size, const T* list,
#endif
template<class A, class T>
inline typename sp_enable<boost::has_trivial_constructor<T>::value>::type
inline typename
boost::enable_if_<boost::has_trivial_constructor<T>::value>::type
sp_array_default(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { }
template<class A, class T>
inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type
inline typename
boost::enable_if_<!boost::has_trivial_constructor<T>::value>::type
sp_array_default(A& none, T* ptr, std::size_t size)
{
sp_destroyer<false, A, T> hold(none, ptr);
@@ -455,27 +381,27 @@ public:
return state_;
}
virtual void dispose() {
virtual void dispose() BOOST_SP_NOEXCEPT {
sp_array_destroy<E>(state_.allocator(),
sp_array_start<sp_array_base, type>(this), state_.size());
}
virtual void destroy() {
virtual void destroy() BOOST_SP_NOEXCEPT {
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&) {
virtual void* get_deleter(const sp_typeinfo&) BOOST_SP_NOEXCEPT {
return 0;
}
virtual void* get_local_deleter(const sp_typeinfo&) {
virtual void* get_local_deleter(const sp_typeinfo&) BOOST_SP_NOEXCEPT {
return 0;
}
virtual void* get_untyped_deleter() {
virtual void* get_untyped_deleter() BOOST_SP_NOEXCEPT {
return 0;
}
@@ -516,15 +442,15 @@ private:
} /* detail */
template<class T, class A>
inline typename detail::sp_if_array<T>::type
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator, std::size_t count)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename remove_extent<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;
std::size_t size = count * detail::sp_array_count<type, scalar>::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);
@@ -535,15 +461,15 @@ allocate_shared(const A& allocator, std::size_t count)
}
template<class T, class A>
inline typename detail::sp_if_size_array<T>::type
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<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 remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T, scalar>::value
};
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);
@@ -556,38 +482,40 @@ allocate_shared(const A& allocator)
}
template<class T, class A>
inline typename detail::sp_if_array<T>::type
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator, std::size_t count,
const typename detail::sp_array_element<T>::type& value)
const typename remove_extent<T>::type& value)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename remove_extent<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;
enum {
total = detail::sp_array_count<type, scalar>::value
};
std::size_t size = count * total;
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);
reinterpret_cast<const scalar*>(&value), total, 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
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator,
const typename detail::sp_array_element<T>::type& value)
const typename remove_extent<T>::type& value)
{
enum {
size = detail::sp_array_count<T>::value
};
typedef typename detail::sp_array_element<T>::type type;
typedef typename remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T, scalar>::value
};
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);
@@ -595,22 +523,22 @@ allocate_shared(const A& allocator,
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::sp_array_count<type, scalar>::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
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
allocate_shared_noinit(const A& allocator, std::size_t count)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename remove_extent<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;
std::size_t size = count * detail::sp_array_count<type, scalar>::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);
@@ -622,15 +550,15 @@ allocate_shared_noinit(const A& allocator, std::size_t count)
}
template<class T, class A>
inline typename detail::sp_if_size_array<T>::type
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<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 remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T, scalar>::value
};
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);

View File

@@ -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
atomic_shared_ptr() BOOST_SP_NOEXCEPT
@@ -71,8 +76,6 @@ public:
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 ) )
@@ -84,6 +87,8 @@ public:
std::memcpy( &l_, &init, sizeof( init ) );
}
#endif
atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
{
boost::detail::spinlock::scoped_lock lock( l_ );

View File

@@ -101,13 +101,13 @@ private:
public:
explicit local_counted_impl( shared_count const& pn ): pn_( pn )
explicit local_counted_impl( shared_count const& pn ) BOOST_SP_NOEXCEPT: pn_( pn )
{
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
explicit local_counted_impl( shared_count && pn ): pn_( std::move(pn) )
explicit local_counted_impl( shared_count && pn ) BOOST_SP_NOEXCEPT: pn_( std::move(pn) )
{
}

View File

@@ -50,7 +50,7 @@ public:
#endif
D& deleter()
D& deleter() BOOST_SP_NOEXCEPT
{
return d_;
}
@@ -74,12 +74,12 @@ template<> class local_sp_deleter<void>
{
};
template<class D> D * get_local_deleter( local_sp_deleter<D> * p )
template<class D> D * get_local_deleter( local_sp_deleter<D> * p ) BOOST_SP_NOEXCEPT
{
return &p->deleter();
}
inline void * get_local_deleter( local_sp_deleter<void> * /*p*/ )
inline void * get_local_deleter( local_sp_deleter<void> * /*p*/ ) BOOST_SP_NOEXCEPT
{
return 0;
}

View File

@@ -29,7 +29,8 @@
#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>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config/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
@@ -118,14 +119,14 @@ private:
public:
BOOST_CONSTEXPR shared_count(): pi_(0) // nothrow
BOOST_CONSTEXPR shared_count() BOOST_SP_NOEXCEPT: pi_(0)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{
}
BOOST_CONSTEXPR explicit shared_count( sp_counted_base * pi ): pi_( pi ) // nothrow
BOOST_CONSTEXPR explicit shared_count( sp_counted_base * pi ) BOOST_SP_NOEXCEPT: pi_( pi )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
@@ -421,7 +422,7 @@ public:
r.release();
}
~shared_count() // nothrow
~shared_count() /*BOOST_SP_NOEXCEPT*/
{
if( pi_ != 0 ) pi_->release();
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
@@ -429,7 +430,7 @@ public:
#endif
}
shared_count(shared_count const & r): pi_(r.pi_) // nothrow
shared_count(shared_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
@@ -439,7 +440,7 @@ public:
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
shared_count(shared_count && r): pi_(r.pi_) // nothrow
shared_count(shared_count && r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
@@ -450,9 +451,9 @@ public:
#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( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPT; // constructs an empty *this when r.use_count() == 0
shared_count & operator= (shared_count const & r) // nothrow
shared_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPT
{
sp_counted_base * tmp = r.pi_;
@@ -466,49 +467,49 @@ public:
return *this;
}
void swap(shared_count & r) // nothrow
void swap(shared_count & r) BOOST_SP_NOEXCEPT
{
sp_counted_base * tmp = r.pi_;
r.pi_ = pi_;
pi_ = tmp;
}
long use_count() const // nothrow
long use_count() const BOOST_SP_NOEXCEPT
{
return pi_ != 0? pi_->use_count(): 0;
}
bool unique() const // nothrow
bool unique() const BOOST_SP_NOEXCEPT
{
return use_count() == 1;
}
bool empty() const // nothrow
bool empty() const BOOST_SP_NOEXCEPT
{
return pi_ == 0;
}
friend inline bool operator==(shared_count const & a, shared_count const & b)
friend inline bool operator==(shared_count const & a, shared_count const & b) BOOST_SP_NOEXCEPT
{
return a.pi_ == b.pi_;
}
friend inline bool operator<(shared_count const & a, shared_count const & b)
friend inline bool operator<(shared_count const & a, shared_count const & b) BOOST_SP_NOEXCEPT
{
return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
}
void * get_deleter( sp_typeinfo const & ti ) const
void * get_deleter( sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
{
return pi_? pi_->get_deleter( ti ): 0;
}
void * get_local_deleter( sp_typeinfo const & ti ) const
void * get_local_deleter( sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
{
return pi_? pi_->get_local_deleter( ti ): 0;
}
void * get_untyped_deleter() const
void * get_untyped_deleter() const BOOST_SP_NOEXCEPT
{
return pi_? pi_->get_untyped_deleter(): 0;
}
@@ -529,14 +530,14 @@ private:
public:
BOOST_CONSTEXPR weak_count(): pi_(0) // nothrow
BOOST_CONSTEXPR weak_count() BOOST_SP_NOEXCEPT: pi_(0)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
{
}
weak_count(shared_count const & r): pi_(r.pi_) // nothrow
weak_count(shared_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
@@ -544,7 +545,7 @@ public:
if(pi_ != 0) pi_->weak_add_ref();
}
weak_count(weak_count const & r): pi_(r.pi_) // nothrow
weak_count(weak_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
@@ -556,7 +557,7 @@ public:
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
weak_count(weak_count && r): pi_(r.pi_) // nothrow
weak_count(weak_count && r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
@@ -566,7 +567,7 @@ public:
#endif
~weak_count() // nothrow
~weak_count() /*BOOST_SP_NOEXCEPT*/
{
if(pi_ != 0) pi_->weak_release();
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
@@ -574,7 +575,7 @@ public:
#endif
}
weak_count & operator= (shared_count const & r) // nothrow
weak_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPT
{
sp_counted_base * tmp = r.pi_;
@@ -588,7 +589,7 @@ public:
return *this;
}
weak_count & operator= (weak_count const & r) // nothrow
weak_count & operator= (weak_count const & r) BOOST_SP_NOEXCEPT
{
sp_counted_base * tmp = r.pi_;
@@ -602,29 +603,29 @@ public:
return *this;
}
void swap(weak_count & r) // nothrow
void swap(weak_count & r) BOOST_SP_NOEXCEPT
{
sp_counted_base * tmp = r.pi_;
r.pi_ = pi_;
pi_ = tmp;
}
long use_count() const // nothrow
long use_count() const BOOST_SP_NOEXCEPT
{
return pi_ != 0? pi_->use_count(): 0;
}
bool empty() const // nothrow
bool empty() const BOOST_SP_NOEXCEPT
{
return pi_ == 0;
}
friend inline bool operator==(weak_count const & a, weak_count const & b)
friend inline bool operator==(weak_count const & a, weak_count const & b) BOOST_SP_NOEXCEPT
{
return a.pi_ == b.pi_;
}
friend inline bool operator<(weak_count const & a, weak_count const & b)
friend inline bool operator<(weak_count const & a, weak_count const & b) BOOST_SP_NOEXCEPT
{
return std::less<sp_counted_base *>()(a.pi_, b.pi_);
}
@@ -641,7 +642,7 @@ inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
}
}
inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ )
inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPT: pi_( r.pi_ )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif

View File

@@ -16,6 +16,7 @@
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
@@ -27,17 +28,17 @@ namespace detail
typedef _Atomic( boost::int_least32_t ) atomic_int_least32_t;
inline void atomic_increment( atomic_int_least32_t * pw )
inline void atomic_increment( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
__c11_atomic_fetch_add( pw, 1, __ATOMIC_RELAXED );
}
inline boost::int_least32_t atomic_decrement( atomic_int_least32_t * pw )
inline boost::int_least32_t atomic_decrement( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
return __c11_atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL );
}
inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t * pw )
inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
// long r = *pw;
// if( r != 0 ) ++*pw;
@@ -76,43 +77,43 @@ private:
public:
sp_counted_base()
sp_counted_base() BOOST_SP_NOEXCEPT
{
__c11_atomic_init( &use_count_, 1 );
__c11_atomic_init( &weak_count_, 1 );
}
virtual ~sp_counted_base() // nothrow
virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
virtual void dispose() BOOST_SP_NOEXCEPT = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
virtual void destroy() BOOST_SP_NOEXCEPT // 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;
virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
void add_ref_copy()
void add_ref_copy() BOOST_SP_NOEXCEPT
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
void release() BOOST_SP_NOEXCEPT
{
if( atomic_decrement( &use_count_ ) == 1 )
{
@@ -121,12 +122,12 @@ public:
}
}
void weak_add_ref() // nothrow
void weak_add_ref() BOOST_SP_NOEXCEPT
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
void weak_release() BOOST_SP_NOEXCEPT
{
if( atomic_decrement( &weak_count_ ) == 1 )
{
@@ -134,7 +135,7 @@ public:
}
}
long use_count() const // nothrow
long use_count() const BOOST_SP_NOEXCEPT
{
return __c11_atomic_load( const_cast< atomic_int_least32_t* >( &use_count_ ), __ATOMIC_ACQUIRE );
}

View File

@@ -19,6 +19,7 @@
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
@@ -40,43 +41,43 @@ private:
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
sp_counted_base() BOOST_SP_NOEXCEPT: use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
virtual void dispose() BOOST_SP_NOEXCEPT = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
virtual void destroy() BOOST_SP_NOEXCEPT // 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;
virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
void add_ref_copy()
void add_ref_copy() BOOST_SP_NOEXCEPT
{
++use_count_;
}
bool add_ref_lock() // true on success
bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
{
if( use_count_ == 0 ) return false;
++use_count_;
return true;
}
void release() // nothrow
void release() BOOST_SP_NOEXCEPT
{
if( --use_count_ == 0 )
{
@@ -85,12 +86,12 @@ public:
}
}
void weak_add_ref() // nothrow
void weak_add_ref() BOOST_SP_NOEXCEPT
{
++weak_count_;
}
void weak_release() // nothrow
void weak_release() BOOST_SP_NOEXCEPT
{
if( --weak_count_ == 0 )
{
@@ -98,7 +99,7 @@ public:
}
}
long use_count() const // nothrow
long use_count() const BOOST_SP_NOEXCEPT
{
return use_count_;
}

View File

@@ -16,6 +16,7 @@
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config.hpp>
#include <atomic>
#include <cstdint>
@@ -26,17 +27,17 @@ namespace boost
namespace detail
{
inline void atomic_increment( std::atomic_int_least32_t * pw )
inline void atomic_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
pw->fetch_add( 1, std::memory_order_relaxed );
}
inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw )
inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
return pw->fetch_sub( 1, std::memory_order_acq_rel );
}
inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_t * pw )
inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
// long r = *pw;
// if( r != 0 ) ++*pw;
@@ -70,41 +71,41 @@ private:
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
sp_counted_base() BOOST_SP_NOEXCEPT: use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
virtual void dispose() BOOST_SP_NOEXCEPT = 0;
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
virtual void destroy() BOOST_SP_NOEXCEPT
{
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;
virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
void add_ref_copy()
void add_ref_copy() BOOST_SP_NOEXCEPT
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
void release() BOOST_SP_NOEXCEPT
{
if( atomic_decrement( &use_count_ ) == 1 )
{
@@ -113,12 +114,12 @@ public:
}
}
void weak_add_ref() // nothrow
void weak_add_ref() BOOST_SP_NOEXCEPT
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
void weak_release() BOOST_SP_NOEXCEPT
{
if( atomic_decrement( &weak_count_ ) == 1 )
{
@@ -126,7 +127,7 @@ public:
}
}
long use_count() const // nothrow
long use_count() const BOOST_SP_NOEXCEPT
{
return use_count_.load( std::memory_order_acquire );
}

View File

@@ -26,6 +26,7 @@
#include <boost/checked_delete.hpp>
#include <boost/smart_ptr/detail/sp_counted_base.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/core/addressof.hpp>
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
@@ -55,12 +56,12 @@ namespace detail
template<class D> class local_sp_deleter;
template<class D> D * get_local_deleter( D * /*p*/ )
template<class D> D * get_local_deleter( D * /*p*/ ) BOOST_SP_NOEXCEPT
{
return 0;
}
template<class D> D * get_local_deleter( local_sp_deleter<D> * p );
template<class D> D * get_local_deleter( local_sp_deleter<D> * p ) BOOST_SP_NOEXCEPT;
//
@@ -84,7 +85,7 @@ public:
#endif
}
virtual void dispose() // nothrow
virtual void dispose() BOOST_SP_NOEXCEPT
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_destructor_hook( px_, sizeof(X), this );
@@ -92,17 +93,17 @@ public:
boost::checked_delete( px_ );
}
virtual void * get_deleter( sp_typeinfo const & )
virtual void * get_deleter( sp_typeinfo const & ) BOOST_SP_NOEXCEPT
{
return 0;
}
virtual void * get_local_deleter( sp_typeinfo const & )
virtual void * get_local_deleter( sp_typeinfo const & ) BOOST_SP_NOEXCEPT
{
return 0;
}
virtual void * get_untyped_deleter()
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT
{
return 0;
}
@@ -167,22 +168,22 @@ public:
{
}
virtual void dispose() // nothrow
virtual void dispose() BOOST_SP_NOEXCEPT
{
del( ptr );
}
virtual void * get_deleter( sp_typeinfo const & ti )
virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT
{
return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0;
}
virtual void * get_local_deleter( sp_typeinfo const & ti )
virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT
{
return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( del ) ): 0;
}
virtual void * get_untyped_deleter()
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT
{
return &reinterpret_cast<char&>( del );
}
@@ -241,12 +242,12 @@ public:
{
}
virtual void dispose() // nothrow
virtual void dispose() BOOST_SP_NOEXCEPT
{
d_( p_ );
}
virtual void destroy() // nothrow
virtual void destroy() BOOST_SP_NOEXCEPT
{
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
@@ -265,17 +266,17 @@ public:
a2.deallocate( this, 1 );
}
virtual void * get_deleter( sp_typeinfo const & ti )
virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT
{
return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast<char&>( d_ ): 0;
}
virtual void * get_local_deleter( sp_typeinfo const & ti )
virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT
{
return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( d_ ) ): 0;
}
virtual void * get_untyped_deleter()
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT
{
return &reinterpret_cast<char&>( d_ );
}

View File

@@ -16,6 +16,7 @@
//
#include <boost/smart_ptr/detail/yield_k.hpp>
#include <boost/config.hpp>
#include <atomic>
namespace boost
@@ -32,12 +33,12 @@ public:
public:
bool try_lock()
bool try_lock() BOOST_NOEXCEPT
{
return !v_.test_and_set( std::memory_order_acquire );
}
void lock()
void lock() BOOST_NOEXCEPT
{
for( unsigned k = 0; !try_lock(); ++k )
{
@@ -45,7 +46,7 @@ public:
}
}
void unlock()
void unlock() BOOST_NOEXCEPT
{
v_ .clear( std::memory_order_release );
}
@@ -63,12 +64,12 @@ public:
public:
explicit scoped_lock( spinlock & sp ): sp_( sp )
explicit scoped_lock( spinlock & sp ) BOOST_NOEXCEPT: sp_( sp )
{
sp.lock();
}
~scoped_lock()
~scoped_lock() /*BOOST_NOEXCEPT*/
{
sp_.unlock();
}

View File

@@ -78,7 +78,7 @@ namespace detail
#endif // !defined( BOOST_USE_WINDOWS_H ) && !BOOST_PLAT_WINDOWS_RUNTIME
inline void yield( unsigned k )
inline void yield( unsigned k ) BOOST_NOEXCEPT
{
if( k < 4 )
{

View File

@@ -144,8 +144,7 @@ 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);
boost::weak_ptr<T> result(p->enable_shared_from_raw::weak_from_this(), p);
return result;
}

View File

@@ -297,6 +297,8 @@ template<class T> T * get_pointer(intrusive_ptr<T> const & p) BOOST_SP_NOEXCEPT
return p.get();
}
// pointer casts
template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
{
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());
}
#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<<
#if !defined(BOOST_NO_IOSTREAM)

View File

@@ -1,6 +1,6 @@
/*
Copyright 2017 Peter Dimov
Copyright 2017 Glen Joseph Fernandes
Copyright 2017-2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
@@ -14,7 +14,8 @@ Distributed under the Boost Software License, Version 1.0.
namespace boost {
template<class T>
inline typename detail::lsp_if_size_array<T>::type
inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared()
{
return boost::allocate_local_shared<T>(std::allocator<typename
@@ -22,15 +23,17 @@ make_local_shared()
}
template<class T>
inline typename detail::lsp_if_size_array<T>::type
make_local_shared(const typename detail::sp_array_element<T>::type& value)
inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared(const typename remove_extent<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
inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared(std::size_t size)
{
return boost::allocate_local_shared<T>(std::allocator<typename
@@ -38,27 +41,30 @@ make_local_shared(std::size_t size)
}
template<class T>
inline typename detail::lsp_if_array<T>::type
inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared(std::size_t size,
const typename detail::sp_array_element<T>::type& value)
const typename remove_extent<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
inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared_noinit()
{
return allocate_local_shared_noinit<T>(std::allocator<typename
return boost::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
inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared_noinit(std::size_t size)
{
return allocate_local_shared_noinit<T>(std::allocator<typename
return boost::allocate_local_shared_noinit<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>(), size);
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2012-2017 Glen Joseph Fernandes
Copyright 2012-2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
@@ -13,7 +13,7 @@ Distributed under the Boost Software License, Version 1.0.
namespace boost {
template<class T>
inline typename detail::sp_if_size_array<T>::type
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
make_shared()
{
return boost::allocate_shared<T>(std::allocator<typename
@@ -21,15 +21,15 @@ make_shared()
}
template<class T>
inline typename detail::sp_if_size_array<T>::type
make_shared(const typename detail::sp_array_element<T>::type& value)
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
make_shared(const typename remove_extent<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
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
make_shared(std::size_t size)
{
return boost::allocate_shared<T>(std::allocator<typename
@@ -37,27 +37,26 @@ make_shared(std::size_t 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)
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
make_shared(std::size_t size, const typename remove_extent<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
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
make_shared_noinit()
{
return allocate_shared_noinit<T>(std::allocator<typename
return boost::allocate_shared_noinit<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>());
}
template<class T>
inline typename detail::sp_if_array<T>::type
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
make_shared_noinit(std::size_t size)
{
return allocate_shared_noinit<T>(std::allocator<typename
return boost::allocate_shared_noinit<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>(), size);
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2012-2015 Glen Joseph Fernandes
Copyright 2012-2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
@@ -8,59 +8,18 @@ Distributed under the Boost Software License, Version 1.0.
#ifndef BOOST_SMART_PTR_MAKE_UNIQUE_HPP
#define BOOST_SMART_PTR_MAKE_UNIQUE_HPP
#include <boost/config.hpp>
#include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_unbounded_array.hpp>
#include <boost/type_traits/remove_extent.hpp>
#include <boost/type_traits/remove_reference.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
inline typename enable_if_<!is_array<T>::value, std::unique_ptr<T> >::type
make_unique()
{
return std::unique_ptr<T>(new T());
@@ -68,7 +27,7 @@ make_unique()
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T, class... Args>
inline typename detail::up_if_object<T>::type
inline typename enable_if_<!is_array<T>::value, std::unique_ptr<T> >::type
make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
@@ -76,33 +35,33 @@ make_unique(Args&&... args)
#endif
template<class T>
inline typename detail::up_if_object<T>::type
make_unique(typename detail::up_remove_reference<T>::type&& value)
inline typename enable_if_<!is_array<T>::value, std::unique_ptr<T> >::type
make_unique(typename 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
inline typename enable_if_<!is_array<T>::value, std::unique_ptr<T> >::type
make_unique_noinit()
{
return std::unique_ptr<T>(new T);
}
template<class T>
inline typename detail::up_if_array<T>::type
inline typename enable_if_<is_unbounded_array<T>::value,
std::unique_ptr<T> >::type
make_unique(std::size_t size)
{
return std::unique_ptr<T>(new typename
detail::up_element<T>::type[size]());
return std::unique_ptr<T>(new typename remove_extent<T>::type[size]());
}
template<class T>
inline typename detail::up_if_array<T>::type
inline typename enable_if_<is_unbounded_array<T>::value,
std::unique_ptr<T> >::type
make_unique_noinit(std::size_t size)
{
return std::unique_ptr<T>(new typename
detail::up_element<T>::type[size]);
return std::unique_ptr<T>(new typename remove_extent<T>::type[size]);
}
} /* boost */

View File

@@ -797,7 +797,7 @@ public:
return px == r.px && pn == r.pn;
}
boost::detail::shared_count _internal_count() const BOOST_NOEXCEPT
boost::detail::shared_count _internal_count() const BOOST_SP_NOEXCEPT
{
return pn;
}
@@ -1022,7 +1022,7 @@ private:
public:
esft2_deleter_wrapper()
esft2_deleter_wrapper() BOOST_SP_NOEXCEPT
{
}

View File

@@ -137,6 +137,23 @@ public:
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)
template<class Y>
@@ -194,6 +211,11 @@ public:
return pn.empty();
}
bool empty() const BOOST_SP_NOEXCEPT // extension, not in std::weak_ptr
{
return pn.empty();
}
void reset() BOOST_SP_NOEXCEPT
{
this_type().swap(*this);
@@ -205,13 +227,6 @@ public:
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;

View File

@@ -158,18 +158,18 @@ 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_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_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 make_shared_array_throws_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run make_shared_array_esft_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run make_shared_array_noinit_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run make_shared_array_value_test.cpp : : : <toolset>msvc-8.0:<build>no ;
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_throws_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run allocate_shared_array_esft_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run allocate_shared_array_noinit_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run allocate_shared_array_value_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run allocate_shared_array_construct_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_test3.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 ;
@@ -275,7 +275,7 @@ run local_sp_fn_test.cpp ;
run lsp_convertible_test.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 ;
@@ -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>98 : : : <cxxstd>0x : abi_test_11_03 ;
run weak_ptr_alias_test.cpp ;
run weak_ptr_alias_move_test.cpp ;

View File

@@ -18,10 +18,10 @@
BOOST_PRAGMA_MESSAGE("Skipping test due to BOOST_NO_CXX11_CONSTEXPR")
int main() {}
#elif BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
#elif BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
// MSVC does not implement static initialization for constexpr
BOOST_PRAGMA_MESSAGE("Skipping test due to BOOST_MSVC < 1920")
// MSVC does not implement static initialization for constexpr constructors
BOOST_PRAGMA_MESSAGE("Skipping test due to BOOST_MSVC < 1930")
int main() {}
#elif defined(__clang__) && defined( BOOST_NO_CXX14_CONSTEXPR )

View File

@@ -41,7 +41,7 @@ class base
{
private:
boost::detail::atomic_count use_count_;
mutable boost::detail::atomic_count use_count_;
base(base const &);
base & operator=(base const &);
@@ -69,24 +69,24 @@ public:
#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_;
}
inline friend void intrusive_ptr_release(base * p)
inline friend void intrusive_ptr_release(base const * p)
{
if(--p->use_count_ == 0) delete p;
}
#else
void add_ref()
void add_ref() const
{
++use_count_;
}
void release()
void release() const
{
if(--use_count_ == 0) delete this;
}
@@ -103,12 +103,12 @@ long base::instances = 0;
namespace boost
{
inline void intrusive_ptr_add_ref(N::base * p)
inline void intrusive_ptr_add_ref(N::base const * p)
{
p->add_ref();
}
inline void intrusive_ptr_release(N::base * p)
inline void intrusive_ptr_release(N::base const * p)
{
p->release();
}
@@ -209,6 +209,58 @@ int main()
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();
}

View File

@@ -42,7 +42,7 @@ class base
{
private:
boost::detail::atomic_count use_count_;
mutable boost::detail::atomic_count use_count_;
base(base const &);
base & operator=(base const &);
@@ -70,24 +70,24 @@ public:
#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_;
}
inline friend void intrusive_ptr_release(base * p)
inline friend void intrusive_ptr_release(base const * p)
{
if(--p->use_count_ == 0) delete p;
}
#else
void add_ref()
void add_ref() const
{
++use_count_;
}
void release()
void release() const
{
if(--use_count_ == 0) delete this;
}
@@ -104,12 +104,12 @@ long base::instances = 0;
namespace boost
{
inline void intrusive_ptr_add_ref(N::base * p)
inline void intrusive_ptr_add_ref(N::base const * p)
{
p->add_ref();
}
inline void intrusive_ptr_release(N::base * p)
inline void intrusive_ptr_release(N::base const * p)
{
p->release();
}
@@ -303,14 +303,211 @@ namespace n_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()
{
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()
{
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()
@@ -707,15 +904,137 @@ namespace n_static_cast
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_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
{
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
@@ -779,6 +1098,7 @@ int main()
n_swap::test();
n_comparison::test();
n_static_cast::test();
n_const_cast::test();
n_dynamic_cast::test();
n_transitive::test();

View File

@@ -17,7 +17,7 @@
# undef HAVE_CONSTEXPR_INIT
#endif
#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
#if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
# undef HAVE_CONSTEXPR_INIT
#endif

View File

@@ -17,7 +17,7 @@
# undef HAVE_CONSTEXPR_INIT
#endif
#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
#if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
# undef HAVE_CONSTEXPR_INIT
#endif

View 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

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