Merge branch 'feature/local_shared_ptr' into develop

This commit is contained in:
Peter Dimov
2017-06-21 03:33:00 +03:00
48 changed files with 3712 additions and 98 deletions

View File

@ -37,6 +37,8 @@ include::smart_ptr/intrusive_ptr.adoc[]
include::smart_ptr/intrusive_ref_counter.adoc[]
include::smart_ptr/local_shared_ptr.adoc[]
include::smart_ptr/pointer_cast.adoc[]
include::smart_ptr/pointer_to_other.adoc[]

View File

@ -24,13 +24,14 @@ deletion of the object when it is no longer needed. As such, they are examples o
acquisition is initialization" idiom described in Bjarne Stroustrup's "The C++ Programming Language",
3rd edition, Section 14.4, Resource Management.
This library provides five smart pointer class templates:
This library provides six smart pointer class templates:
* `<<scoped_ptr,scoped_ptr>>`, used to contain ownership of a dynamically allocated object to the current scope;
* `<<scoped_array,scoped_array>>`, which provides scoped ownership for a dynamically allocated array;
* `<<shared_ptr,shared_ptr>>`, a versatile tool for managing shared ownership of an object or array;
* `<<weak_ptr,weak_ptr>>`, a non-owning observer to a shared_ptr-managed object that can be promoted temporarily to shared_ptr;
* `<<intrusive_ptr,intrusive_ptr>>`, a pointer to objects with an embedded reference count.
* `<<intrusive_ptr,intrusive_ptr>>`, a pointer to objects with an embedded reference count;
* `<<local_shared_ptr,local_shared_ptr>>`, providing shared ownership within a single thread.
`shared_ptr` and `weak_ptr` are part of the {cpp} standard since its 2011 iteration.

View File

