Compare commits

...

10 Commits

Author SHA1 Message Date
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
14 changed files with 646 additions and 170 deletions

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. # Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
@@ -14,28 +14,28 @@ branches:
environment: environment:
matrix: matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0,msvc-12.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-14.0 TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-12.0,msvc-14.0
ADDRMD: 32,64 ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1 TOOLSET: msvc-14.1
CXXSTD: 14,17 CXXSTD: 14,17
ADDRMD: 32,64 ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\cygwin\bin; ADDPATH: C:\cygwin\bin;
TOOLSET: gcc TOOLSET: gcc
CXXSTD: 03,11,14,1z CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\cygwin64\bin; ADDPATH: C:\cygwin64\bin;
TOOLSET: gcc TOOLSET: gcc
CXXSTD: 03,11,14,1z CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\mingw\bin; ADDPATH: C:\mingw\bin;
TOOLSET: gcc TOOLSET: gcc
CXXSTD: 03,11,14,1z CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin; ADDPATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;
TOOLSET: gcc TOOLSET: gcc
CXXSTD: 03,11,14,1z CXXSTD: 03,11,14,1z

View File

@@ -5,8 +5,6 @@
# See accompanying file LICENSE_1_0.txt or copy at # See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt # http://www.boost.org/LICENSE_1_0.txt
project doc/smart_ptr ;
import asciidoctor ; import asciidoctor ;
html smart_ptr.html : smart_ptr.adoc ; html smart_ptr.html : smart_ptr.adoc ;

View File