@ -0,0 +1,719 @@
////
Copyright 2017 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt
////
[#local_shared_ptr]
# local_shared_ptr: Shared Ownership within a Single Thread
:toc:
:toc-title:
:idprefix: local_shared_ptr_
## Description
`local_shared_ptr` is nearly identical to `shared_ptr`, with the only difference of note being that its reference count is
updated with non-atomic operations. As such, a `local_shared_ptr` and all its copies must reside in (be local to) a single
thread (hence the name.)
`local_shared_ptr` can be converted to `shared_ptr` and vice versa. Creating a `local_shared_ptr` from a `shared_ptr` creates
a new local reference count; this means that two `local_shared_ptr` instances, both created from the same `shared_ptr`, refer
to the same object but don't share the same count, and as such, can safely be used by two different threads.
.Two local_shared_ptr instances created from a shared_ptr
```
shared_ptr<X> p1( new X );
local_shared_ptr<X> p2( p1 ); // p2.local_use_count() == 1
local_shared_ptr<X> p3( p1 ); // p3.local_use_count() also 1
```
Creating the second `local_shared_ptr` from the first one, however, does lead to the two sharing the same count:
.A local_shared_ptr created from another local_shared_ptr
```
shared_ptr<X> p1( new X );
local_shared_ptr<X> p2( p1 ); // p2.local_use_count() == 1
local_shared_ptr<X> p3( p2 ); // p3.local_use_count() == 2
```
Two `shared_ptr` instances created from the same `local_shared_ptr` do share ownership:
.Two shared_ptr instances created from a local_shared_ptr
```
local_shared_ptr<X> p1( new X );
shared_ptr<X> p2( p1 ); // p2.use_count() == 2
shared_ptr<X> p3( p1 ); // p3.use_count() == 3
```
Here `p2.use_count()` is 2, because `p1` holds a reference, too.
One can think of `local_shared_ptr<T>` as `shared_ptr<shared_ptr<T>>`, with the outer `shared_ptr` using non-atomic operations for
its count. Converting from `local_shared_ptr` to `shared_ptr` gives you a copy of the inner `shared_ptr`; converting from `shared_ptr`
wraps it into an outer `shared_ptr` with a non-atomic use count (conceptually speaking) and returns the result.
## Synopsis
`local_shared_ptr` is defined in `<boost/smart_ptr/local_shared_ptr.hpp>`.
```
namespace boost {
template<class T> class local_shared_ptr {
public:
typedef /*see below*/ element_type;
// constructors
constexpr local_shared_ptr() noexcept;
constexpr local_shared_ptr(std::nullptr_t) noexcept;
template<class Y> explicit local_shared_ptr(Y * p);
template<class Y, class D> local_shared_ptr(Y * p, D d);
template<class D> local_shared_ptr(std::nullptr_t p, D d);
template<class Y, class D, class A> local_shared_ptr(Y * p, D d, A a);
template<class D, class A> local_shared_ptr(std::nullptr_t p, D d, A a);
local_shared_ptr(local_shared_ptr const & r) noexcept;
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r) noexcept;
local_shared_ptr(local_shared_ptr && r) noexcept;
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r) noexcept;
template<class Y> local_shared_ptr( shared_ptr<Y> const & r );
template<class Y> local_shared_ptr( shared_ptr<Y> && r );
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r, element_type * p) noexcept;
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r, element_type * p) noexcept;
template<class Y, class D> local_shared_ptr(std::unique_ptr<Y, D> && r);
// destructor
~local_shared_ptr() noexcept;
// assignment
local_shared_ptr & operator=(local_shared_ptr const & r) noexcept;
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const & r) noexcept;
local_shared_ptr & operator=(local_shared_ptr const && r) noexcept;
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const && r) noexcept;
template<class Y, class D> local_shared_ptr & operator=(std::unique_ptr<Y, D> && r);
local_shared_ptr & operator=(std::nullptr_t) noexcept;
// reset
void reset() noexcept;
template<class Y> void reset(Y * p);
template<class Y, class D> void reset(Y * p, D d);
template<class Y, class D, class A> void reset(Y * p, D d, A a);
template<class Y> void reset(local_shared_ptr<Y> const & r, element_type * p) noexcept;
template<class Y> void reset(local_shared_ptr<Y> && r, element_type * p) noexcept;
// accessors
T & operator*() const noexcept; // only valid when T is not an array type
T * operator->() const noexcept; // only valid when T is not an array type
// only valid when T is an array type
element_type & operator[](std::ptrdiff_t i) const noexcept;
element_type * get() const noexcept;
long local_use_count() const noexcept;
// conversions
explicit operator bool() const noexcept;
template<class Y> operator shared_ptr<Y>() const noexcept;
template<class Y> operator weak_ptr<Y>() const noexcept;
// swap
void swap(local_shared_ptr & b) noexcept;
// owner_before
template<class Y> bool owner_before(local_shared_ptr<Y> const & rhs) const noexcept;
};
// comparisons
template<class T, class U>
bool operator==(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator==(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator==(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator!=(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator!=(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator!=(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
template<class T> bool operator==(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
template<class T> bool operator==(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
template<class T> bool operator!=(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
template<class T> bool operator!=(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
template<class T, class U>
bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
// swap
template<class T> void swap(local_shared_ptr<T> & a, local_shared_ptr<T> & b) noexcept;
// get_pointer
template<class T>
typename local_shared_ptr<T>::element_type *
get_pointer(local_shared_ptr<T> const & p) noexcept;
// casts
template<class T, class U>
local_shared_ptr<T> static_pointer_cast(local_shared_ptr<U> const & r) noexcept;
template<class T, class U>
local_shared_ptr<T> const_pointer_cast(local_shared_ptr<U> const & r) noexcept;
template<class T, class U>
local_shared_ptr<T> dynamic_pointer_cast(local_shared_ptr<U> const & r) noexcept;
template<class T, class U>
local_shared_ptr<T> reinterpret_pointer_cast(local_shared_ptr<U> const & r) noexcept;
// stream I/O
template<class E, class T, class Y>
std::basic_ostream<E, T> &
operator<< (std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p);
// get_deleter
template<class D, class T> D * get_deleter(local_shared_ptr<T> const & p) noexcept;
}
```
## Members
### element_type
```
typedef ... element_type;
```
`element_type` is `T` when `T` is not an array type, and `U` when `T` is `U[]` or `U[N]`.
### default constructor
```
constexpr local_shared_ptr() noexcept;
```
```
constexpr local_shared_ptr(std::nullptr_t) noexcept;
```
[none]
* {blank}
+
Effects:: Constructs an empty `local_shared_ptr`.
Postconditions:: `local_use_count() == 0 && get() == 0`.
### pointer constructor
```
template<class Y> explicit local_shared_ptr(Y * p);
```
[none]
* {blank}
+
Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p )`.
Postconditions:: `local_use_count() == 1 && get() == p`.
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
### constructors taking a deleter
```
template<class Y, class D> local_shared_ptr(Y * p, D d);
```
```
template<class D> local_shared_ptr(std::nullptr_t p, D d);
```
[none]
* {blank}
+
Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p, d )`.
Postconditions:: `local_use_count() == 1 && get() == p`.
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
```
template<class Y, class D, class A> local_shared_ptr(Y * p, D d, A a);
```
```
template<class D, class A> local_shared_ptr(std::nullptr_t p, D d, A a);
```
[none]
* {blank}
+
Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p, d, a )`.
Postconditions:: `local_use_count() == 1 && get() == p`.
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
### copy and converting constructors
```
local_shared_ptr(local_shared_ptr const & r) noexcept;
```
```
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r) noexcept;
```
[none]
* {blank}
+
Requires:: `Y*` should be convertible to `T*`.
Effects:: If `r` is empty, constructs an empty `local_shared_ptr`; otherwise, constructs a `local_shared_ptr` that shares ownership with `r`.
Postconditions:: `get() == r.get() && local_use_count() == r.local_use_count()`.
### move constructors
```
local_shared_ptr(local_shared_ptr && r) noexcept;
```
```
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r) noexcept;
```
[none]
* {blank}
+
Requires:: `Y*` should be convertible to `T*`.
Effects:: Move-constructs a `local_shared_ptr` from `r`.
Postconditions:: `*this` contains the old value of `r`. `r` is empty and `r.get() == 0`.
### shared_ptr constructor
```
template<class Y> local_shared_ptr( shared_ptr<Y> const & r );
```
```
template<class Y> local_shared_ptr( shared_ptr<Y> && r );
```
[none]
* {blank}
+
Effects:: Constructs a `local_shared_ptr` that owns `r`.
Postconditions:: `local_use_count() == 1`. `get()` returns the old value of `r.get()`.
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
### aliasing constructor
```
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r, element_type * p) noexcept;
```
[none]
* {blank}
+
Effects:: constructs a `local_shared_ptr` that shares ownership with `r` and stores `p`.
Postconditions:: `get() == p && local_use_count() == r.local_use_count()`.
### aliasing move constructor
```
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r, element_type * p) noexcept;
```
[none]
* {blank}
+
Effects:: Move-constructs a `local_shared_ptr` from `r`, while storing `p` instead.
Postconditions:: `get() == p` and `local_use_count()` equals the old count of `r`. `r` is empty and `r.get() == 0`.
### unique_ptr constructor
```
template<class Y, class D> local_shared_ptr(std::unique_ptr<Y, D> && r);
```
[none]
* {blank}
+
Requires:: `Y*` should be convertible to `T*`.
Effects::
- When `r.get() == 0`, equivalent to `local_shared_ptr()`;
- Otherwise, constructs a `local_shared_ptr` that owns `shared_ptr<T>( std::move(r) )`.
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
Exception safety:: If an exception is thrown, the constructor has no effect.
### destructor
```
~local_shared_ptr() noexcept;
```
[none]
* {blank}
+
Effects::
- If `*this` is empty, or shares ownership with another `local_shared_ptr` instance (`local_use_count() > 1`), there are no side effects.
- Otherwise, destroys the owned `shared_ptr`.
### assignment
```
local_shared_ptr & operator=(local_shared_ptr const & r) noexcept;
```
```
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const & r) noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr(r).swap(*this)`.
Returns:: `*this`.
```
local_shared_ptr & operator=(local_shared_ptr && r) noexcept;
```
```
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> && r) noexcept;
```
```
template<class Y, class D> local_shared_ptr & operator=(std::unique_ptr<Y, D> && r);
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr(std::move(r)).swap(*this)`.
Returns:: `*this`.
```
local_shared_ptr & operator=(std::nullptr_t) noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr().swap(*this)`.
Returns:: `*this`.
### reset
```
void reset() noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr().swap(*this)`.
```
template<class Y> void reset(Y * p);
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr(p).swap(*this)`.
```
template<class Y, class D> void reset(Y * p, D d);
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr(p, d).swap(*this)`.
```
template<class Y, class D, class A> void reset(Y * p, D d, A a);
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr(p, d, a).swap(*this)`.
```
template<class Y> void reset(local_shared_ptr<Y> const & r, element_type * p) noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr(r, p).swap(*this)`.
```
template<class Y> void reset(local_shared_ptr<Y> && r, element_type * p) noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr(std::move(r), p).swap(*this)`.
### indirection
```
T & operator*() const noexcept;
```
[none]
* {blank}
+
Requires:: `T` should not be an array type.
Returns:: `*get()`.
```
T * operator->() const noexcept;
```
[none]
* {blank}
+
Requires:: `T` should not be an array type.
Returns:: `get()`.
```
element_type & operator[](std::ptrdiff_t i) const noexcept;
```
[none]
* {blank}
+
Requires:: `T` should be an array type. The stored pointer must not be 0. `i >= 0`. If `T` is `U[N]`, `i < N`.
Returns:: `get()[i]`.
### get
```
element_type * get() const noexcept;
```
[none]
* {blank}
+
Returns:: The stored pointer.
### local_use_count
```
long local_use_count() const noexcept;
```
[none]
* {blank}
+
Returns:: The number of `local_shared_ptr` objects, `*this` included, that share ownership with `*this`, or 0 when `*this` is empty.
### conversions
```
explicit operator bool() const noexcept;
```
[none]
* {blank}
+
Returns:: `get() != 0`.
NOTE: On C++03 compilers, the return value is of an unspecified type.
```
template<class Y> operator shared_ptr<Y>() const noexcept;
```
```
template<class Y> operator weak_ptr<Y>() const noexcept;
```
[none]
* {blank}
+
Requires:: `T*` should be convertible to `Y*`.
Returns:: a copy of the owned `shared_ptr`.
### swap
```
void swap(local_shared_ptr & b) noexcept;
```
[none]
* {blank}
+
Effects:: Exchanges the contents of the two smart pointers.
### owner_before
```
template<class Y> bool owner_before(local_shared_ptr<Y> const & rhs) const noexcept;
```
[none]
* {blank}
+
Effects:: See the description of `operator<`.
## Free Functions
### comparison
```
template<class T, class U>
bool operator==(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
```
```
template<class T, class U>
bool operator==(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
```
```
template<class T, class U>
bool operator==(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
```
[none]
* {blank}
+
Returns:: `a.get() == b.get()`.
```
template<class T, class U>
bool operator!=(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
```
```
template<class T, class U>
bool operator!=(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
```
```
template<class T, class U>
bool operator!=(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
```
[none]
* {blank}
+
Returns:: `a.get() != b.get()`.
```
template<class T> bool operator==(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
```
```
template<class T> bool operator==(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
```
[none]
* {blank}
+
Returns:: `p.get() == 0`.
```
template<class T> bool operator!=(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
```
```
template<class T> bool operator!=(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
```
[none]
* {blank}
+
Returns:: `p.get() != 0`.
```
template<class T, class U>
bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
```
[none]
* {blank}
+
Returns:: An unspecified value such that
- `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard;
- under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `local_shared_ptr` instances
are equivalent if and only if they share ownership or are both empty.
NOTE: Allows `local_shared_ptr` objects to be used as keys in associative containers.
NOTE: The rest of the comparison operators are omitted by design.
### swap
```
template<class T> void swap(local_shared_ptr<T> & a, local_shared_ptr<T> & b) noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `a.swap(b)`.
### get_pointer
```
template<class T>
typename local_shared_ptr<T>::element_type *
get_pointer(local_shared_ptr<T> const & p) noexcept;
```
[none]
* {blank}
+
Returns:: `p.get()`.
NOTE: Provided as an aid to generic programming. Used by `mem_fn`.
### static_pointer_cast
```
template<class T, class U>
local_shared_ptr<T> static_pointer_cast(local_shared_ptr<U> const & r) noexcept;
```
[none]
* {blank}
+
Requires:: The expression `static_cast<T*>( (U*)0 )` must be well-formed.
Returns:: `local_shared_ptr<T>( r, static_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`.
CAUTION: The seemingly equivalent expression `local_shared_ptr<T>(static_cast<T*>(r.get()))` will eventually
result in undefined behavior, attempting to delete the same object twice.
### const_pointer_cast
```
template<class T, class U>
local_shared_ptr<T> const_pointer_cast(local_shared_ptr<U> const & r) noexcept;
```
[none]
* {blank}
+
Requires:: The expression `const_cast<T*>( (U*)0 )` must be well-formed.
Returns:: `local_shared_ptr<T>( r, const_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`.
### dynamic_pointer_cast
```
template<class T, class U>
local_shared_ptr<T> dynamic_pointer_cast(local_shared_ptr<U> const & r) noexcept;
```
[none]
* {blank}
+
Requires:: The expression `dynamic_cast<T*>( (U*)0 )` must be well-formed.
Returns::
- When `dynamic_cast<typename local_shared_ptr<T>::element_type*>(r.get())` returns a nonzero value `p`, `local_shared_ptr<T>(r, p)`;
- Otherwise, `local_shared_ptr<T>()`.
### reinterpret_pointer_cast
```
template<class T, class U>
local_shared_ptr<T> reinterpret_pointer_cast(local_shared_ptr<U> const & r) noexcept;
```
[none]
* {blank}
+
Requires:: The expression `reinterpret_cast<T*>( (U*)0 )` must be well-formed.
Returns:: `local_shared_ptr<T>( r, reinterpret_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`.
### operator<<
```
template<class E, class T, class Y>
std::basic_ostream<E, T> &
operator<< (std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p);
```
[none]
* {blank}
+
Effects:: `os << p.get();`.
Returns:: `os`.
### get_deleter
```
template<class D, class T>
D * get_deleter(local_shared_ptr<T> const & p) noexcept;
```
[none]
* {blank}
+
Returns:: If `*this` owns a `shared_ptr` instance `p`, `get_deleter<D>( p )`, otherwise 0.

View File

@ -767,6 +767,10 @@ public:
&reinterpret_cast<char&>(deleter_) : 0;
}
void* get_local_deleter(const sp_typeinfo&) {
return 0;
}
void* get_untyped_deleter() {
return &reinterpret_cast<char&>(deleter_);
}
@ -809,6 +813,10 @@ public:
&reinterpret_cast<char&>(deleter_) : 0;
}
void* get_local_deleter(const sp_typeinfo&) {
return 0;
}
void* get_untyped_deleter() {
return &reinterpret_cast<char&>(deleter_);
}
@ -856,6 +864,10 @@ public:
&reinterpret_cast<char&>(deleter_) : 0;
}
void* get_local_deleter(const sp_typeinfo&) {
return 0;
}
void* get_untyped_deleter() {
return &reinterpret_cast<char&>(deleter_);
}
@ -902,6 +914,10 @@ public:
&reinterpret_cast<char&>(deleter_) : 0;
}
void* get_local_deleter(const sp_typeinfo&) {
return 0;
}
void* get_untyped_deleter() {
return &reinterpret_cast<char&>(deleter_);
}

View File

@ -17,7 +17,7 @@
//
// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/detail/shared_count.hpp>
#include <boost/config.hpp>
#include <utility>
#include <climits>
@ -55,9 +55,9 @@ public:
{
}
virtual void destroy() BOOST_SP_NOEXCEPT = 0;
virtual void local_cb_destroy() BOOST_SP_NOEXCEPT = 0;
virtual boost::shared_ptr<void> get_shared_ptr() const BOOST_SP_NOEXCEPT = 0;
virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT = 0;
void add_ref() BOOST_SP_NOEXCEPT
{
@ -78,7 +78,7 @@ public:
if( local_use_count_ == 0 )
{
destroy();
local_cb_destroy();
}
}
@ -96,30 +96,30 @@ private:
private:
boost::shared_ptr<void const volatile> pn_;
shared_count pn_;
public:
template<class T> explicit local_counted_impl( boost::shared_ptr<T> const& pn ): pn_( pn )
explicit local_counted_impl( shared_count const& pn ): pn_( pn )
{
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
template<class T> explicit local_counted_impl( boost::shared_ptr<T>&& pn ): pn_( std::move(pn) )
explicit local_counted_impl( shared_count && pn ): pn_( std::move(pn) )
{
}
#endif
virtual void destroy() BOOST_SP_NOEXCEPT
virtual void local_cb_destroy() BOOST_SP_NOEXCEPT
{
delete this;
}
virtual boost::shared_ptr<void> get_shared_ptr() const BOOST_SP_NOEXCEPT
virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT
{
return const_pointer_cast<void>( pn_ );
return pn_;
}
};
@ -127,16 +127,16 @@ class local_counted_impl_em: public local_counted_base
{
public:
boost::shared_ptr<void const volatile> pn_;
shared_count pn_;
virtual void destroy() BOOST_SP_NOEXCEPT
virtual void local_cb_destroy() BOOST_SP_NOEXCEPT
{
pn_.reset();
shared_count().swap( pn_ );
}
virtual boost::shared_ptr<void> get_shared_ptr() const BOOST_SP_NOEXCEPT
virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT
{
return const_pointer_cast<void>( pn_ );
return pn_;
}
};

View File

@ -0,0 +1,91 @@
#ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// detail/local_sp_deleter.hpp
//
// Copyright 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/smart_ptr/detail/local_counted_base.hpp>
#include <boost/config.hpp>
namespace boost
{
namespace detail
{
template<class D> class local_sp_deleter: public local_counted_impl_em
{
private:
D d_;
public:
local_sp_deleter(): d_()
{
}
explicit local_sp_deleter( D const& d ) BOOST_SP_NOEXCEPT: d_( d )
{
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
explicit local_sp_deleter( D&& d ) BOOST_SP_NOEXCEPT: d_( std::move(d) )
{
}
#endif
D& deleter()
{
return d_;
}
template<class Y> void operator()( Y* p ) BOOST_SP_NOEXCEPT
{
d_( p );
}
#if !defined( BOOST_NO_CXX11_NULLPTR )
void operator()( boost::detail::sp_nullptr_t p ) BOOST_SP_NOEXCEPT
{
d_( p );
}
#endif
};
template<> class local_sp_deleter<void>
{
};
template<class D> D * get_local_deleter( local_sp_deleter<D> * p )
{
return &p->deleter();
}
inline void * get_local_deleter( local_sp_deleter<void> * /*p*/ )
{
return 0;
}
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED

View File

@ -496,6 +496,11 @@ public:
return pi_? pi_->get_deleter( ti ): 0;
}
void * get_local_deleter( sp_typeinfo const & ti ) const
{
return pi_? pi_->get_local_deleter( ti ): 0;
}
void * get_untyped_deleter() const
{
return pi_? pi_->get_untyped_deleter(): 0;

View File

@ -104,6 +104,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -96,6 +96,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -98,6 +98,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -124,6 +124,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -112,6 +112,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -111,6 +111,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -135,6 +135,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -135,6 +135,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -120,6 +120,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -127,6 +127,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -59,6 +59,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -71,6 +71,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -115,6 +115,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -62,6 +62,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -84,6 +84,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -90,6 +90,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -109,6 +109,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -104,6 +104,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -67,6 +67,7 @@ public:
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@ -26,6 +26,7 @@
#include <boost/checked_delete.hpp>
#include <boost/smart_ptr/detail/sp_counted_base.hpp>
#include <boost/core/addressof.hpp>
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
#include <boost/smart_ptr/detail/quick_allocator.hpp>
@ -50,6 +51,19 @@ void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn );
namespace detail
{
// get_local_deleter
template<class D> class local_sp_deleter;
template<class D> D * get_local_deleter( D * /*p*/ )
{
return 0;
}
template<class D> D * get_local_deleter( local_sp_deleter<D> * p );
//
template<class X> class sp_counted_impl_p: public sp_counted_base
{
private:
@ -83,6 +97,11 @@ public:
return 0;
}
virtual void * get_local_deleter( sp_typeinfo const & )
{
return 0;
}
virtual void * get_untyped_deleter()
{
return 0;
@ -158,6 +177,11 @@ public:
return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0;
}
virtual void * get_local_deleter( sp_typeinfo const & ti )
{
return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( del ) ): 0;
}
virtual void * get_untyped_deleter()
{
return &reinterpret_cast<char&>( del );
@ -246,6 +270,11 @@ public:
return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast<char&>( d_ ): 0;
}
virtual void * get_local_deleter( sp_typeinfo const & ti )
{
return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( d_ ) ): 0;
}
virtual void * get_untyped_deleter()
{
return &reinterpret_cast<char&>( d_ );

View File

@ -11,7 +11,6 @@
//
// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/smart_ptr/detail/local_counted_base.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
namespace boost
@ -22,46 +21,7 @@ template<class T> class local_shared_ptr;
namespace detail
{
template<class D> class local_sp_deleter: public local_counted_impl_em
{
private:
D d_;
public:
local_sp_deleter(): d_()
{
}
explicit local_sp_deleter( D const& d ) BOOST_SP_NOEXCEPT: d_( d )
{
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
explicit local_sp_deleter( D&& d ) BOOST_SP_NOEXCEPT: d_( std::move(d) )
{
}
#endif
template<class Y> void operator()( Y* p ) const BOOST_SP_NOEXCEPT
{
d_( p );
}
#if !defined( BOOST_NO_CXX11_NULLPTR )
void operator()( boost::detail::sp_nullptr_t p ) const BOOST_SP_NOEXCEPT
{
d_( p );
}
#endif
};
template< class E, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E > * ppx, Y * p, boost::detail::local_counted_base * & pn )
template< class E, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn )
{
boost::detail::sp_assert_convertible< Y, E >();
@ -71,12 +31,12 @@ template< class E, class Y > inline void lsp_pointer_construct( boost::local_sha
D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() );
pd->pn_ = p2;
pd->pn_ = p2._internal_count();
pn = pd;
}
template< class E, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E[] > * ppx, Y * p, boost::detail::local_counted_base * & pn )
template< class E, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E[] > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn )
{
boost::detail::sp_assert_convertible< Y[], E[] >();
@ -86,12 +46,12 @@ template< class E, class Y > inline void lsp_pointer_construct( boost::local_sha
D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() );
pd->pn_ = p2;
pd->pn_ = p2._internal_count();
pn = pd;
}
template< class E, std::size_t N, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E[N] > * ppx, Y * p, boost::detail::local_counted_base * & pn )
template< class E, std::size_t N, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E[N] > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn )
{
boost::detail::sp_assert_convertible< Y[N], E[N] >();
@ -101,12 +61,12 @@ template< class E, std::size_t N, class Y > inline void lsp_pointer_construct( b
D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() );
pd->pn_ = p2;
pd->pn_ = p2._internal_count();
pn = pd;
}
template< class E, class P, class D > inline void lsp_deleter_construct( boost::local_shared_ptr< E > * ppx, P p, D const& d, boost::detail::local_counted_base * & pn )
template< class E, class P, class D > inline void lsp_deleter_construct( boost::local_shared_ptr< E > * /*ppx*/, P p, D const& d, boost::detail::local_counted_base * & pn )
{
typedef boost::detail::local_sp_deleter<D> D2;
@ -114,12 +74,12 @@ template< class E, class P, class D > inline void lsp_deleter_construct( boost::
D2 * pd = static_cast< D2 * >( p2._internal_get_untyped_deleter() );
pd->pn_ = p2;
pd->pn_ = p2._internal_count();
pn = pd;
}
template< class E, class P, class D, class A > inline void lsp_allocator_construct( boost::local_shared_ptr< E > * ppx, P p, D const& d, A const& a, boost::detail::local_counted_base * & pn )
template< class E, class P, class D, class A > inline void lsp_allocator_construct( boost::local_shared_ptr< E > * /*ppx*/, P p, D const& d, A const& a, boost::detail::local_counted_base * & pn )
{
typedef boost::detail::local_sp_deleter<D> D2;
@ -127,11 +87,15 @@ template< class E, class P, class D, class A > inline void lsp_allocator_constru
D2 * pd = static_cast< D2 * >( p2._internal_get_untyped_deleter() );
pd->pn_ = p2;
pd->pn_ = p2._internal_count();
pn = pd;
}
struct lsp_internal_constructor_tag
{
};
} // namespace detail
//
@ -184,6 +148,11 @@ public:
#endif
// internal constructor, used by make_shared
BOOST_CONSTEXPR local_shared_ptr( boost::detail::lsp_internal_constructor_tag, T * px_, boost::detail::local_counted_base * pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( pn_ )
{
}
template<class Y>
explicit local_shared_ptr( Y * p ): px( p ), pn( 0 )
{
@ -228,7 +197,7 @@ public:
if( r.use_count() != 0 )
{
pn = new boost::detail::local_counted_impl( r );
pn = new boost::detail::local_counted_impl( r._internal_count() );
}
}
@ -242,7 +211,8 @@ public:
if( r.use_count() != 0 )
{
pn = new boost::detail::local_counted_impl( std::move(r) );
pn = new boost::detail::local_counted_impl( r._internal_count() );
r.reset();
}
}
@ -261,7 +231,7 @@ public:
if( px )
{
pn = new boost::detail::local_counted_impl( shared_ptr<T>( std::move(r) ) );
pn = new boost::detail::local_counted_impl( shared_ptr<T>( std::move(r) )._internal_count() );
}
}
@ -484,7 +454,7 @@ public:
if( pn )
{
return static_pointer_cast<Y>( pn->get_shared_ptr() );
return shared_ptr<Y>( boost::detail::sp_internal_constructor_tag(), px, pn->local_cb_get_shared_count() );
}
else
{
@ -502,7 +472,7 @@ public:
if( pn )
{
return static_pointer_cast<Y>( pn->get_shared_ptr() );
return shared_ptr<Y>( boost::detail::sp_internal_constructor_tag(), px, pn->local_cb_get_shared_count() );
}
else
{
@ -693,6 +663,13 @@ template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< ( std:
#endif // !defined(BOOST_NO_IOSTREAM)
// get_deleter
template<class D, class T> D * get_deleter( local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
return get_deleter<D>( shared_ptr<T>( p ) );
}
// hash_value
template< class T > struct hash;

View File

@ -0,0 +1,17 @@
#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED
#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED
// make_local_shared.hpp
//
// Copyright 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/smart_ptr/make_local_shared_object.hpp>
#include <boost/smart_ptr/make_local_shared_array.hpp>
#endif // #ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED

View File

@ -0,0 +1,63 @@
#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP_INCLUDED
#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP_INCLUDED
// make_local_shared_array.hpp
//
// Copyright 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/config.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <utility>
#include <cstddef>
namespace boost
{
namespace detail
{
template<class T> struct lsp_if_array
{
};
template<class T> struct lsp_if_array<T[]>
{
typedef boost::local_shared_ptr<T[]> type;
};
template<class T, std::size_t N> struct lsp_if_array<T[N]>
{
typedef boost::local_shared_ptr<T[N]> type;
};
} // namespace detail
template<class T, class... Args> typename boost::detail::lsp_if_array<T>::type make_local_shared( Args&&... args )
{
return boost::make_shared<T>( std::forward<Args>(args)... );
}
template<class T, class... Args> typename boost::detail::lsp_if_array<T>::type make_local_shared_noinit( Args&&... args )
{
return boost::make_shared_noinit<T>( std::forward<Args>(args)... );
}
template<class T, class A, class... Args> typename boost::detail::lsp_if_array<T>::type allocate_local_shared( A const & a, Args&&... args )
{
return boost::allocate_shared<T>( a, std::forward<Args>(args)... );
}
template<class T, class A, class... Args> typename boost::detail::lsp_if_array<T>::type allocate_local_shared_noinit( A const & a, Args&&... args )
{
return boost::allocate_shared_noinit<T>( a, std::forward<Args>(args)... );
}
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED

View File

@ -0,0 +1,199 @@
#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_OBJECT_HPP_INCLUDED
#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_OBJECT_HPP_INCLUDED
// make_local_shared_object.hpp
//
// Copyright 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/smart_ptr/local_shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <boost/config.hpp>
#include <utility>
#include <cstddef>
namespace boost
{
namespace detail
{
// lsp_if_not_array
template<class T> struct lsp_if_not_array
{
typedef boost::local_shared_ptr<T> type;
};
template<class T> struct lsp_if_not_array<T[]>
{
};
template<class T, std::size_t N> struct lsp_if_not_array<T[N]>
{
};
// lsp_ms_deleter
template<class T, class A> class lsp_ms_deleter: public local_counted_impl_em
{
private:
typedef typename sp_aligned_storage<sizeof(T), ::boost::alignment_of<T>::value>::type storage_type;
storage_type storage_;
A a_;
bool initialized_;
private:
void destroy() BOOST_SP_NOEXCEPT
{
if( initialized_ )
{
T * p = reinterpret_cast< T* >( storage_.data_ );
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
std::allocator_traits<A>::destroy( a_, p );
#else
p->~T();
#endif
initialized_ = false;
}
}
public:
explicit lsp_ms_deleter( A const & a ) BOOST_SP_NOEXCEPT : a_( a ), initialized_( false )
{
}
// optimization: do not copy storage_
lsp_ms_deleter( lsp_ms_deleter const & r ) BOOST_SP_NOEXCEPT : a_( r.a_), initialized_( false )
{
}
~lsp_ms_deleter() BOOST_SP_NOEXCEPT
{
destroy();
}
void operator()( T * ) BOOST_SP_NOEXCEPT
{
destroy();
}
static void operator_fn( T* ) BOOST_SP_NOEXCEPT // operator() can't be static
{
}
void * address() BOOST_SP_NOEXCEPT
{
return storage_.data_;
}
void set_initialized() BOOST_SP_NOEXCEPT
{
initialized_ = true;
}
};
} // namespace detail
template<class T, class A, class... Args> typename boost::detail::lsp_if_not_array<T>::type allocate_local_shared( A const & a, Args&&... args )
{
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
#else
typedef typename A::template rebind<T>::other A2;
#endif
A2 a2( a );
typedef boost::detail::lsp_ms_deleter<T, A2> D;
boost::shared_ptr<T> pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
void * pv = pd->address();
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
std::allocator_traits<A2>::construct( a2, static_cast< T* >( pv ), std::forward<Args>( args )... );
#else
::new( pv ) T( std::forward<Args>( args )... );
#endif
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
pd->pn_ = pt._internal_count();
return boost::local_shared_ptr<T>( boost::detail::lsp_internal_constructor_tag(), pt2, pd );
}
template<class T, class A> typename boost::detail::lsp_if_not_array<T>::type allocate_local_shared_noinit( A const & a )
{
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
#else
typedef typename A::template rebind<T>::other A2;
#endif
A2 a2( a );
typedef boost::detail::lsp_ms_deleter<T, A2> D;
boost::shared_ptr<T> pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
void * pv = pd->address();
::new( pv ) T;
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
pd->pn_ = pt._internal_count();
return boost::local_shared_ptr<T>( boost::detail::lsp_internal_constructor_tag(), pt2, pd );
}
template<class T, class... Args> typename boost::detail::lsp_if_not_array<T>::type make_local_shared( Args&&... args )
{
return boost::allocate_local_shared<T>( std::allocator<T>(), std::forward<Args>(args)... );
}
template<class T> typename boost::detail::lsp_if_not_array<T>::type make_local_shared_noinit()
{
return boost::allocate_shared_noinit<T>( std::allocator<T>() );
}
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED

View File

@ -323,6 +323,10 @@ template< class T, std::size_t N, class Y > inline void sp_deleter_construct( bo
#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
struct sp_internal_constructor_tag
{
};
} // namespace detail
@ -355,6 +359,18 @@ public:
{
}
#endif
BOOST_CONSTEXPR shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count const & pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( pn_ )
{
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
BOOST_CONSTEXPR shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count && pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( std::move( pn_ ) )
{
}
#endif
template<class Y>
@ -766,6 +782,11 @@ public:
return pn.get_deleter( ti );
}
void * _internal_get_local_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
{
return pn.get_local_deleter( ti );
}
void * _internal_get_untyped_deleter() const BOOST_SP_NOEXCEPT
{
return pn.get_untyped_deleter();
@ -776,6 +797,11 @@ public:
return px == r.px && pn == r.pn;
}
boost::detail::shared_count _internal_count() const BOOST_NOEXCEPT
{
return pn;
}
// Tasteless as this may seem, making all members public allows member templates
// to work in the absence of member template friends. (Matthew Langston)
@ -980,27 +1006,13 @@ template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::
namespace detail
{
#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
// g++ 2.9x doesn't allow static_cast<X const *>(void *)
// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
template<class D, class T> D * basic_get_deleter(shared_ptr<T> const & p)
{
void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
return const_cast<D *>(static_cast<D const *>(q));
}
#else
template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID(D)) );
}
#endif
template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT;
template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT;
class esft2_deleter_wrapper
{
@ -1035,17 +1047,22 @@ public:
template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
D *del = boost::detail::basic_get_deleter<D>(p);
D * d = boost::detail::basic_get_deleter<D>( p );
if(del == 0)
if( d == 0 )
{
d = boost::detail::basic_get_local_deleter( d, p );
}
if( d == 0 )
{
boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p);
// The following get_deleter method call is fully qualified because
// older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>()
if(del_wrapper) del = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>();
if(del_wrapper) d = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>();
}
return del;
return d;
}
// atomic access
@ -1138,6 +1155,28 @@ template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOO
} // namespace boost
#include <boost/smart_ptr/detail/local_sp_deleter.hpp>
namespace boost
{
namespace detail
{
template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID(local_sp_deleter<D>) ) );
}
template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID(local_sp_deleter<D>) ) );
}
} // namespace detail
} // namespace boost
#if defined( BOOST_SP_DISABLE_DEPRECATED )
#pragma GCC diagnostic pop
#endif

View File

@ -230,5 +230,18 @@ import testing ;
[ run lsp_array_n_test.cpp ]
[ run lsp_array_cv_test.cpp ]
[ run lsp_array_cast_test.cpp ]
[ run get_local_deleter_test.cpp ]
[ run get_local_deleter_test2.cpp ]
[ run get_local_deleter_test3.cpp ]
[ run get_local_deleter_array_test.cpp ]
[ run get_local_deleter_array_test2.cpp ]
[ run make_local_shared_test.cpp ]
[ run make_local_shared_esft_test.cpp ]
[ run allocate_local_shared_test.cpp ]
[ run allocate_local_shared_esft_test.cpp ]
[ run local_sp_fn_test.cpp ]
;
}

View File

@ -0,0 +1,298 @@
// allocate_local_shared_esft_test.cpp
//
// Copyright 2007-2009, 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) || defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES )
int main()
{
}
#else
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/make_local_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <memory>
class X: public boost::enable_shared_from_this<X>
{
private:
X( X const & );
X & operator=( X const & );
public:
static int instances;
explicit X( int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0 )
{
++instances;
}
~X()
{
--instances;
}
};
int X::instances = 0;
int main()
{
BOOST_TEST_EQ( X::instances, 0 );
{
boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>() );
BOOST_TEST_EQ( X::instances, 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST_EQ( px, qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST_EQ( X::instances, 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST_EQ( X::instances, 0 );
{
boost::shared_ptr< X > px = boost::allocate_local_shared_noinit< X >( std::allocator<void>() );
BOOST_TEST_EQ( X::instances, 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST_EQ( px, qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST_EQ( X::instances, 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST_EQ( X::instances, 0 );
{
boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1 );
BOOST_TEST_EQ( X::instances, 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST_EQ( px, qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST_EQ( X::instances, 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST_EQ( X::instances, 0 );
{
boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2 );
BOOST_TEST_EQ( X::instances, 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST_EQ( px, qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST_EQ( X::instances, 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST_EQ( X::instances, 0 );
{
boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3 );
BOOST_TEST_EQ( X::instances, 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST_EQ( px, qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST_EQ( X::instances, 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST_EQ( X::instances, 0 );
{
boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4 );
BOOST_TEST_EQ( X::instances, 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST_EQ( px, qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST_EQ( X::instances, 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST_EQ( X::instances, 0 );
{
boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5 );
BOOST_TEST_EQ( X::instances, 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST_EQ( px, qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST_EQ( X::instances, 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST_EQ( X::instances, 0 );
{
boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6 );
BOOST_TEST_EQ( X::instances, 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST_EQ( px, qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST_EQ( X::instances, 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST_EQ( X::instances, 0 );
{
boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
BOOST_TEST_EQ( X::instances, 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST_EQ( px, qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST_EQ( X::instances, 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST_EQ( X::instances, 0 );
{
boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
BOOST_TEST_EQ( X::instances, 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST_EQ( px, qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST_EQ( X::instances, 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST_EQ( X::instances, 0 );
{
boost::shared_ptr< X > px = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
BOOST_TEST_EQ( X::instances, 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST_EQ( px, qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST_EQ( X::instances, 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST_EQ( X::instances, 0 );
return boost::report_errors();
}
#endif

View File

@ -0,0 +1,235 @@
// allocate_local_shared_test.cpp
//
// Copyright 2007-2009, 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) || defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES )
int main()
{
}
#else
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/make_local_shared.hpp>
#include <boost/smart_ptr/local_shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <cstddef>
class X
{
private:
X( X const & );
X & operator=( X const & );
void * operator new( std::size_t n )
{
// lack of this definition causes link errors on Comeau C++
BOOST_ERROR( "private X::new called" );
return ::operator new( n );
}
void operator delete( void * p )
{
// lack of this definition causes link errors on MSVC
BOOST_ERROR( "private X::delete called" );
::operator delete( p );
}
public:
static int instances;
int v;
explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
{
++instances;
}
~X()
{
--instances;
}
};
int X::instances = 0;
int main()
{
{
boost::local_shared_ptr< int > pi = boost::allocate_local_shared< int >( std::allocator<int>() );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( *pi == 0 );
}
{
boost::local_shared_ptr< int > pi = boost::allocate_local_shared_noinit< int >( std::allocator<int>() );
BOOST_TEST( pi.get() != 0 );
}
{
boost::local_shared_ptr< int > pi = boost::allocate_local_shared< int >( std::allocator<int>(), 5 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( *pi == 5 );
}
BOOST_TEST( X::instances == 0 );
{
boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>() );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 0 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::allocate_local_shared_noinit< X >( std::allocator<void>() );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 0 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::allocate_local_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
return boost::report_errors();
}
#endif

View File

@ -62,6 +62,28 @@ int main()
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared_noinit< X >( std::allocator<void>() );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1 );
BOOST_TEST( X::instances == 1 );

View File

@ -61,6 +61,12 @@ int main()
BOOST_TEST( *pi == 0 );
}
{
boost::shared_ptr< int > pi = boost::allocate_shared_noinit< int >( std::allocator<int>() );
BOOST_TEST( pi.get() != 0 );
}
{
boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator<int>(), 5 );
@ -83,6 +89,19 @@ int main()
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared_noinit< X >( std::allocator<void>() );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 0 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1 );
boost::weak_ptr<X> wp( pi );

View File

@ -0,0 +1,151 @@
//
// get_local_deleter_array_test2.cpp
//
// Copyright 2002, 2011, 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/smart_ptr/local_shared_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
struct deleter
{
int data;
deleter(): data(0)
{
}
void operator()(void *)
{
BOOST_TEST(data == 17041);
}
};
struct deleter2
{
};
struct X
{
};
int main()
{
{
boost::local_shared_ptr<X[]> p;
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
}
{
boost::local_shared_ptr<X[1]> p;
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
}
{
boost::local_shared_ptr<X[]> p(new X[1]);
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
}
{
boost::local_shared_ptr<X[1]> p(new X[1]);
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
}
{
X x[1];
boost::local_shared_ptr<X[]> p(x, deleter());
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
deleter * q = boost::get_deleter<deleter>(p);
BOOST_TEST(q != 0);
BOOST_TEST(q->data == 0);
q->data = 17041;
deleter const * r = boost::get_deleter<deleter const>(p);
BOOST_TEST(r == q);
BOOST_TEST(r->data == 17041);
}
{
X x[1];
boost::local_shared_ptr<X[1]> p(x, deleter());
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
deleter * q = boost::get_deleter<deleter>(p);
BOOST_TEST(q != 0);
BOOST_TEST(q->data == 0);
q->data = 17041;
deleter const * r = boost::get_deleter<deleter const>(p);
BOOST_TEST(r == q);
BOOST_TEST(r->data == 17041);
}
return boost::report_errors();
}

View File

@ -0,0 +1,74 @@
//
// get_local_deleter_test2.cpp
//
// Copyright 2002, 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/config.hpp>
#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) || defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES )
int main()
{
}
#else
#include <boost/smart_ptr/local_shared_ptr.hpp>
#include <boost/smart_ptr/make_local_shared.hpp>
#include <boost/core/lightweight_test.hpp>
struct deleter
{
};
struct deleter2;
struct X
{
};
int main()
{
{
boost::local_shared_ptr<X[]> p = boost::make_local_shared<X[]>( 1 );
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
}
{
boost::local_shared_ptr<X[1]> p = boost::make_local_shared<X[1]>();
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
}
return boost::report_errors();
}
struct deleter2
{
};
#endif

View File

@ -0,0 +1,95 @@
//
// get_local_deleter_test.cpp
//
// Copyright 2002, 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/smart_ptr/local_shared_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
struct deleter
{
int data;
deleter(): data(0)
{
}
void operator()(void *)
{
BOOST_TEST(data == 17041);
}
};
struct deleter2
{
};
struct X
{
};
int main()
{
{
boost::local_shared_ptr<X> p;
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
}
{
boost::local_shared_ptr<X> p(new X);
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
}
{
X x;
boost::local_shared_ptr<X> p(&x, deleter());
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
deleter * q = boost::get_deleter<deleter>(p);
BOOST_TEST(q != 0);
BOOST_TEST(q->data == 0);
q->data = 17041;
deleter const * r = boost::get_deleter<deleter const>(p);
BOOST_TEST(r == q);
BOOST_TEST(r->data == 17041);
}
return boost::report_errors();
}

View File

@ -0,0 +1,43 @@
//
// get_local_deleter_test2.cpp
//
// Copyright 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/smart_ptr/local_shared_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
struct deleter;
struct X
{
};
static void test_lsp_get_deleter( boost::local_shared_ptr<X> const & p )
{
BOOST_TEST( boost::get_deleter<deleter>( p ) != 0 );
}
static void test_sp_get_deleter( boost::shared_ptr<X> const & p )
{
BOOST_TEST( boost::get_deleter<deleter>( p ) != 0 );
}
struct deleter
{
void operator()( X const * p ) { delete p; }
};
int main()
{
boost::local_shared_ptr<X> p( new X, deleter() );
test_lsp_get_deleter( p );
test_sp_get_deleter( p );
return boost::report_errors();
}

View File

@ -0,0 +1,59 @@
//
// get_local_deleter_test3.cpp
//
// Copyright 2002, 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/config.hpp>
#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) || defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES )
int main()
{
}
#else
#include <boost/smart_ptr/local_shared_ptr.hpp>
#include <boost/smart_ptr/make_local_shared.hpp>
#include <boost/core/lightweight_test.hpp>
struct deleter
{
};
struct deleter2;
struct X
{
};
int main()
{
{
boost::local_shared_ptr<X> p = boost::make_local_shared<X>();
BOOST_TEST(boost::get_deleter<void>(p) == 0);
BOOST_TEST(boost::get_deleter<void const>(p) == 0);
BOOST_TEST(boost::get_deleter<int>(p) == 0);
BOOST_TEST(boost::get_deleter<int const>(p) == 0);
BOOST_TEST(boost::get_deleter<X>(p) == 0);
BOOST_TEST(boost::get_deleter<X const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter const>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2>(p) == 0);
BOOST_TEST(boost::get_deleter<deleter2 const>(p) == 0);
}
return boost::report_errors();
}
struct deleter2
{
};
#endif

43
test/local_sp_fn_test.cpp Normal file
View File

@ -0,0 +1,43 @@
//
// local_sp_fn_test.cpp
//
// Copyright 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/smart_ptr/local_shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
static void f()
{
}
struct null_deleter
{
template<class Y> void operator()( Y* ) {}
};
int main()
{
boost::local_shared_ptr<void()> pf( f, null_deleter() );
BOOST_TEST( pf.get() == f );
BOOST_TEST_EQ( pf.local_use_count(), 1 );
BOOST_TEST( boost::get_deleter<null_deleter>( pf ) != 0 );
boost::weak_ptr<void()> wp( pf );
BOOST_TEST( wp.lock().get() == f );
BOOST_TEST_EQ( wp.use_count(), 1 );
pf.reset();
BOOST_TEST( wp.lock().get() == 0 );
BOOST_TEST_EQ( wp.use_count(), 0 );
return boost::report_errors();
}

View File

@ -9,6 +9,8 @@
//
#include <boost/smart_ptr/local_shared_ptr.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/weak_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
struct X
@ -1679,6 +1681,809 @@ static void shared_ptr_move_assignment()
#endif
// unique_ptr assignment
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) && !defined( BOOST_NO_CXX11_SMART_PTR )
template<class T> static void empty_unique_ptr_assign_test()
{
boost::local_shared_ptr<T> p2;
p2 = std::unique_ptr<T>();
BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
BOOST_TEST_EQ( p2.local_use_count(), 0 );
boost::local_shared_ptr<T const> p3;
p3 = std::unique_ptr<T>();
BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
BOOST_TEST_EQ( p3.local_use_count(), 0 );
boost::local_shared_ptr<void> p4;
p4 = std::unique_ptr<T>();
BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
BOOST_TEST_EQ( p4.local_use_count(), 0 );
boost::local_shared_ptr<void const> p5;
p5 = std::unique_ptr<T const>();
BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
BOOST_TEST_EQ( p5.local_use_count(), 0 );
}
template<class T> static void empty_unique_ptr_assign_test_()
{
boost::local_shared_ptr<T> p2( static_cast<T*>(0) );
p2 = std::unique_ptr<T>();
BOOST_TEST_EQ( p2.get(), static_cast<void*>(0) );
BOOST_TEST_EQ( p2.local_use_count(), 0 );
boost::local_shared_ptr<T const> p3( static_cast<T const*>(0) );
p3 = std::unique_ptr<T>();
BOOST_TEST_EQ( p3.get(), static_cast<void*>(0) );
BOOST_TEST_EQ( p3.local_use_count(), 0 );
boost::local_shared_ptr<void> p4( static_cast<T*>(0) );
p4 = std::unique_ptr<T>();
BOOST_TEST_EQ( p4.get(), static_cast<void*>(0) );
BOOST_TEST_EQ( p4.local_use_count(), 0 );
boost::local_shared_ptr<void const> p5( static_cast<T const*>(0) );
p5 = std::unique_ptr<T const>();
BOOST_TEST_EQ( p5.get(), static_cast<void*>(0) );
BOOST_TEST_EQ( p5.local_use_count(), 0 );
}
template<class T, class U, class D> static void test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T> p2, std::unique_ptr<U, D> && p1 )
{
U* q = p1.get();
p2 = std::move( p1 );
BOOST_TEST_EQ( p2.get(), q );
BOOST_TEST_EQ( p2.local_use_count(), 1 );
BOOST_TEST( p1.get() == 0 );
}
template<class T> static void new_unique_ptr_assign_test()
{
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T>(), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const>(), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T volatile>(), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const volatile>(), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T>( static_cast<T*>(0) ), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const>( static_cast<T const*>(0) ), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T volatile>( static_cast<T volatile*>(0) ), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const volatile>( static_cast<T const volatile*>(0) ), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T>( new T() ), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const>( new T const() ), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T volatile>( new T volatile() ), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const volatile>( new T const volatile() ), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void>(), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void const>(), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void volatile>(), std::unique_ptr<T>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void const volatile>(), std::unique_ptr<T>( new T() ) );
}
template<class T> static void del_unique_ptr_assign_test()
{
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T volatile>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const volatile>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T>( static_cast<T*>(0) ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const>( static_cast<T const*>(0) ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T volatile>( static_cast<T volatile*>(0) ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const volatile>( static_cast<T const volatile*>(0) ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T>( new T() ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const>( new T const() ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T volatile>( new T volatile() ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<T const volatile>( new T const volatile() ), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void const>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void volatile>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
test_nonempty_unique_ptr_assign( boost::local_shared_ptr<void const volatile>(), std::unique_ptr<T, boost::checked_deleter<T>>( new T() ) );
}
static void unique_ptr_assignment()
{
empty_unique_ptr_assign_test<int>();
empty_unique_ptr_assign_test_<int>();
empty_unique_ptr_assign_test<X>();
empty_unique_ptr_assign_test_<X>();
BOOST_TEST( X::instances == 0 );
new_unique_ptr_assign_test<int>();
new_unique_ptr_assign_test<X>();
BOOST_TEST( X::instances == 0 );
del_unique_ptr_assign_test<int>();
del_unique_ptr_assign_test<X>();
BOOST_TEST( X::instances == 0 );
}
#else
static void unique_ptr_assignment()
{
}
#endif
// pointer reset
template<class T, class U> static void test_pointer_reset( boost::local_shared_ptr<U> p2 )
{
T * q = new T();
p2.reset( q );
BOOST_TEST_EQ( p2.get(), q );
BOOST_TEST_EQ( p2.local_use_count(), 1 );
}
template<class T> static void empty_pointer_reset_test()
{
test_pointer_reset<T>( boost::local_shared_ptr<T>() );
test_pointer_reset<T>( boost::local_shared_ptr<T const>() );
test_pointer_reset<T>( boost::local_shared_ptr<T volatile>() );
test_pointer_reset<T>( boost::local_shared_ptr<T const volatile>() );
test_pointer_reset<T>( boost::local_shared_ptr<void>() );
test_pointer_reset<T>( boost::local_shared_ptr<void const>() );
test_pointer_reset<T>( boost::local_shared_ptr<void volatile>() );
test_pointer_reset<T>( boost::local_shared_ptr<void const volatile>() );
}
template<class T> static void null_pointer_reset_test()
{
test_pointer_reset<T>( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
test_pointer_reset<T>( boost::local_shared_ptr<T const>( static_cast<T*>(0) ) );
test_pointer_reset<T>( boost::local_shared_ptr<T volatile>( static_cast<T*>(0) ) );
test_pointer_reset<T>( boost::local_shared_ptr<T const volatile>( static_cast<T*>(0) ) );
test_pointer_reset<T>( boost::local_shared_ptr<void>( static_cast<T*>(0) ) );
test_pointer_reset<T>( boost::local_shared_ptr<void const>( static_cast<T*>(0) ) );
test_pointer_reset<T>( boost::local_shared_ptr<void volatile>( static_cast<T*>(0) ) );
test_pointer_reset<T>( boost::local_shared_ptr<void const volatile>( static_cast<T*>(0) ) );
}
template<class T> static void new_pointer_reset_test()
{
test_pointer_reset<T>( boost::local_shared_ptr<T>( new T() ) );
test_pointer_reset<T>( boost::local_shared_ptr<T const>( new T() ) );
test_pointer_reset<T>( boost::local_shared_ptr<T volatile>( new T() ) );
test_pointer_reset<T>( boost::local_shared_ptr<T const volatile>( new T() ) );
test_pointer_reset<T>( boost::local_shared_ptr<void>( new T() ) );
test_pointer_reset<T>( boost::local_shared_ptr<void const>( new T() ) );
test_pointer_reset<T>( boost::local_shared_ptr<void volatile>( new T() ) );
test_pointer_reset<T>( boost::local_shared_ptr<void const volatile>( new T() ) );
}
static void pointer_reset()
{
empty_pointer_reset_test<int>();
empty_pointer_reset_test<X>();
BOOST_TEST( X::instances == 0 );
null_pointer_reset_test<int>();
null_pointer_reset_test<X>();
BOOST_TEST( X::instances == 0 );
new_pointer_reset_test<int>();
new_pointer_reset_test<X>();
BOOST_TEST( X::instances == 0 );
}
// deleter reset
template<class T> class deleter
{
private:
bool * called_;
public:
explicit deleter( bool * called ): called_( called ) {}
void operator()( T * p ) { *called_ = true; delete p; }
};
template<class T, class U> static void test_deleter_reset( boost::local_shared_ptr<U> p2 )
{
T * q = new T();
bool called = false;
p2.reset( q, deleter<T>( &called ) );
BOOST_TEST_EQ( p2.get(), q );
BOOST_TEST_EQ( p2.local_use_count(), 1 );
boost::shared_ptr<U> p3( p2 );
BOOST_TEST( boost::get_deleter< deleter<T> >( p3 ) != 0 );
p3.reset();
BOOST_TEST( !called );
p2.reset();
BOOST_TEST( called );
}
template<class T> static void empty_deleter_reset_test()
{
test_deleter_reset<T>( boost::local_shared_ptr<T>() );
test_deleter_reset<T>( boost::local_shared_ptr<T const>() );
test_deleter_reset<T>( boost::local_shared_ptr<T volatile>() );
test_deleter_reset<T>( boost::local_shared_ptr<T const volatile>() );
test_deleter_reset<T>( boost::local_shared_ptr<void>() );
test_deleter_reset<T>( boost::local_shared_ptr<void const>() );
test_deleter_reset<T>( boost::local_shared_ptr<void volatile>() );
test_deleter_reset<T>( boost::local_shared_ptr<void const volatile>() );
}
template<class T> static void null_deleter_reset_test()
{
test_deleter_reset<T>( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
test_deleter_reset<T>( boost::local_shared_ptr<T const>( static_cast<T*>(0) ) );
test_deleter_reset<T>( boost::local_shared_ptr<T volatile>( static_cast<T*>(0) ) );
test_deleter_reset<T>( boost::local_shared_ptr<T const volatile>( static_cast<T*>(0) ) );
test_deleter_reset<T>( boost::local_shared_ptr<void>( static_cast<T*>(0) ) );
test_deleter_reset<T>( boost::local_shared_ptr<void const>( static_cast<T*>(0) ) );
test_deleter_reset<T>( boost::local_shared_ptr<void volatile>( static_cast<T*>(0) ) );
test_deleter_reset<T>( boost::local_shared_ptr<void const volatile>( static_cast<T*>(0) ) );
}
template<class T> static void new_deleter_reset_test()
{
test_deleter_reset<T>( boost::local_shared_ptr<T>( new T() ) );
test_deleter_reset<T>( boost::local_shared_ptr<T const>( new T() ) );
test_deleter_reset<T>( boost::local_shared_ptr<T volatile>( new T() ) );
test_deleter_reset<T>( boost::local_shared_ptr<T const volatile>( new T() ) );
test_deleter_reset<T>( boost::local_shared_ptr<void>( new T() ) );
test_deleter_reset<T>( boost::local_shared_ptr<void const>( new T() ) );
test_deleter_reset<T>( boost::local_shared_ptr<void volatile>( new T() ) );
test_deleter_reset<T>( boost::local_shared_ptr<void const volatile>( new T() ) );
}
static void deleter_reset()
{
empty_deleter_reset_test<int>();
empty_deleter_reset_test<X>();
BOOST_TEST( X::instances == 0 );
null_deleter_reset_test<int>();
null_deleter_reset_test<X>();
BOOST_TEST( X::instances == 0 );
new_deleter_reset_test<int>();
new_deleter_reset_test<X>();
BOOST_TEST( X::instances == 0 );
}
// allocator reset
template<class T, class U> static void test_allocator_reset( boost::local_shared_ptr<U> p2 )
{
T * q = new T();
bool called = false;
p2.reset( q, deleter<T>( &called ), std::allocator<T>() );
BOOST_TEST_EQ( p2.get(), q );
BOOST_TEST_EQ( p2.local_use_count(), 1 );
boost::shared_ptr<U> p3( p2 );
BOOST_TEST( boost::get_deleter< deleter<T> >( p3 ) != 0 );
p3.reset();
BOOST_TEST( !called );
p2.reset();
BOOST_TEST( called );
}
template<class T> static void empty_allocator_reset_test()
{
test_allocator_reset<T>( boost::local_shared_ptr<T>() );
test_allocator_reset<T>( boost::local_shared_ptr<T const>() );
test_allocator_reset<T>( boost::local_shared_ptr<T volatile>() );
test_allocator_reset<T>( boost::local_shared_ptr<T const volatile>() );
test_allocator_reset<T>( boost::local_shared_ptr<void>() );
test_allocator_reset<T>( boost::local_shared_ptr<void const>() );
test_allocator_reset<T>( boost::local_shared_ptr<void volatile>() );
test_allocator_reset<T>( boost::local_shared_ptr<void const volatile>() );
}
template<class T> static void null_allocator_reset_test()
{
test_allocator_reset<T>( boost::local_shared_ptr<T>( static_cast<T*>(0) ) );
test_allocator_reset<T>( boost::local_shared_ptr<T const>( static_cast<T*>(0) ) );
test_allocator_reset<T>( boost::local_shared_ptr<T volatile>( static_cast<T*>(0) ) );
test_allocator_reset<T>( boost::local_shared_ptr<T const volatile>( static_cast<T*>(0) ) );
test_allocator_reset<T>( boost::local_shared_ptr<void>( static_cast<T*>(0) ) );
test_allocator_reset<T>( boost::local_shared_ptr<void const>( static_cast<T*>(0) ) );
test_allocator_reset<T>( boost::local_shared_ptr<void volatile>( static_cast<T*>(0) ) );
test_allocator_reset<T>( boost::local_shared_ptr<void const volatile>( static_cast<T*>(0) ) );
}
template<class T> static void new_allocator_reset_test()
{
test_allocator_reset<T>( boost::local_shared_ptr<T>( new T() ) );
test_allocator_reset<T>( boost::local_shared_ptr<T const>( new T() ) );
test_allocator_reset<T>( boost::local_shared_ptr<T volatile>( new T() ) );
test_allocator_reset<T>( boost::local_shared_ptr<T const volatile>( new T() ) );
test_allocator_reset<T>( boost::local_shared_ptr<void>( new T() ) );
test_allocator_reset<T>( boost::local_shared_ptr<void const>( new T() ) );
test_allocator_reset<T>( boost::local_shared_ptr<void volatile>( new T() ) );
test_allocator_reset<T>( boost::local_shared_ptr<void const volatile>( new T() ) );
}
static void allocator_reset()
{
empty_allocator_reset_test<int>();
empty_allocator_reset_test<X>();
BOOST_TEST( X::instances == 0 );
null_allocator_reset_test<int>();
null_allocator_reset_test<X>();
BOOST_TEST( X::instances == 0 );
new_allocator_reset_test<int>();
new_allocator_reset_test<X>();
BOOST_TEST( X::instances == 0 );
}
// aliasing reset
struct null_deleter
{
void operator()( void const volatile* ) {}
};
template<class T, class U> void test_aliasing_reset_( boost::local_shared_ptr<T> const & p1, U * p2 )
{
boost::local_shared_ptr<U> p3( static_cast<U*>(0), null_deleter() );
p3.reset( p1, p2 );
BOOST_TEST( p3.get() == p2 );
BOOST_TEST( p3.local_use_count() == p1.local_use_count() );
BOOST_TEST( !p3.owner_before( p1 ) && !p1.owner_before( p3 ) );
}
template<class T, class U> void test_01_aliasing_reset_()
{
U u;
boost::local_shared_ptr<T> p1;
test_aliasing_reset_( p1, &u );
}
template<class T, class U> void test_01_aliasing_reset()
{
test_01_aliasing_reset_<T, U>();
test_01_aliasing_reset_<T const, U>();
test_01_aliasing_reset_<T volatile, U>();
test_01_aliasing_reset_<T const volatile, U>();
test_01_aliasing_reset_<T, U volatile>();
test_01_aliasing_reset_<T const, U volatile>();
test_01_aliasing_reset_<T volatile, U volatile>();
test_01_aliasing_reset_<T const volatile, U volatile>();
}
template<class T, class U> void test_10_aliasing_reset_()
{
boost::local_shared_ptr<T> p1( new T() );
test_aliasing_reset_( p1, static_cast<U*>(0) );
}
template<class T, class U> void test_10_aliasing_reset()
{
test_10_aliasing_reset_<T, U>();
test_10_aliasing_reset_<T const, U>();
test_10_aliasing_reset_<T volatile, U>();
test_10_aliasing_reset_<T const volatile, U>();
test_10_aliasing_reset_<T, U const>();
test_10_aliasing_reset_<T const, U const>();
test_10_aliasing_reset_<T volatile, U const>();
test_10_aliasing_reset_<T const volatile, U const>();
test_10_aliasing_reset_<T, U volatile>();
test_10_aliasing_reset_<T const, U volatile>();
test_10_aliasing_reset_<T volatile, U volatile>();
test_10_aliasing_reset_<T const volatile, U volatile>();
test_10_aliasing_reset_<T, U const volatile>();
test_10_aliasing_reset_<T const, U const volatile>();
test_10_aliasing_reset_<T volatile, U const volatile>();
test_10_aliasing_reset_<T const volatile, U const volatile>();
}
template<class T, class U> void test_11_aliasing_reset_()
{
U u;
boost::local_shared_ptr<T> p1( new T() );
test_aliasing_reset_( p1, &u );
}
template<class T, class U> void test_11_aliasing_reset()
{
test_11_aliasing_reset_<T, U>();
test_11_aliasing_reset_<T const, U>();
test_11_aliasing_reset_<T volatile, U>();
test_11_aliasing_reset_<T const volatile, U>();
test_11_aliasing_reset_<T, U volatile>();
test_11_aliasing_reset_<T const, U volatile>();
test_11_aliasing_reset_<T volatile, U volatile>();
test_11_aliasing_reset_<T const volatile, U volatile>();
}
static void aliasing_reset()
{
test_01_aliasing_reset<int, int>();
test_10_aliasing_reset<int, int>();
test_11_aliasing_reset<int, int>();
test_01_aliasing_reset<void, int>();
test_10_aliasing_reset<int, void>();
test_10_aliasing_reset<int, incomplete>();
test_01_aliasing_reset<X, X>();
BOOST_TEST( X::instances == 0 );
test_10_aliasing_reset<X, X>();
BOOST_TEST( X::instances == 0 );
test_11_aliasing_reset<X, X>();
BOOST_TEST( X::instances == 0 );
test_01_aliasing_reset<int, X>();
BOOST_TEST( X::instances == 0 );
test_10_aliasing_reset<int, X>();
BOOST_TEST( X::instances == 0 );
test_11_aliasing_reset<int, X>();
BOOST_TEST( X::instances == 0 );
test_01_aliasing_reset<X, int>();
BOOST_TEST( X::instances == 0 );
test_10_aliasing_reset<X, int>();
BOOST_TEST( X::instances == 0 );
test_11_aliasing_reset<X, int>();
BOOST_TEST( X::instances == 0 );
test_01_aliasing_reset<void, X>();
BOOST_TEST( X::instances == 0 );
test_10_aliasing_reset<X, void>();
BOOST_TEST( X::instances == 0 );
test_10_aliasing_reset<X, incomplete>();
BOOST_TEST( X::instances == 0 );
}
// element access
template<class T> static void empty_element_access_()
{
boost::local_shared_ptr<T> p1;
BOOST_TEST_EQ( p1.operator->(), static_cast<T*>(0) );
BOOST_TEST_EQ( p1.get(), static_cast<T*>(0) );
BOOST_TEST( p1? false: true );
BOOST_TEST( !p1 );
BOOST_TEST_EQ( p1.local_use_count(), 0 );
}
template<class T> static void empty_element_access()
{
empty_element_access_<T>();
empty_element_access_<T const>();
empty_element_access_<T volatile>();
empty_element_access_<T const volatile>();
}
template<class T> static void new_element_access_()
{
{
T * p0 = new T();
boost::local_shared_ptr<T> p1( p0 );
BOOST_TEST_EQ( p1.operator->(), p0 );
BOOST_TEST_EQ( p1.get(), p0 );
BOOST_TEST_EQ( &*p1, p0 );
BOOST_TEST( p1? true: false );
BOOST_TEST_NOT( !p1 );
BOOST_TEST_EQ( p1.local_use_count(), 1 );
}
{
T * p0 = new T[3]();
boost::local_shared_ptr<T[]> p1( p0 );
BOOST_TEST_EQ( p1.get(), p0 );
BOOST_TEST_EQ( &p1[0], &p0[0] );
BOOST_TEST_EQ( &p1[1], &p0[1] );
BOOST_TEST_EQ( &p1[2], &p0[2] );
BOOST_TEST( p1? true: false );
BOOST_TEST_NOT( !p1 );
BOOST_TEST_EQ( p1.local_use_count(), 1 );
}
{
T * p0 = new T[3]();
boost::local_shared_ptr<T[3]> p1( p0 );
BOOST_TEST_EQ( p1.get(), p0 );
BOOST_TEST_EQ( &p1[0], &p0[0] );
BOOST_TEST_EQ( &p1[1], &p0[1] );
BOOST_TEST_EQ( &p1[2], &p0[2] );
BOOST_TEST( p1? true: false );
BOOST_TEST_NOT( !p1 );
BOOST_TEST_EQ( p1.local_use_count(), 1 );
}
}
template<class T> static void new_element_access()
{
new_element_access_<T>();
new_element_access_<T const>();
new_element_access_<T volatile>();
new_element_access_<T const volatile>();
}
static void element_access()
{
empty_element_access<int>();
empty_element_access<X>();
BOOST_TEST( X::instances == 0 );
empty_element_access<incomplete>();
empty_element_access<void>();
new_element_access<int>();
new_element_access<X>();
BOOST_TEST( X::instances == 0 );
}
// shared_ptr conversion
template<class T, class U> static void empty_shared_ptr_conversion_()
{
boost::local_shared_ptr<T> p1;
boost::shared_ptr<U> p2( p1 );
BOOST_TEST_EQ( p2.get(), static_cast<U*>(0) );
BOOST_TEST_EQ( p2.use_count(), 0 );
}
template<class T> static void empty_shared_ptr_conversion()
{
empty_shared_ptr_conversion_<T, T>();
empty_shared_ptr_conversion_<T, T const>();
empty_shared_ptr_conversion_<T, T volatile>();
empty_shared_ptr_conversion_<T, T const volatile>();
empty_shared_ptr_conversion_<T const, T const>();
empty_shared_ptr_conversion_<T volatile, T volatile>();
empty_shared_ptr_conversion_<T const volatile, T const volatile>();
empty_shared_ptr_conversion_<T, void>();
empty_shared_ptr_conversion_<T, void const>();
empty_shared_ptr_conversion_<T, void volatile>();
empty_shared_ptr_conversion_<T, void const volatile>();
empty_shared_ptr_conversion_<T const, void const>();
empty_shared_ptr_conversion_<T volatile, void volatile>();
empty_shared_ptr_conversion_<T const volatile, void const volatile>();
}
template<class T, class U> static void new_shared_ptr_conversion_()
{
boost::local_shared_ptr<T> p1( new T() );
boost::shared_ptr<U> p2( p1 );
BOOST_TEST_EQ( p2.get(), p1.get() );
BOOST_TEST_EQ( p2.use_count(), 2 );
boost::shared_ptr<U> p3( p1 );
BOOST_TEST_EQ( p3.get(), p1.get() );
BOOST_TEST_EQ( p3.use_count(), 3 );
BOOST_TEST( !(p2 < p3) && !(p3 < p2) );
BOOST_TEST_EQ( p1.local_use_count(), 1 );
p1.reset();
BOOST_TEST_EQ( p2.use_count(), 2 );
BOOST_TEST_EQ( p3.use_count(), 2 );
}
template<class T> static void new_shared_ptr_conversion()
{
new_shared_ptr_conversion_<T, T>();
new_shared_ptr_conversion_<T, T const>();
new_shared_ptr_conversion_<T, T volatile>();
new_shared_ptr_conversion_<T, T const volatile>();
new_shared_ptr_conversion_<T const, T const>();
new_shared_ptr_conversion_<T volatile, T volatile>();
new_shared_ptr_conversion_<T const volatile, T const volatile>();
new_shared_ptr_conversion_<T, void>();
new_shared_ptr_conversion_<T, void const>();
new_shared_ptr_conversion_<T, void volatile>();
new_shared_ptr_conversion_<T, void const volatile>();
new_shared_ptr_conversion_<T const, void const>();
new_shared_ptr_conversion_<T volatile, void volatile>();
new_shared_ptr_conversion_<T const volatile, void const volatile>();
}
static void shared_ptr_conversion()
{
empty_shared_ptr_conversion<void>();
empty_shared_ptr_conversion<incomplete>();
empty_shared_ptr_conversion<int>();
empty_shared_ptr_conversion<X>();
BOOST_TEST( X::instances == 0 );
new_shared_ptr_conversion<int>();
new_shared_ptr_conversion<X>();
BOOST_TEST( X::instances == 0 );
}
// weak_ptr conversion
template<class T, class U> static void empty_weak_ptr_conversion_()
{
boost::local_shared_ptr<T> p1;
boost::weak_ptr<U> p2( p1 );
BOOST_TEST_EQ( p2.lock().get(), static_cast<U*>(0) );
BOOST_TEST_EQ( p2.use_count(), 0 );
}
template<class T> static void empty_weak_ptr_conversion()
{
empty_weak_ptr_conversion_<T, T>();
empty_weak_ptr_conversion_<T, T const>();
empty_weak_ptr_conversion_<T, T volatile>();
empty_weak_ptr_conversion_<T, T const volatile>();
empty_weak_ptr_conversion_<T const, T const>();
empty_weak_ptr_conversion_<T volatile, T volatile>();
empty_weak_ptr_conversion_<T const volatile, T const volatile>();
empty_weak_ptr_conversion_<T, void>();
empty_weak_ptr_conversion_<T, void const>();
empty_weak_ptr_conversion_<T, void volatile>();
empty_weak_ptr_conversion_<T, void const volatile>();
empty_weak_ptr_conversion_<T const, void const>();
empty_weak_ptr_conversion_<T volatile, void volatile>();
empty_weak_ptr_conversion_<T const volatile, void const volatile>();
}
template<class T, class U> static void new_weak_ptr_conversion_()
{
boost::local_shared_ptr<T> p1( new T() );
boost::weak_ptr<U> p2( p1 );
BOOST_TEST_EQ( p2.lock().get(), p1.get() );
BOOST_TEST_EQ( p2.use_count(), 1 );
boost::weak_ptr<U> p3( p1 );
BOOST_TEST_EQ( p3.lock().get(), p1.get() );
BOOST_TEST_EQ( p3.use_count(), 1 );
BOOST_TEST( !(p2 < p3) && !(p3 < p2) );
BOOST_TEST_EQ( p1.local_use_count(), 1 );
p1.reset();
BOOST_TEST_EQ( p2.use_count(), 0 );
BOOST_TEST_EQ( p3.use_count(), 0 );
}
template<class T> static void new_weak_ptr_conversion()
{
new_weak_ptr_conversion_<T, T>();
new_weak_ptr_conversion_<T, T const>();
new_weak_ptr_conversion_<T, T volatile>();
new_weak_ptr_conversion_<T, T const volatile>();
new_weak_ptr_conversion_<T const, T const>();
new_weak_ptr_conversion_<T volatile, T volatile>();
new_weak_ptr_conversion_<T const volatile, T const volatile>();
new_weak_ptr_conversion_<T, void>();
new_weak_ptr_conversion_<T, void const>();
new_weak_ptr_conversion_<T, void volatile>();
new_weak_ptr_conversion_<T, void const volatile>();
new_weak_ptr_conversion_<T const, void const>();
new_weak_ptr_conversion_<T volatile, void volatile>();
new_weak_ptr_conversion_<T const volatile, void const volatile>();
}
static void weak_ptr_conversion()
{
empty_weak_ptr_conversion<void>();
empty_weak_ptr_conversion<incomplete>();
empty_weak_ptr_conversion<int>();
empty_weak_ptr_conversion<X>();
BOOST_TEST( X::instances == 0 );
new_weak_ptr_conversion<int>();
new_weak_ptr_conversion<X>();
BOOST_TEST( X::instances == 0 );
}
// main
int main()
@ -1702,18 +2507,25 @@ int main()
nullptr_assignment();
shared_ptr_copy_assignment();
shared_ptr_move_assignment();
// unique_ptr_assignment();
unique_ptr_assignment();
default_reset();
// pointer_reset();
// deleter_reset();
// allocator_reset();
// aliasing_reset();
pointer_reset();
deleter_reset();
allocator_reset();
aliasing_reset();
// element_access();
element_access();
shared_ptr_conversion();
weak_ptr_conversion();
// swap_test();
// owner_before_test();
// equal_test();
// operator< ?
// casts
// get_pointer
// operator<<
// hash
return boost::report_errors();
}

View File

@ -0,0 +1,297 @@
// make_local_shared_esft_test.cpp
//
// Copyright 2007-2009, 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) || defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES )
int main()
{
}
#else
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/make_local_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
class X: public boost::enable_shared_from_this<X>
{
private:
X( X const & );
X & operator=( X const & );
public:
static int instances;
explicit X( int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0 )
{
++instances;
}
~X()
{
--instances;
}
};
int X::instances = 0;
int main()
{
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_local_shared< X >();
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_local_shared_noinit< X >();
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_local_shared< X >( 1 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2, 3 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2, 3, 4 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2, 3, 4, 5 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6, 7 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8, 9 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
return boost::report_errors();
}
#endif

View File

@ -0,0 +1,235 @@
// make_local_shared_test.cpp
//
// Copyright 2007-2009, 2017 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) || defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES )
int main()
{
}
#else
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/make_local_shared.hpp>
#include <boost/smart_ptr/local_shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <cstddef>
class X
{
private:
X( X const & );
X & operator=( X const & );
void * operator new( std::size_t n )
{
// lack of this definition causes link errors on Comeau C++
BOOST_ERROR( "private X::new called" );
return ::operator new( n );
}
void operator delete( void * p )
{
// lack of this definition causes link errors on MSVC
BOOST_ERROR( "private X::delete called" );
::operator delete( p );
}
public:
static int instances;
int v;
explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
{
++instances;
}
~X()
{
--instances;
}
};
int X::instances = 0;
int main()
{
{
boost::local_shared_ptr< int > pi = boost::make_local_shared< int >();
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( *pi == 0 );
}
{
boost::local_shared_ptr< int > pi = boost::make_local_shared_noinit< int >();
BOOST_TEST( pi.get() != 0 );
}
{
boost::local_shared_ptr< int > pi = boost::make_local_shared< int >( 5 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( *pi == 5 );
}
BOOST_TEST( X::instances == 0 );
{
boost::local_shared_ptr< X > pi = boost::make_local_shared< X >();
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 0 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::make_local_shared_noinit< X >();
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 0 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2, 3 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2, 3, 4 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2, 3, 4, 5 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6, 7 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr< X > pi = boost::make_local_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8, 9 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
return boost::report_errors();
}
#endif

View File

@ -61,6 +61,28 @@ int main()
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_shared_noinit< X >();
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_shared< X >( 1 );
BOOST_TEST( X::instances == 1 );

View File

@ -61,6 +61,12 @@ int main()
BOOST_TEST( *pi == 0 );
}
{
boost::shared_ptr< int > pi = boost::make_shared_noinit< int >();
BOOST_TEST( pi.get() != 0 );
}
{
boost::shared_ptr< int > pi = boost::make_shared< int >( 5 );
@ -83,6 +89,19 @@ int main()
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::make_shared_noinit< X >();
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 0 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::make_shared< X >( 1 );
boost::weak_ptr<X> wp( pi );