@@ -78,12 +78,13 @@ namespace boost {
``` ```
intrusive_ref_counter() noexcept; intrusive_ref_counter() noexcept;
``` ```
::
``` ```
intrusive_ref_counter(const intrusive_ref_counter&) noexcept; intrusive_ref_counter(const intrusive_ref_counter&) noexcept;
``` ```
:: [none]
Postconditions::: `use_count() == 0`. * {blank}
+
Postconditions:: `use_count() == 0`.
NOTE: The pointer to the constructed object is expected to be passed to NOTE: The pointer to the constructed object is expected to be passed to
`intrusive_ptr` constructor, assignment operator or `reset` method, which `intrusive_ptr` constructor, assignment operator or `reset` method, which
@@ -94,8 +95,10 @@ would increment the reference counter.
``` ```
~intrusive_ref_counter(); ~intrusive_ref_counter();
``` ```
:: [none]
Effects::: Destroys the counter object. * {blank}
+
Effects:: Destroys the counter object.
NOTE: The destructor is protected so that the object can only be destroyed NOTE: The destructor is protected so that the object can only be destroyed
through the `Derived` class. through the `Derived` class.
@@ -105,16 +108,20 @@ through the `Derived` class.
``` ```
intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept; intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept;
``` ```
:: [none]
Effects::: Does nothing, reference counter is not modified. * {blank}
+
Effects:: Does nothing, reference counter is not modified.
### use_count ### use_count
``` ```
unsigned int use_count() const noexcept; unsigned int use_count() const noexcept;
``` ```
:: [none]
Returns::: The current value of the reference counter. * {blank}
+
Returns:: The current value of the reference counter.
NOTE: The returned value may not be actual in multi-threaded applications. NOTE: The returned value may not be actual in multi-threaded applications.
@@ -127,8 +134,10 @@ template<class Derived, class CounterPolicy>
void intrusive_ptr_add_ref( void intrusive_ptr_add_ref(
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept; const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
``` ```
:: [none]
Effects::: Increments the reference counter. * {blank}
+
Effects:: Increments the reference counter.
### intrusive_ptr_release ### intrusive_ptr_release
@@ -137,6 +146,8 @@ template<class Derived, class CounterPolicy>
void intrusive_ptr_release( void intrusive_ptr_release(
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept; const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
``` ```
:: [none]
Effects::: Decrements the reference counter. If the reference counter reaches * {blank}
+
Effects:: Decrements the reference counter. If the reference counter reaches
0, calls `delete static_cast<const Derived*>(p)`. 0, calls `delete static_cast<const Derived*>(p)`.

View File

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

View File

@@ -174,17 +174,18 @@ the reference counts.
template<class T, class... Args> template<class T, class... Args>
shared_ptr<T> make_shared(Args&&... args); shared_ptr<T> make_shared(Args&&... args);
``` ```
::
``` ```
template<class T, class A, class... Args> template<class T, class A, class... Args>
shared_ptr<T> allocate_shared(const A& a, Args&&... args); shared_ptr<T> allocate_shared(const A& a, Args&&... args);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is not an array type. `T` is not an array type.
Returns::: A `shared_ptr` to an object of type `T`, constructed from Returns:: A `shared_ptr` to an object of type `T`, constructed from
`args\...`. `args\...`.
Examples::: Examples::
* `auto p = make_shared<int>();` * `auto p = make_shared<int>();`
* `auto p = make_shared<std::vector<int> >(16, 1);` * `auto p = make_shared<std::vector<int> >(16, 1);`
@@ -192,17 +193,18 @@ Examples:::
template<class T> template<class T>
shared_ptr<T> make_shared(std::size_t n); shared_ptr<T> make_shared(std::size_t n);
``` ```
::
``` ```
template<class T, class A> template<class T, class A>
shared_ptr<T> allocate_shared(const A& a, std::size_t n); shared_ptr<T> allocate_shared(const A& a, std::size_t n);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is an array type of the form `U[]`. `T` is an array type of the form `U[]`.
Returns::: A `shared_ptr` to a sequence of `n` value-initialized objects of Returns:: A `shared_ptr` to a sequence of `n` value-initialized objects of
type `U`. type `U`.
Examples::: Examples::
* `auto p = make_shared<double[]>(1024);` * `auto p = make_shared<double[]>(1024);`
* `auto p = make_shared<double[][2][2]>(6);` * `auto p = make_shared<double[][2][2]>(6);`
@@ -210,17 +212,18 @@ Examples:::
template<class T> template<class T>
shared_ptr<T> make_shared(); shared_ptr<T> make_shared();
``` ```
::
``` ```
template<class T, class A> template<class T, class A>
shared_ptr<T> allocate_shared(const A& a); shared_ptr<T> allocate_shared(const A& a);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is an array type of the form `U[N]`. `T` is an array type of the form `U[N]`.
Returns::: A `shared_ptr` to a sequence of `N` value-initialized objects of Returns:: A `shared_ptr` to a sequence of `N` value-initialized objects of
type `U`. type `U`.
Examples::: Examples::
* `auto p = make_shared<double[1024]>();` * `auto p = make_shared<double[1024]>();`
* `auto p = make_shared<double[6][2][2]>();` * `auto p = make_shared<double[6][2][2]>();`
@@ -228,17 +231,18 @@ Examples:::
template<class T> shared_ptr<T> template<class T> shared_ptr<T>
make_shared(std::size_t n, const remove_extent_t<T>& v); make_shared(std::size_t n, const remove_extent_t<T>& v);
``` ```
::
``` ```
template<class T, class A> shared_ptr<T> template<class T, class A> shared_ptr<T>
allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v); allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is an array type of the form `U[]`. `T` is an array type of the form `U[]`.
Returns::: A `shared_ptr` to a sequence of `n` objects of type `U`, each Returns:: A `shared_ptr` to a sequence of `n` objects of type `U`, each
initialized to `v`. initialized to `v`.
Examples::: Examples::
* `auto p = make_shared<double[]>(1024, 1.0);` * `auto p = make_shared<double[]>(1024, 1.0);`
* `auto p = make_shared<double[][2]>(6, {1.0, 0.0});` * `auto p = make_shared<double[][2]>(6, {1.0, 0.0});`
* `auto p = make_shared<std::vector<int>[]>(4, {1, 2});` * `auto p = make_shared<std::vector<int>[]>(4, {1, 2});`
@@ -247,17 +251,18 @@ Examples:::
template<class T> template<class T>
shared_ptr<T> make_shared(const remove_extent_t<T>& v); shared_ptr<T> make_shared(const remove_extent_t<T>& v);
``` ```
::
``` ```
template<class T, class A> template<class T, class A>
shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v); shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is an array type of the form `U[N]`. `T` is an array type of the form `U[N]`.
Returns::: A `shared_ptr` to a sequence of `N` objects of type `U`, each Returns:: A `shared_ptr` to a sequence of `N` objects of type `U`, each
initialized to `v`. initialized to `v`.
Examples::: Examples::
* `auto p = make_shared<double[1024]>(1.0);` * `auto p = make_shared<double[1024]>(1.0);`
* `auto p = make_shared<double[6][2]>({1.0, 0.0});` * `auto p = make_shared<double[6][2]>({1.0, 0.0});`
* `auto p = make_shared<std::vector<int>[4]>({1, 2});` * `auto p = make_shared<std::vector<int>[4]>({1, 2});`
@@ -266,30 +271,32 @@ Examples:::
template<class T> template<class T>
shared_ptr<T> make_shared_noinit(); shared_ptr<T> make_shared_noinit();
``` ```
::
``` ```
template<class T, class A> template<class T, class A>
shared_ptr<T> allocate_shared_noinit(const A& a); shared_ptr<T> allocate_shared_noinit(const A& a);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is not an array type, or an array type of the `U[N]`. `T` is not an array type, or an array type of the `U[N]`.
Returns::: A `shared_ptr` to a default-initialized object of type `T`, or a Returns:: A `shared_ptr` to a default-initialized object of type `T`, or a
sequence of `N` default-initialized objects of type `U`, respectively. sequence of `N` default-initialized objects of type `U`, respectively.
Example::: `auto p = make_shared_noinit<double[1024]>();` Example:: `auto p = make_shared_noinit<double[1024]>();`
``` ```
template<class T> template<class T>
shared_ptr<T> make_shared_noinit(std::size_t n); shared_ptr<T> make_shared_noinit(std::size_t n);
``` ```
::
``` ```
template<class T, class A> template<class T, class A>
shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n); shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is an array type of the form `U[]`. `T` is an array type of the form `U[]`.
Returns::: A `shared_ptr` to a sequence of `_n_` default-initialized objects Returns:: A `shared_ptr` to a sequence of `_n_` default-initialized objects
of type `U`. of type `U`.
Example::: `auto p = make_shared_noinit<double[]>(1024);` Example:: `auto p = make_shared_noinit<double[]>(1024);`

View File

@@ -68,48 +68,58 @@ namespace boost {
template<class T, class... Args> template<class T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args); std::unique_ptr<T> make_unique(Args&&... args);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is not an array type. `T` is not an array type.
Returns::: `std::unique_ptr<T>(new T(std::forward<Args>(args)\...)`. Returns:: `std::unique_ptr<T>(new T(std::forward<Args>(args)\...)`.
Example::: `auto p = make_unique<int>();` Example:: `auto p = make_unique<int>();`
``` ```
template<class T> template<class T>
std::unique_ptr<T> make_unique(remove_reference_t<T>&& v); std::unique_ptr<T> make_unique(remove_reference_t<T>&& v);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is not an array type. `T` is not an array type.
Returns::: `std::unique_ptr<T>(new T(std::move(v))`. Returns:: `std::unique_ptr<T>(new T(std::move(v))`.
Example::: `auto p = make_unique<std::vector<int> >({1, 2});` Example:: `auto p = make_unique<std::vector<int> >({1, 2});`
``` ```
template<class T> template<class T>
std::unique_ptr<T> make_unique(std::size_t n); std::unique_ptr<T> make_unique(std::size_t n);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is an array type of the form `U[]`. `T` is an array type of the form `U[]`.
Returns::: `std::unique_ptr<U[]>(new U[n]())`. Returns:: `std::unique_ptr<U[]>(new U[n]())`.
Example::: `auto p = make_unique<double[]>(1024);` Example:: `auto p = make_unique<double[]>(1024);`
``` ```
template<class T> template<class T>
std::unique_ptr<T> make_unique_noinit(); std::unique_ptr<T> make_unique_noinit();
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is not an array type. `T` is not an array type.
Returns::: `std::unique_ptr<T>(new T)`. Returns:: `std::unique_ptr<T>(new T)`.
Example::: `auto p = make_unique_noinit<double[1024]>();` Example:: `auto p = make_unique_noinit<double[1024]>();`
``` ```
template<class T> template<class T>
std::unique_ptr<T> make_unique_noinit(std::size_t n); std::unique_ptr<T> make_unique_noinit(std::size_t n);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is an array type of the form `U[]`. `T` is an array type of the form `U[]`.
Returns::: `std::unique_ptr<U[]>(new U[n])`. Returns:: `std::unique_ptr<U[]>(new U[n])`.
Example::: `auto p = make_unique_noinit<double[]>(1024);` Example:: `auto p = make_unique_noinit<double[]>(1024);`

View File

@@ -78,23 +78,29 @@ namespace boost {
``` ```
template<class T, class U> T* static_pointer_cast(U* p) noexcept; template<class T, class U> T* static_pointer_cast(U* p) noexcept;
``` ```
:: [none]
Returns::: `static_cast<T*>(p)` * {blank}
+
Returns:: `static_cast<T*>(p)`
``` ```
template<class T, class U> std::shared_ptr<T> template<class T, class U> std::shared_ptr<T>
static_pointer_cast(const std::shared_ptr<U>& p) noexcept; static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
``` ```
:: [none]
Returns::: `std::static_pointer_cast<T>(p)` * {blank}
+
Returns:: `std::static_pointer_cast<T>(p)`
``` ```
template<class T, class U> std::unique_ptr<T> template<class T, class U> std::unique_ptr<T>
static_pointer_cast(std::unique_ptr<U>&& p) noexcept; static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
``` ```
:: [none]
Requires::: The expression `static_cast<T*>((U*)0)` must be well-formed. * {blank}
Returns::: `std::unique_ptr<T>(static_cast<typename +
Requires:: The expression `static_cast<T*>((U*)0)` must be well-formed.
Returns:: `std::unique_ptr<T>(static_cast<typename
std::unique_ptr<T>::element_type*>(p.release()))`. std::unique_ptr<T>::element_type*>(p.release()))`.
CAUTION: The seemingly equivalent expression CAUTION: The seemingly equivalent expression
@@ -106,25 +112,31 @@ undefined behavior, attempting to delete the same object twice.
``` ```
template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept; template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
``` ```
:: [none]
Returns::: `dynamic_cast<T*>(p)` * {blank}
+
Returns:: `dynamic_cast<T*>(p)`
``` ```
template<class T, class U> std::shared_ptr<T> template<class T, class U> std::shared_ptr<T>
dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept; dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
``` ```
:: [none]
Returns::: `std::dynamic_pointer_cast<T>(p)` * {blank}
+
Returns:: `std::dynamic_pointer_cast<T>(p)`
``` ```
template<class T, class U> std::unique_ptr<T> template<class T, class U> std::unique_ptr<T>
dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept; dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
``` ```
:: [none]
Requires::: * {blank}
+
Requires::
* The expression `static_cast<T*>((U*)0)` must be well-formed. * The expression `static_cast<T*>((U*)0)` must be well-formed.
* `T` must have a virtual destructor. * `T` must have a virtual destructor.
Returns::: Returns::
* When `dynamic_cast<typename std::unique_ptr<T>::element_type*>(p.get())` * When `dynamic_cast<typename std::unique_ptr<T>::element_type*>(p.get())`
returns a non-zero value, `std::unique_ptr<T>(dynamic_cast<typename returns a non-zero value, `std::unique_ptr<T>(dynamic_cast<typename
std::unique_ptr<T>::element_type*>(p.release()));`. std::unique_ptr<T>::element_type*>(p.release()));`.
@@ -135,23 +147,29 @@ std::unique_ptr<T>::element_type*>(p.release()));`.
``` ```
template<class T, class U> T* const_pointer_cast(U* p) noexcept; template<class T, class U> T* const_pointer_cast(U* p) noexcept;
``` ```
:: [none]
Returns::: `const_cast<T*>(p)` * {blank}
+
Returns:: `const_cast<T*>(p)`
``` ```
template<class T, class U> std::shared_ptr<T> template<class T, class U> std::shared_ptr<T>
const_pointer_cast(const std::shared_ptr<U>& p) noexcept; const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
``` ```
:: [none]
Returns::: `std::const_pointer_cast<T>(p)` * {blank}
+
Returns:: `std::const_pointer_cast<T>(p)`
``` ```
template<class T, class U> std::unique_ptr<T> template<class T, class U> std::unique_ptr<T>
const_pointer_cast(std::unique_ptr<U>&& p) noexcept; const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
``` ```
:: [none]
Requires::: The expression `const_cast<T*>((U*)0)` must be well-formed. * {blank}
Returns::: `std::unique_ptr<T>(const_cast<typename +
Requires:: The expression `const_cast<T*>((U*)0)` must be well-formed.
Returns:: `std::unique_ptr<T>(const_cast<typename
std::unique_ptr<T>::element_type*>(p.release()))`. std::unique_ptr<T>::element_type*>(p.release()))`.
### reinterpret_pointer_cast ### reinterpret_pointer_cast
@@ -159,23 +177,29 @@ std::unique_ptr<T>::element_type*>(p.release()))`.
``` ```
template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept; template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
``` ```
:: [none]
Returns::: `reinterpret_cast<T*>(p)` * {blank}
+
Returns:: `reinterpret_cast<T*>(p)`
``` ```
template<class T, class U> std::shared_ptr<T> template<class T, class U> std::shared_ptr<T>
reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept; reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
``` ```
:: [none]
Returns::: `std::reinterpret_pointer_cast<T>(p)` * {blank}
+
Returns:: `std::reinterpret_pointer_cast<T>(p)`
``` ```
template<class T, class U> std::unique_ptr<T> template<class T, class U> std::unique_ptr<T>
reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept; reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
``` ```
:: [none]
Requires::: The expression `reinterpret_cast<T*>((U*)0)` must be well-formed. * {blank}
Returns::: `std::unique_ptr<T>(reinterpret_cast<typename +
Requires:: The expression `reinterpret_cast<T*>((U*)0)` must be well-formed.
Returns:: `std::unique_ptr<T>(reinterpret_cast<typename
std::unique_ptr<T>::element_type*>(p.release()))`. std::unique_ptr<T>::element_type*>(p.release()))`.
## Example ## Example

View File

@@ -105,42 +105,50 @@ Type:: Provides the type of the stored pointer.
``` ```
explicit shared_array(T* p = 0); explicit shared_array(T* p = 0);
``` ```
:: [none]
Effects::: Constructs a `shared_array`, storing a copy of `p`, which must be a * {blank}
+
Effects:: Constructs a `shared_array`, storing a copy of `p`, which must be a
pointer to an array that was allocated via a C++ `new[]` expression or be 0. pointer to an array that was allocated via a C++ `new[]` expression or be 0.
Afterwards, the use count is 1 (even if `p == 0`; see `~shared_array`). Afterwards, the use count is 1 (even if `p == 0`; see `~shared_array`).
Requires::: `T` is a complete type. Requires:: `T` is a complete type.
Throws::: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called. Throws:: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called.
``` ```
template<class D> shared_array(T* p, D d); template<class D> shared_array(T* p, D d);
``` ```
:: [none]
Effects::: Constructs a `shared_array`, storing a copy of `p` and of `d`. * {blank}
+
Effects:: Constructs a `shared_array`, storing a copy of `p` and of `d`.
Afterwards, the use count is 1. When the the time comes to delete the array Afterwards, the use count is 1. When the the time comes to delete the array
pointed to by `p`, the object `d` is used in the statement `d(p)`. pointed to by `p`, the object `d` is used in the statement `d(p)`.
Requires::: Requires::
* `T` is a complete type. * `T` is a complete type.
* The copy constructor and destructor of `D` must not throw. * The copy constructor and destructor of `D` must not throw.
* Invoking the object `d` with parameter `p` must not throw. * Invoking the object `d` with parameter `p` must not throw.
Throws::: `std::bad_alloc`. If an exception is thrown, `d(p)` is called. Throws:: `std::bad_alloc`. If an exception is thrown, `d(p)` is called.
``` ```
shared_array(const shared_array& v) noexcept; shared_array(const shared_array& v) noexcept;
``` ```
:: [none]
Effects::: Constructs a `shared_array`, as if by storing a copy of the pointer * {blank}
+
Effects:: Constructs a `shared_array`, as if by storing a copy of the pointer
stored in `v`. Afterwards, the use count for all copies is 1 more than the stored in `v`. Afterwards, the use count for all copies is 1 more than the
initial use count. initial use count.
Requires::: `T` is a complete type. Requires:: `T` is a complete type.
### Destructor ### Destructor
``` ```
~shared_array() noexcept; ~shared_array() noexcept;
``` ```
:: [none]
Effects::: Decrements the use count. Then, if the use count is 0, deletes the * {blank}
+
Effects:: Decrements the use count. Then, if the use count is 0, deletes the
array pointed to by the stored pointer. Note that `delete[]` on a pointer with array pointed to by the stored pointer. Note that `delete[]` on a pointer with
a value of 0 is harmless. a value of 0 is harmless.
@@ -149,60 +157,70 @@ a value of 0 is harmless.
``` ```
shared_array& operator=(const shared_array& v) noexcept; shared_array& operator=(const shared_array& v) noexcept;
``` ```
:: [none]
Effects::: Constructs a new `shared_array` as described above, then replaces * {blank}
+
Effects:: Constructs a new `shared_array` as described above, then replaces
this `shared_array` with the new one, destroying the replaced object. this `shared_array` with the new one, destroying the replaced object.
Requires::: `T` is a complete type. Requires:: `T` is a complete type.
Returns::: `*this`. Returns:: `*this`.
### reset ### reset
``` ```
void reset(T* p = 0); void reset(T* p = 0);
``` ```
:: [none]
Effects::: Constructs a new `shared_array` as described above, then replaces * {blank}
+
Effects:: Constructs a new `shared_array` as described above, then replaces
this `shared_array` with the new one, destroying the replaced object. this `shared_array` with the new one, destroying the replaced object.
Requires::: `T` is a complete type. Requires:: `T` is a complete type.
Throws::: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called. Throws:: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called.
``` ```
template<class D> void reset(T* p, D d); template<class D> void reset(T* p, D d);
``` ```
:: [none]
Effects::: Constructs a new `shared_array` as described above, then replaces * {blank}
+
Effects:: Constructs a new `shared_array` as described above, then replaces
this `shared_array` with the new one, destroying the replaced object. this `shared_array` with the new one, destroying the replaced object.
Requires::: Requires::
* `T` is a complete type. * `T` is a complete type.
* The copy constructor of `D` must not throw. * The copy constructor of `D` must not throw.
Throws::: `std::bad_alloc`. If an exception is thrown, `d(p)` is called. Throws:: `std::bad_alloc`. If an exception is thrown, `d(p)` is called.
### Indexing ### Indexing
``` ```
T& operator[](std::ptrdiff_t n) const noexcept; T& operator[](std::ptrdiff_t n) const noexcept;
``` ```
Returns::: A reference to element `n` of the array pointed to by the stored Returns:: A reference to element `n` of the array pointed to by the stored
pointer. Behavior is undefined and almost certainly undesirable if the stored pointer. Behavior is undefined and almost certainly undesirable if the stored
pointer is 0, or if `n` is less than 0 or is greater than or equal to the pointer is 0, or if `n` is less than 0 or is greater than or equal to the
number of elements in the array. number of elements in the array.
Requires::: `T` is a complete type. Requires:: `T` is a complete type.
### get ### get
``` ```
T* get() const noexcept; T* get() const noexcept;
``` ```
:: [none]
Returns::: The stored pointer. * {blank}
+
Returns:: The stored pointer.
### unique ### unique
``` ```
bool unique() const noexcept; bool unique() const noexcept;
``` ```
:: [none]
Returns::: `true` if no other `shared_array` is sharing ownership of the * {blank}
+
Returns:: `true` if no other `shared_array` is sharing ownership of the
stored pointer, `false` otherwise. stored pointer, `false` otherwise.
### use_count ### use_count
@@ -210,8 +228,10 @@ stored pointer, `false` otherwise.
``` ```
long use_count() const noexcept; long use_count() const noexcept;
``` ```
:: [none]
Returns::: The number of `shared_array` objects sharing ownership of the * {blank}
+
Returns:: The number of `shared_array` objects sharing ownership of the
stored pointer. stored pointer.
### Conversions ### Conversions
@@ -219,17 +239,21 @@ stored pointer.
``` ```
explicit operator bool() const noexcept; explicit operator bool() const noexcept;
``` ```
:: [none]
Returns::: `get() != 0`. * {blank}
Requires::: `T` is a complete type. +
Returns:: `get() != 0`.
Requires:: `T` is a complete type.
### swap ### swap
``` ```
void swap(shared_array<T>& b) noexcept; void swap(shared_array<T>& b) noexcept;
``` ```
:: [none]
Effects::: Exchanges the contents of the two smart pointers. * {blank}
+
Effects:: Exchanges the contents of the two smart pointers.
## Free Functions ## Free Functions
@@ -247,8 +271,10 @@ template<class T> bool
template<class T> bool template<class T> bool
operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept; operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept;
``` ```
:: [none]
Returns::: The result of comparing the stored pointers of the two smart * {blank}
+
Returns:: The result of comparing the stored pointers of the two smart
pointers. pointers.
NOTE: The `operator<` overload is provided to define an ordering so that NOTE: The `operator<` overload is provided to define an ordering so that
@@ -265,6 +291,8 @@ mandates that relational operations on pointers are unspecified (5.9
template<class T> template<class T>
void swap(shared_array<T>& a, shared_array<T>& b) noexcept; void swap(shared_array<T>& a, shared_array<T>& b) noexcept;
``` ```
:: [none]
Returns::: `a.swap(b)`. * {blank}
Requires::: `T` is a complete type. +
Returns:: `a.swap(b)`.
Requires:: `T` is a complete type.

View File

@@ -297,6 +297,8 @@ template<class T> T * get_pointer(intrusive_ptr<T> const & p) BOOST_SP_NOEXCEPT
return p.get(); return p.get();
} }
// pointer casts
template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p) template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
{ {
return static_cast<T *>(p.get()); return static_cast<T *>(p.get());
@@ -312,6 +314,31 @@ template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U
return dynamic_cast<T *>(p.get()); return dynamic_cast<T *>(p.get());
} }
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
template<class T, class U> intrusive_ptr<T> static_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
{
return intrusive_ptr<T>( static_cast<T*>( p.detach() ), false );
}
template<class T, class U> intrusive_ptr<T> const_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
{
return intrusive_ptr<T>( const_cast<T*>( p.detach() ), false );
}
template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
{
T * p2 = dynamic_cast<T*>( p.get() );
intrusive_ptr<T> r( p2, false );
if( p2 ) p.detach();
return r;
}
#endif // defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
// operator<< // operator<<
#if !defined(BOOST_NO_IOSTREAM) #if !defined(BOOST_NO_IOSTREAM)

View File

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

View File

@@ -41,7 +41,7 @@ class base
{ {
private: private:
boost::detail::atomic_count use_count_; mutable boost::detail::atomic_count use_count_;
base(base const &); base(base const &);
base & operator=(base const &); base & operator=(base const &);
@@ -69,24 +69,24 @@ public:
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
inline friend void intrusive_ptr_add_ref(base * p) inline friend void intrusive_ptr_add_ref(base const * p)
{ {
++p->use_count_; ++p->use_count_;
} }
inline friend void intrusive_ptr_release(base * p) inline friend void intrusive_ptr_release(base const * p)
{ {
if(--p->use_count_ == 0) delete p; if(--p->use_count_ == 0) delete p;
} }
#else #else
void add_ref() void add_ref() const
{ {
++use_count_; ++use_count_;
} }
void release() void release() const
{ {
if(--use_count_ == 0) delete this; if(--use_count_ == 0) delete this;
} }
@@ -103,12 +103,12 @@ long base::instances = 0;
namespace boost namespace boost
{ {
inline void intrusive_ptr_add_ref(N::base * p) inline void intrusive_ptr_add_ref(N::base const * p)
{ {
p->add_ref(); p->add_ref();
} }
inline void intrusive_ptr_release(N::base * p) inline void intrusive_ptr_release(N::base const * p)
{ {
p->release(); p->release();
} }
@@ -209,6 +209,58 @@ int main()
BOOST_TEST( N::base::instances == 0 ); BOOST_TEST( N::base::instances == 0 );
} }
{
boost::intrusive_ptr<X> px( new Y );
X * px2 = px.get();
boost::intrusive_ptr<Y> py = boost::static_pointer_cast<Y>( std::move( px ) );
BOOST_TEST( py.get() == px2 );
BOOST_TEST( px.get() == 0 );
BOOST_TEST( py->use_count() == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X const> px( new X );
X const * px2 = px.get();
boost::intrusive_ptr<X> px3 = boost::const_pointer_cast<X>( std::move( px ) );
BOOST_TEST( px3.get() == px2 );
BOOST_TEST( px.get() == 0 );
BOOST_TEST( px3->use_count() == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new Y );
X * px2 = px.get();
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( std::move( px ) );
BOOST_TEST( py.get() == px2 );
BOOST_TEST( px.get() == 0 );
BOOST_TEST( py->use_count() == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new X );
X * px2 = px.get();
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( std::move( px ) );
BOOST_TEST( py.get() == 0 );
BOOST_TEST( px.get() == px2 );
BOOST_TEST( px->use_count() == 1 );
}
BOOST_TEST( N::base::instances == 0 );
return boost::report_errors(); return boost::report_errors();
} }

View File

@@ -42,7 +42,7 @@ class base
{ {
private: private:
boost::detail::atomic_count use_count_; mutable boost::detail::atomic_count use_count_;
base(base const &); base(base const &);
base & operator=(base const &); base & operator=(base const &);
@@ -70,24 +70,24 @@ public:
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
inline friend void intrusive_ptr_add_ref(base * p) inline friend void intrusive_ptr_add_ref(base const * p)
{ {
++p->use_count_; ++p->use_count_;
} }
inline friend void intrusive_ptr_release(base * p) inline friend void intrusive_ptr_release(base const * p)
{ {
if(--p->use_count_ == 0) delete p; if(--p->use_count_ == 0) delete p;
} }
#else #else
void add_ref() void add_ref() const
{ {
++use_count_; ++use_count_;
} }
void release() void release() const
{ {
if(--use_count_ == 0) delete this; if(--use_count_ == 0) delete this;
} }
@@ -104,12 +104,12 @@ long base::instances = 0;
namespace boost namespace boost
{ {
inline void intrusive_ptr_add_ref(N::base * p) inline void intrusive_ptr_add_ref(N::base const * p)
{ {
p->add_ref(); p->add_ref();
} }
inline void intrusive_ptr_release(N::base * p) inline void intrusive_ptr_release(N::base const * p)
{ {
p->release(); p->release();
} }
@@ -303,14 +303,211 @@ namespace n_assignment
void copy_assignment() void copy_assignment()
{ {
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> p1;
p1 = p1;
BOOST_TEST(p1 == p1);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
boost::intrusive_ptr<X> p2;
p1 = p2;
BOOST_TEST(p1 == p2);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
boost::intrusive_ptr<X> p3(p1);
p1 = p3;
BOOST_TEST(p1 == p3);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
BOOST_TEST(N::base::instances == 0);
boost::intrusive_ptr<X> p4(new X);
BOOST_TEST(N::base::instances == 1);
p1 = p4;
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p1 == p4);
BOOST_TEST(p1->use_count() == 2);
p1 = p2;
BOOST_TEST(p1 == p2);
BOOST_TEST(N::base::instances == 1);
p4 = p3;
BOOST_TEST(p4 == p3);
BOOST_TEST(N::base::instances == 0);
}
} }
void conversion_assignment() void conversion_assignment()
{ {
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> p1;
boost::intrusive_ptr<Y> p2;
p1 = p2;
BOOST_TEST(p1 == p2);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
BOOST_TEST(N::base::instances == 0);
boost::intrusive_ptr<Y> p4(new Y);
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p4->use_count() == 1);
boost::intrusive_ptr<X> p5(p4);
BOOST_TEST(p4->use_count() == 2);
p1 = p4;
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p1 == p4);
BOOST_TEST(p1->use_count() == 3);
BOOST_TEST(p4->use_count() == 3);
p1 = p2;
BOOST_TEST(p1 == p2);
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p4->use_count() == 2);
p4 = p2;
p5 = p2;
BOOST_TEST(p4 == p2);
BOOST_TEST(N::base::instances == 0);
}
} }
void pointer_assignment() void pointer_assignment()
{ {
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> p1;
p1 = p1.get();
BOOST_TEST(p1 == p1);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
boost::intrusive_ptr<X> p2;
p1 = p2.get();
BOOST_TEST(p1 == p2);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
boost::intrusive_ptr<X> p3(p1);
p1 = p3.get();
BOOST_TEST(p1 == p3);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
BOOST_TEST(N::base::instances == 0);
boost::intrusive_ptr<X> p4(new X);
BOOST_TEST(N::base::instances == 1);
p1 = p4.get();
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p1 == p4);
BOOST_TEST(p1->use_count() == 2);
p1 = p2.get();
BOOST_TEST(p1 == p2);
BOOST_TEST(N::base::instances == 1);
p4 = p3.get();
BOOST_TEST(p4 == p3);
BOOST_TEST(N::base::instances == 0);
}
{
boost::intrusive_ptr<X> p1;
boost::intrusive_ptr<Y> p2;
p1 = p2.get();
BOOST_TEST(p1 == p2);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
BOOST_TEST(N::base::instances == 0);
boost::intrusive_ptr<Y> p4(new Y);
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p4->use_count() == 1);
boost::intrusive_ptr<X> p5(p4);
BOOST_TEST(p4->use_count() == 2);
p1 = p4.get();
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p1 == p4);
BOOST_TEST(p1->use_count() == 3);
BOOST_TEST(p4->use_count() == 3);
p1 = p2.get();
BOOST_TEST(p1 == p2);
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p4->use_count() == 2);
p4 = p2.get();
p5 = p2.get();
BOOST_TEST(p4 == p2);
BOOST_TEST(N::base::instances == 0);
}
} }
void test() void test()
@@ -707,15 +904,137 @@ namespace n_static_cast
void test() void test()
{ {
{
boost::intrusive_ptr<X> px(new Y);
boost::intrusive_ptr<Y> py = boost::static_pointer_cast<Y>(px);
BOOST_TEST(px.get() == py.get());
BOOST_TEST(px->use_count() == 2);
BOOST_TEST(py->use_count() == 2);
boost::intrusive_ptr<X> px2(py);
BOOST_TEST(px2.get() == px.get());
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<Y> py = boost::static_pointer_cast<Y>( boost::intrusive_ptr<X>(new Y) );
BOOST_TEST(py.get() != 0);
BOOST_TEST(py->use_count() == 1);
}
BOOST_TEST( N::base::instances == 0 );
} }
} // namespace n_static_cast } // namespace n_static_cast
namespace n_const_cast
{
void test()
{
{
boost::intrusive_ptr<X const> px;
boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>(px);
BOOST_TEST(px2.get() == 0);
}
{
boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>( boost::intrusive_ptr<X const>() );
BOOST_TEST(px2.get() == 0);
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X const> px(new X);
boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>(px);
BOOST_TEST(px2.get() == px.get());
BOOST_TEST(px2->use_count() == 2);
BOOST_TEST(px->use_count() == 2);
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px = boost::const_pointer_cast<X>( boost::intrusive_ptr<X const>(new X) );
BOOST_TEST(px.get() != 0);
BOOST_TEST(px->use_count() == 1);
}
BOOST_TEST( N::base::instances == 0 );
}
} // namespace n_const_cast
namespace n_dynamic_cast namespace n_dynamic_cast
{ {
void test() void test()
{ {
{
boost::intrusive_ptr<X> px;
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
BOOST_TEST(py.get() == 0);
}
{
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>() );
BOOST_TEST(py.get() == 0);
}
{
boost::intrusive_ptr<X> px(static_cast<X*>(0));
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
BOOST_TEST(py.get() == 0);
}
{
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(static_cast<X*>(0)) );
BOOST_TEST(py.get() == 0);
}
{
boost::intrusive_ptr<X> px(new X);
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
BOOST_TEST(py.get() == 0);
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(new X) );
BOOST_TEST(py.get() == 0);
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px(new Y);
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
BOOST_TEST(py.get() == px.get());
BOOST_TEST(py->use_count() == 2);
BOOST_TEST(px->use_count() == 2);
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px(new Y);
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(new Y) );
BOOST_TEST(py.get() != 0);
BOOST_TEST(py->use_count() == 1);
}
BOOST_TEST( N::base::instances == 0 );
} }
} // namespace n_dynamic_cast } // namespace n_dynamic_cast
@@ -779,6 +1098,7 @@ int main()
n_swap::test(); n_swap::test();
n_comparison::test(); n_comparison::test();
n_static_cast::test(); n_static_cast::test();
n_const_cast::test();
n_dynamic_cast::test(); n_dynamic_cast::test();
n_transitive::test(); n_transitive::test();

View File

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

View File

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