Merge branch 'develop'

This commit is contained in:
Peter Dimov
2014-02-11 01:29:29 +02:00
89 changed files with 6786 additions and 5192 deletions

View File

@@ -1,88 +1,88 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>Smart Pointer Changes</title> <title>Smart Pointer Changes</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> </head>
<body bgcolor="#ffffff" text="#000000"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86" <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
border="0"></A>Smart Pointer Changes</h1> width="277" align="middle" border="0">Smart Pointer Changes</h1>
<p>The February 2002 change to the Boost smart pointers introduced a number of <p>The February 2002 change to the Boost smart pointers introduced a number of
changes. Since the previous version of the smart pointers was in use for a long changes. Since the previous version of the smart pointers was in use for a long
time, it's useful to have a detailed list of what changed from a library user's time, it's useful to have a detailed list of what changed from a library user's
point of view.</p> point of view.</p>
<p>Note that for compilers that don't support member templates well enough, a <p>Note that for compilers that don't support member templates well enough, a
separate implementation is used that lacks many of the new features and is more separate implementation is used that lacks many of the new features and is more
like the old version.</p> like the old version.</p>
<h2>Features Requiring Code Changes to Take Advantage</h2> <h2>Features Requiring Code Changes to Take Advantage</h2>
<ul> <ul>
<li> <li>
The smart pointer class templates now each have their own header file. For The smart pointer class templates now each have their own header file. For
compatibility, the <a href="../../boost/smart_ptr.hpp">&lt;boost/smart_ptr.hpp&gt;</a> compatibility, the <a href="../../boost/smart_ptr.hpp">&lt;boost/smart_ptr.hpp&gt;</a>
header now includes the headers for the four classic smart pointer class header now includes the headers for the four classic smart pointer class
templates. templates.
<li> <li>
The <b>weak_ptr</b> The <b>weak_ptr</b>
template was added. template was added.
<li> <li>
The new <b>shared_ptr</b> and <b>shared_array</b> relax the requirement that The new <b>shared_ptr</b> and <b>shared_array</b> relax the requirement that
the pointed-to object's destructor must be visible when instantiating the <b>shared_ptr</b> the pointed-to object's destructor must be visible when instantiating the <b>shared_ptr</b>
destructor. This makes it easier to have shared_ptr members in classes without destructor. This makes it easier to have shared_ptr members in classes without
explicit destructors. explicit destructors.
<li> <li>
A custom deallocator can be passed in when creating a <b>shared_ptr</b> or <b>shared_array</b>. A custom deallocator can be passed in when creating a <b>shared_ptr</b> or <b>shared_array</b>.
<li> <li>
<b>shared_static_cast</b> and <b>shared_dynamic_cast</b> function templates are <b>shared_static_cast</b> and <b>shared_dynamic_cast</b> function templates are
provided which work for <b>shared_ptr</b> and <b>weak_ptr</b> as <b>static_cast</b> provided which work for <b>shared_ptr</b> and <b>weak_ptr</b> as <b>static_cast</b>
and <b>dynamic_cast</b> and <b>dynamic_cast</b>
do for pointers. do for pointers.
<li> <li>
The self-assignment misfeature has been removed from <b>shared_ptr::reset</b>, The self-assignment misfeature has been removed from <b>shared_ptr::reset</b>,
although it is still present in <b>scoped_ptr</b>, and in <b>std::auto_ptr</b>. although it is still present in <b>scoped_ptr</b>, and in <b>std::auto_ptr</b>.
Calling <b>reset</b> with a pointer to the object that's already owned by the <b>shared_ptr</b> Calling <b>reset</b> with a pointer to the object that's already owned by the <b>shared_ptr</b>
results in undefined behavior (an assertion, or eventually a double-delete if results in undefined behavior (an assertion, or eventually a double-delete if
assertions are off). assertions are off).
<li> <li>
The <b>BOOST_SMART_PTR_CONVERSION</b> The <b>BOOST_SMART_PTR_CONVERSION</b>
feature has been removed. feature has been removed.
<li> <li>
<b>shared_ptr&lt;void&gt;</b> is now allowed.</li> <b>shared_ptr&lt;void&gt;</b> is now allowed.</li>
</ul> </ul>
<h2>Features That Improve Robustness</h2> <h2>Features That Improve Robustness</h2>
<ul> <ul>
<li> <li>
The manipulation of use counts is now <a name="threadsafe">thread safe</a> on The manipulation of use counts is now <a name="threadsafe">thread safe</a> on
Windows, Linux, and platforms that support pthreads. See the <a href="../../boost/detail/atomic_count.hpp"> Windows, Linux, and platforms that support pthreads. See the <a href="../../boost/detail/atomic_count.hpp">
&lt;boost/detail/atomic_count.hpp&gt;</a> &lt;boost/detail/atomic_count.hpp&gt;</a>
file for details file for details
<li> <li>
The new shared_ptr will always delete the object using the pointer it was The new shared_ptr will always delete the object using the pointer it was
originally constructed with. This prevents subtle problems that could happen if originally constructed with. This prevents subtle problems that could happen if
the last <b>shared_ptr</b> was a pointer to a sub-object of a class that did the last <b>shared_ptr</b> was a pointer to a sub-object of a class that did
not have a virtual destructor.</li> not have a virtual destructor.</li>
</ul> </ul>
<h2>Implementation Details</h2> <h2>Implementation Details</h2>
<ul> <ul>
<li> <li>
Some bugs in the assignment operator implementations and in <b>reset</b> Some bugs in the assignment operator implementations and in <b>reset</b>
have been fixed by using the "copy and swap" idiom. have been fixed by using the "copy and swap" idiom.
<li> <li>
Assertions have been added to check preconditions of various functions; Assertions have been added to check preconditions of various functions;
however, since these use the new <a href="../../boost/assert.hpp">&lt;boost/assert.hpp&gt;</a> however, since these use the new <a href="../../boost/assert.hpp">&lt;boost/assert.hpp&gt;</a>
header, the assertions are disabled by default. header, the assertions are disabled by default.
<li> <li>
The partial specialization of <b>std::less</b> has been replaced by <b>operator&lt;</b> The partial specialization of <b>std::less</b> has been replaced by <b>operator&lt;</b>
overloads which accomplish the same thing without relying on undefined overloads which accomplish the same thing without relying on undefined
behavior. behavior.
<li> <li>
The incorrect overload of <b>std::swap</b> has been replaced by <b>boost::swap</b>, The incorrect overload of <b>std::swap</b> has been replaced by <b>boost::swap</b>,
which has many of the same advantages for generic programming but does not which has many of the same advantages for generic programming but does not
violate the C++ standard.</li> violate the C++ standard.</li>
</ul> </ul>
<hr> <hr>
<p>Revised 1 February 2002</p> <p>$Date$</p>
<p><small>Copyright 2002 Darin Adler. Distributed under the Boost Software License, Version <p><small>Copyright 2002 Darin Adler. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p> copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body> </body>
</html> </html>

View File

@@ -1,34 +1,24 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>Boost: enable_shared_from_this.hpp documentation</title> <title>enable_shared_from_this</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> </head>
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<table border="0" width="100%"> <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
<tr> width="277" align="middle" border="0">enable_shared_from_this</h1>
<td width="277"><A href="../../index.htm"> <img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86" border="0"></A> <h2><a name="Purpose">Purpose</a></h2>
</td> <p>
<td align="center"> The header <STRONG>&lt;boost/enable_shared_from_this.hpp&gt;</STRONG> defines
<h1>enable_shared_from_this.hpp</h1> the class template <STRONG>enable_shared_from_this</STRONG>. It is used as a
</td> base class that allows a <A href="shared_ptr.htm">shared_ptr</A> to the current
</tr> object to be obtained from within a member function.
<tr> </p>
<td colspan="2" height="64">&nbsp;</td> <P><STRONG>enable_shared_from_this&lt;T&gt;</STRONG> defines two member functions
</tr> called <STRONG>shared_from_this</STRONG> that return a <STRONG>shared_ptr&lt;T&gt;</STRONG>
</table> and <STRONG>shared_ptr&lt;T const&gt;</STRONG>, depending on constness, to <STRONG>this</STRONG>.</P>
<h3><a name="Purpose">Purpose</a></h3> <h2><a name="Example">Example</a></h2>
<p> <pre>
The header <STRONG>&lt;boost/enable_shared_from_this.hpp&gt;</STRONG> defines
the class template <STRONG>enable_shared_from_this</STRONG>. It is used as a
base class that allows a <A href="shared_ptr.htm">shared_ptr</A> to the current
object to be obtained from within a member function.
</p>
<P><STRONG>enable_shared_from_this&lt;T&gt;</STRONG> defines two member functions
called <STRONG>shared_from_this</STRONG> that return a <STRONG>shared_ptr&lt;T&gt;</STRONG>
and <STRONG>shared_ptr&lt;T const&gt;</STRONG>, depending on constness, to <STRONG>this</STRONG>.</P>
<h3><a name="Example">Example</a></h3>
<pre>
#include &lt;boost/enable_shared_from_this.hpp&gt; #include &lt;boost/enable_shared_from_this.hpp&gt;
#include &lt;boost/shared_ptr.hpp&gt; #include &lt;boost/shared_ptr.hpp&gt;
#include &lt;cassert&gt; #include &lt;cassert&gt;
@@ -51,8 +41,8 @@ int main()
assert(!(p &lt; q || q &lt; p)); // p and q must share ownership assert(!(p &lt; q || q &lt; p)); // p and q must share ownership
} }
</pre> </pre>
<h3><a name="Synopsis">Synopsis</a></h3> <h3><a name="Synopsis">Synopsis</a></h3>
<pre> <pre>
namespace boost namespace boost
{ {
@@ -66,30 +56,30 @@ public:
} }
</pre> </pre>
<h4>template&lt;class T&gt; shared_ptr&lt;T&gt; <h4>template&lt;class T&gt; shared_ptr&lt;T&gt;
enable_shared_from_this&lt;T&gt;::shared_from_this();</h4> enable_shared_from_this&lt;T&gt;::shared_from_this();</h4>
<h4>template&lt;class T&gt; shared_ptr&lt;T const&gt; <h4>template&lt;class T&gt; shared_ptr&lt;T const&gt;
enable_shared_from_this&lt;T&gt;::shared_from_this() const;</h4> enable_shared_from_this&lt;T&gt;::shared_from_this() const;</h4>
<blockquote> <blockquote>
<p> <p>
<b>Requires:</b> <STRONG>enable_shared_from_this&lt;T&gt;</STRONG> must be an <b>Requires:</b> <STRONG>enable_shared_from_this&lt;T&gt;</STRONG> must be an
accessible base class of <b>T</b>. <STRONG>*this</STRONG> must be a subobject accessible base class of <b>T</b>. <STRONG>*this</STRONG> must be a subobject
of an instance <STRONG>t</STRONG> of type <STRONG>T</STRONG> . There must exist of an instance <STRONG>t</STRONG> of type <STRONG>T</STRONG> . There must exist
at least one <STRONG>shared_ptr</STRONG> instance <STRONG>p</STRONG> that <EM>owns</EM> at least one <STRONG>shared_ptr</STRONG> instance <STRONG>p</STRONG> that <EM>owns</EM>
<STRONG>t</STRONG>. <STRONG>t</STRONG>.
</p> </p>
<p> <p>
<b>Returns:</b> A <b>shared_ptr&lt;T&gt;</b> instance <b>r</b> that shares <b>Returns:</b> A <b>shared_ptr&lt;T&gt;</b> instance <b>r</b> that shares
ownership with <b>p</b>. ownership with <b>p</b>.
</p> </p>
<p> <p>
<b>Postconditions:</b> <tt>r.get() == this</tt>. <b>Postconditions:</b> <tt>r.get() == this</tt>.
</p> </p>
</blockquote> </blockquote>
<p> <p>$Date$</p>
<br> <p>
<small>Copyright <EFBFBD> 2002, 2003 by Peter Dimov. Distributed under the Boost Software License, Version <small>Copyright &copy; 2002, 2003 by Peter Dimov. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p> copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,14 @@
/*
* Copyright (c) 2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_MAKE_UNIQUE_HPP_INCLUDED
#define BOOST_MAKE_UNIQUE_HPP_INCLUDED
#include <boost/smart_ptr/make_unique.hpp>
#endif

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Glen Joseph Fernandes * Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com * glenfe at live dot com
* *
* Distributed under the Boost Software License, * Distributed under the Boost Software License,
@@ -9,14 +9,10 @@
#ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP #ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
#define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP #define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
#include <boost/smart_ptr/shared_ptr.hpp> #include <boost/smart_ptr/detail/array_allocator.hpp>
#include <boost/smart_ptr/detail/allocate_array_helper.hpp>
#include <boost/smart_ptr/detail/array_deleter.hpp> #include <boost/smart_ptr/detail/array_deleter.hpp>
#include <boost/smart_ptr/detail/array_traits.hpp>
#include <boost/smart_ptr/detail/sp_if_array.hpp> #include <boost/smart_ptr/detail/sp_if_array.hpp>
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include <boost/type_traits/remove_cv.hpp>
#include <initializer_list>
#endif
namespace boost { namespace boost {
template<typename T, typename A> template<typename T, typename A>
@@ -24,225 +20,140 @@ namespace boost {
allocate_shared(const A& allocator, std::size_t size) { allocate_shared(const A& allocator, std::size_t size) {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
typedef boost::detail::as_allocator<T3[], A> A1;
typedef boost::detail::as_deleter<T3[], A> D1;
T1* p1 = 0; T1* p1 = 0;
T2* p2 = 0; T3* p2 = 0;
std::size_t n1 = size * boost::detail::array_total<T1>::size; std::size_t n1 = size * boost::detail::array_total<T1>::size;
boost::detail::allocate_array_helper<A, T2[]> a1(allocator, n1, &p2); D1 d1(allocator, n1);
boost::detail::array_deleter<T2[]> d1(n1); A1 a1(allocator, n1, &p2);
boost::shared_ptr<T> s1(p1, d1, a1); boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[]>* D2;
p1 = reinterpret_cast<T1*>(p2); p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter()); boost::detail::as_init(allocator, p2, n1);
d2->init(p2); D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1); return boost::shared_ptr<T>(s1, p1);
} }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<typename T, typename A, typename... Args>
inline typename boost::detail::sp_if_array<T>::type
allocate_shared(const A& allocator, std::size_t size, Args&&... args) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
T1* p1 = 0;
T2* p2 = 0;
std::size_t n1 = size * boost::detail::array_total<T1>::size;
boost::detail::allocate_array_helper<A, T2[]> a1(allocator, n1, &p2);
boost::detail::array_deleter<T2[]> d1(n1);
boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[]>* D2;
p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
d2->init(p2, boost::detail::sp_forward<Args>(args)...);
return boost::shared_ptr<T>(s1, p1);
}
template<typename T, typename A, typename... Args>
inline typename boost::detail::sp_if_size_array<T>::type
allocate_shared(const A& allocator, Args&&... args) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
enum {
N = boost::detail::array_total<T>::size
};
T1* p1 = 0;
T2* p2 = 0;
boost::detail::allocate_array_helper<A, T2[N]> a1(allocator, &p2);
boost::detail::array_deleter<T2[N]> d1;
boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[N]>* D2;
p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
d2->init(p2, boost::detail::sp_forward<Args>(args)...);
return boost::shared_ptr<T>(s1, p1);
}
#endif
#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
template<typename T, typename A> template<typename T, typename A>
inline typename boost::detail::sp_if_size_array<T>::type inline typename boost::detail::sp_if_size_array<T>::type
allocate_shared(const A& allocator, const T& list) { allocate_shared(const A& allocator) {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef const T2 T3; typedef typename boost::remove_cv<T2>::type T3;
enum { enum {
N = boost::detail::array_total<T>::size N = boost::detail::array_total<T>::size
}; };
typedef boost::detail::as_allocator<T3[N], A> A1;
typedef boost::detail::as_deleter<T3[N], A> D1;
T1* p1 = 0; T1* p1 = 0;
T2* p2 = 0; T3* p2 = 0;
T3* p3 = 0; D1 d1(allocator);
boost::detail::allocate_array_helper<A, T2[N]> a1(allocator, &p2); A1 a1(allocator, &p2);
boost::detail::array_deleter<T2[N]> d1;
boost::shared_ptr<T> s1(p1, d1, a1); boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[N]>* D2;
p3 = reinterpret_cast<T3*>(list);
p1 = reinterpret_cast<T1*>(p2); p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter()); boost::detail::as_init(allocator, p2, N);
d2->init_list(p2, p3); D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1); return boost::shared_ptr<T>(s1, p1);
} }
template<typename T, typename A> template<typename T, typename A>
inline typename boost::detail::sp_if_array<T>::type inline typename boost::detail::sp_if_array<T>::type
allocate_shared(const A& allocator, std::size_t size, allocate_shared(const A& allocator, std::size_t size,
const typename boost::detail::array_inner<T>::type& list) { const typename boost::detail::array_inner<T>::type& value) {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef const T2 T3; typedef typename boost::remove_cv<T2>::type T3;
typedef const T2 T4;
typedef boost::detail::as_allocator<T3[], A> A1;
typedef boost::detail::as_deleter<T3[], A> D1;
enum { enum {
M = boost::detail::array_total<T1>::size M = boost::detail::array_total<T1>::size
}; };
T1* p1 = 0; T1* p1 = 0;
T2* p2 = 0; T3* p2 = 0;
T3* p3 = 0; T4* p3 = reinterpret_cast<T4*>(&value);
std::size_t n1 = M * size; std::size_t n1 = M * size;
boost::detail::allocate_array_helper<A, T2[]> a1(allocator, n1, &p2); D1 d1(allocator, n1);
boost::detail::array_deleter<T2[]> d1(n1); A1 a1(allocator, n1, &p2);
boost::shared_ptr<T> s1(p1, d1, a1); boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[]>* D2;
p3 = reinterpret_cast<T3*>(list);
p1 = reinterpret_cast<T1*>(p2); p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter()); boost::detail::as_init<T3, A, M>(allocator, p2, n1, p3);
d2->template init_list<M>(p2, p3); D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1); return boost::shared_ptr<T>(s1, p1);
} }
template<typename T, typename A> template<typename T, typename A>
inline typename boost::detail::sp_if_size_array<T>::type inline typename boost::detail::sp_if_size_array<T>::type
allocate_shared(const A& allocator, allocate_shared(const A& allocator,
const typename boost::detail::array_inner<T>::type& list) { const typename boost::detail::array_inner<T>::type& value) {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef const T2 T3; typedef typename boost::remove_cv<T2>::type T3;
typedef const T2 T4;
enum { enum {
M = boost::detail::array_total<T1>::size, M = boost::detail::array_total<T1>::size,
N = boost::detail::array_total<T>::size N = boost::detail::array_total<T>::size
}; };
typedef boost::detail::as_allocator<T3[N], A> A1;
typedef boost::detail::as_deleter<T3[N], A> D1;
T1* p1 = 0; T1* p1 = 0;
T2* p2 = 0; T3* p2 = 0;
T3* p3 = 0; T4* p3 = reinterpret_cast<T4*>(&value);
boost::detail::allocate_array_helper<A, T2[N]> a1(allocator, &p2); D1 d1(allocator);
boost::detail::array_deleter<T2[N]> d1; A1 a1(allocator, &p2);
boost::shared_ptr<T> s1(p1, d1, a1); boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[N]>* D2;
p3 = reinterpret_cast<T3*>(list);
p1 = reinterpret_cast<T1*>(p2); p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter()); boost::detail::as_init<T3, A, M>(allocator, p2, N, p3);
d2->template init_list<M>(p2, p3); D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1); return boost::shared_ptr<T>(s1, p1);
} }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template<typename T, typename A>
inline typename boost::detail::sp_if_array<T>::type
allocate_shared(const A& allocator,
std::initializer_list<typename boost::detail::array_inner<T>::type> list) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef const T2 T3;
T1* p1 = 0;
T2* p2 = 0;
T3* p3 = 0;
std::size_t n1 = list.size() * boost::detail::array_total<T1>::size;
boost::detail::allocate_array_helper<A, T2[]> a1(allocator, n1, &p2);
boost::detail::array_deleter<T2[]> d1(n1);
boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[]>* D2;
p3 = reinterpret_cast<T3*>(list.begin());
p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
d2->init_list(p2, p3);
return boost::shared_ptr<T>(s1, p1);
}
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<typename T, typename A>
inline typename boost::detail::sp_if_array<T>::type
allocate_shared(const A& allocator, std::size_t size,
typename boost::detail::array_base<T>::type&& value) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
T1* p1 = 0;
T2* p2 = 0;
std::size_t n1 = size * boost::detail::array_total<T1>::size;
boost::detail::allocate_array_helper<A, T2[]> a1(allocator, n1, &p2);
boost::detail::array_deleter<T2[]> d1(n1);
boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[]>* D2;
p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
d2->init(p2, boost::detail::sp_forward<T2>(value));
return boost::shared_ptr<T>(s1, p1);
}
template<typename T, typename A>
inline typename boost::detail::sp_if_size_array<T>::type
allocate_shared(const A& allocator,
typename boost::detail::array_base<T>::type&& value) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
enum {
N = boost::detail::array_total<T>::size
};
T1* p1 = 0;
T2* p2 = 0;
boost::detail::allocate_array_helper<A, T2[N]> a1(allocator, &p2);
boost::detail::array_deleter<T2[N]> d1;
boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[N]>* D2;
p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
d2->init(p2, boost::detail::sp_forward<T2>(value));
return boost::shared_ptr<T>(s1, p1);
}
#endif
#endif
template<typename T, typename A> template<typename T, typename A>
inline typename boost::detail::sp_if_array<T>::type inline typename boost::detail::sp_if_array<T>::type
allocate_shared_noinit(const A& allocator, std::size_t size) { allocate_shared_noinit(const A& allocator, std::size_t size) {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
typedef boost::detail::as_allocator<T3[], A> A1;
typedef boost::detail::ms_deleter<T3[]> D1;
T1* p1 = 0; T1* p1 = 0;
T2* p2 = 0; T3* p2 = 0;
std::size_t n1 = size * boost::detail::array_total<T1>::size; std::size_t n1 = size * boost::detail::array_total<T1>::size;
boost::detail::allocate_array_helper<A, T2[]> a1(allocator, n1, &p2); D1 d1(n1);
boost::detail::array_deleter<T2[]> d1(n1); A1 a1(allocator, n1, &p2);
boost::shared_ptr<T> s1(p1, d1, a1); boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[]>* D2;
p1 = reinterpret_cast<T1*>(p2); p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter()); boost::detail::ms_noinit(p2, n1);
d2->noinit(p2); D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1); return boost::shared_ptr<T>(s1, p1);
} }
template<typename T, typename A> template<typename T, typename A>
inline typename boost::detail::sp_if_size_array<T>::type inline typename boost::detail::sp_if_size_array<T>::type
allocate_shared_noinit(const A& allocator) { allocate_shared_noinit(const A& allocator) {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
enum { enum {
N = boost::detail::array_total<T>::size N = boost::detail::array_total<T>::size
}; };
typedef boost::detail::as_allocator<T3[N], A> A1;
typedef boost::detail::ms_deleter<T3[N]> D1;
T1* p1 = 0; T1* p1 = 0;
T2* p2 = 0; T3* p2 = 0;
boost::detail::allocate_array_helper<A, T2[N]> a1(allocator, &p2); D1 d1;
boost::detail::array_deleter<T2[N]> d1; A1 a1(allocator, &p2);
boost::shared_ptr<T> s1(p1, d1, a1); boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[N]>* D2;
p1 = reinterpret_cast<T1*>(p2); p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter()); boost::detail::ms_noinit(p2, N);
d2->noinit(p2); D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1); return boost::shared_ptr<T>(s1, p1);
} }
} }

View File

@@ -1,169 +0,0 @@
/*
* Copyright (c) 2012 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP
#define BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP
#include <boost/type_traits/alignment_of.hpp>
namespace boost {
namespace detail {
template<typename A, typename T, typename Y = char>
class allocate_array_helper;
template<typename A, typename T, typename Y>
class allocate_array_helper<A, T[], Y> {
template<typename A9, typename T9, typename Y9>
friend class allocate_array_helper;
typedef typename A::template rebind<Y> ::other A2;
typedef typename A::template rebind<char>::other A3;
public:
typedef typename A2::value_type value_type;
typedef typename A2::pointer pointer;
typedef typename A2::const_pointer const_pointer;
typedef typename A2::reference reference;
typedef typename A2::const_reference const_reference;
typedef typename A2::size_type size_type;
typedef typename A2::difference_type difference_type;
template<typename U>
struct rebind {
typedef allocate_array_helper<A, T[], U> other;
};
allocate_array_helper(const A& allocator_, std::size_t size_, T** data_)
: allocator(allocator_),
size(sizeof(T) * size_),
data(data_) {
}
template<class U>
allocate_array_helper(const allocate_array_helper<A, T[], U>& other)
: allocator(other.allocator),
size(other.size),
data(other.data) {
}
pointer address(reference value) const {
return allocator.address(value);
}
const_pointer address(const_reference value) const {
return allocator.address(value);
}
size_type max_size() const {
return allocator.max_size();
}
pointer allocate(size_type count, const void* value = 0) {
std::size_t a1 = boost::alignment_of<T>::value;
std::size_t n1 = count * sizeof(Y) + a1 - 1;
char* p1 = A3(allocator).allocate(n1 + size, value);
char* p2 = p1 + n1;
while (std::size_t(p2) % a1 != 0) {
p2--;
}
*data = reinterpret_cast<T*>(p2);
return reinterpret_cast<Y*>(p1);
}
void deallocate(pointer memory, size_type count) {
std::size_t a1 = boost::alignment_of<T>::value;
std::size_t n1 = count * sizeof(Y) + a1 - 1;
char* p1 = reinterpret_cast<char*>(memory);
A3(allocator).deallocate(p1, n1 + size);
}
void construct(pointer memory, const Y& value) {
allocator.construct(memory, value);
}
void destroy(pointer memory) {
allocator.destroy(memory);
}
template<typename U>
bool operator==(const allocate_array_helper<A, T[], U>& other) const {
return allocator == other.allocator;
}
template<typename U>
bool operator!=(const allocate_array_helper<A, T[], U>& other) const {
return !(*this == other);
}
private:
A2 allocator;
std::size_t size;
T** data;
};
template<typename A, typename T, std::size_t N, typename Y>
class allocate_array_helper<A, T[N], Y> {
template<typename A9, typename T9, typename Y9>
friend class allocate_array_helper;
typedef typename A::template rebind<Y> ::other A2;
typedef typename A::template rebind<char>::other A3;
public:
typedef typename A2::value_type value_type;
typedef typename A2::pointer pointer;
typedef typename A2::const_pointer const_pointer;
typedef typename A2::reference reference;
typedef typename A2::const_reference const_reference;
typedef typename A2::size_type size_type;
typedef typename A2::difference_type difference_type;
template<typename U>
struct rebind {
typedef allocate_array_helper<A, T[N], U> other;
};
allocate_array_helper(const A& allocator_, T** data_)
: allocator(allocator_),
data(data_) {
}
template<class U>
allocate_array_helper(const allocate_array_helper<A, T[N], U>& other)
: allocator(other.allocator),
data(other.data) {
}
pointer address(reference value) const {
return allocator.address(value);
}
const_pointer address(const_reference value) const {
return allocator.address(value);
}
size_type max_size() const {
return allocator.max_size();
}
pointer allocate(size_type count, const void* value = 0) {
std::size_t a1 = boost::alignment_of<T>::value;
std::size_t n1 = count * sizeof(Y) + a1 - 1;
char* p1 = A3(allocator).allocate(n1 + N1, value);
char* p2 = p1 + n1;
while (std::size_t(p2) % a1 != 0) {
p2--;
}
*data = reinterpret_cast<T*>(p2);
return reinterpret_cast<Y*>(p1);
}
void deallocate(pointer memory, size_type count) {
std::size_t a1 = boost::alignment_of<T>::value;
std::size_t n1 = count * sizeof(Y) + a1 - 1;
char* p1 = reinterpret_cast<char*>(memory);
A3(allocator).deallocate(p1, n1 + N1);
}
void construct(pointer memory, const Y& value) {
allocator.construct(memory, value);
}
void destroy(pointer memory) {
allocator.destroy(memory);
}
template<typename U>
bool operator==(const allocate_array_helper<A, T[N], U>& other) const {
return allocator == other.allocator;
}
template<typename U>
bool operator!=(const allocate_array_helper<A, T[N], U>& other) const {
return !(*this == other);
}
private:
enum {
N1 = N * sizeof(T)
};
A2 allocator;
T** data;
};
}
}
#endif

View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_DETAIL_ALLOCATOR_PAIR_HPP
#define BOOST_SMART_PTR_DETAIL_ALLOCATOR_PAIR_HPP
#include <cstddef>
namespace boost {
namespace detail {
template<typename A, typename T>
struct as_pair
: A {
as_pair(const A& allocator, const T& value)
: A(allocator),
data(value) {
}
T data;
};
}
}
#endif

View File

@@ -0,0 +1,293 @@
/*
* Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP
#define BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP
#include <boost/smart_ptr/detail/allocator_pair.hpp>
#include <boost/smart_ptr/detail/array_traits.hpp>
#include <boost/type_traits/alignment_of.hpp>
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
#include <memory>
#endif
namespace boost {
namespace detail {
template<typename T>
struct ms_allocator_base;
template<typename T>
struct ms_allocator_base<T[]> {
ms_allocator_base(std::size_t size_)
: size(size_ * sizeof(T)) {
}
std::size_t size;
};
template<typename T, std::size_t N>
struct ms_allocator_base<T[N]> {
enum {
size = N * sizeof(T)
};
};
template<typename T, typename A, typename Y = char>
class as_allocator
: ms_allocator_base<T> {
using ms_allocator_base<T>::size;
template<typename T_, typename A_, typename Y_>
friend class as_allocator;
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef typename std::allocator_traits<A>::
template rebind_alloc<Y> YA;
typedef typename std::allocator_traits<A>::
template rebind_alloc<char> CA;
typedef typename std::allocator_traits<A>::
template rebind_traits<Y> YT;
typedef typename std::allocator_traits<A>::
template rebind_traits<char> CT;
#else
typedef typename A::template rebind<Y>::other YA;
typedef typename A::template rebind<char>::other CA;
#endif
public:
typedef typename array_inner<T>::type type;
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef typename YT::value_type value_type;
typedef typename YT::pointer pointer;
typedef typename YT::const_pointer const_pointer;
typedef typename YT::size_type size_type;
typedef typename YT::difference_type difference_type;
typedef Y& reference;
typedef const Y& const_reference;
#else
typedef typename YA::value_type value_type;
typedef typename YA::pointer pointer;
typedef typename YA::const_pointer const_pointer;
typedef typename YA::size_type size_type;
typedef typename YA::difference_type difference_type;
typedef typename YA::reference reference;
typedef typename YA::const_reference const_reference;
#endif
template<typename U>
struct rebind {
typedef as_allocator<T, A, U> other;
};
as_allocator(const A& allocator, type** data)
: pair(allocator, data) {
}
as_allocator(const A& allocator, std::size_t size_, type** data)
: ms_allocator_base<T>(size_),
pair(allocator, data) {
}
template<class U>
as_allocator(const as_allocator<T, A, U>& other)
: ms_allocator_base<T>(other),
pair(other.pair, other.pair.data) {
}
pointer address(reference value) const {
return pair.address(value);
}
const_pointer address(const_reference value) const {
return pair.address(value);
}
size_type max_size() const {
return pair.max_size();
}
pointer allocate(size_type count, const void* value = 0) {
std::size_t a1 = boost::alignment_of<type>::value;
std::size_t n1 = count * sizeof(value_type) + a1 - 1;
CA ca(pair);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
char* p1 = CT::allocate(ca, size + n1, value);
#else
char* p1 = ca.allocate(size + n1, value);
#endif
char* p2 = p1 + n1;
while (std::size_t(p2) % a1 != 0) {
p2--;
}
*pair.data = reinterpret_cast<type*>(p2);
return reinterpret_cast<value_type*>(p1);
}
void deallocate(pointer memory, size_type count) {
std::size_t a1 = boost::alignment_of<type>::value;
std::size_t n1 = count * sizeof(value_type) + a1 - 1;
char* p1 = reinterpret_cast<char*>(memory);
CA ca(pair);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
CT::deallocate(ca, p1, size + n1);
#else
ca.deallocate(p1, size + n1);
#endif
}
template<typename U>
void construct(U* memory, const_reference value) {
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
YT::construct(pair, memory, value);
#else
pair.construct(memory, value);
#endif
}
template<typename U>
void destroy(U* memory) {
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
YT::destroy(pair, memory);
#else
pair.destroy(memory);
#endif
}
#if !defined(BOOST_NO_CXX11_ALLOCATOR) && \
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<typename U, typename... Args>
void construct(U* memory, Args&&... args) {
YT::construct(pair, memory, std::forward<Args>(args)...);
}
#endif
template<typename U>
bool operator==(const as_allocator<T, A, U>& other) const {
return pair == other.pair;
}
template<typename U>
bool operator!=(const as_allocator<T, A, U>& other) const {
return !(*this == other);
}
private:
as_pair<YA, type**> pair;
};
template<typename T, typename Y = char>
class ms_allocator
: ms_allocator_base<T> {
using ms_allocator_base<T>::size;
template<typename T_, typename Y_>
friend class ms_allocator;
public:
typedef typename array_inner<T>::type type;
typedef Y value_type;
typedef Y* pointer;
typedef const Y* const_pointer;
typedef std::size_t size_type;
typedef ptrdiff_t difference_type;
typedef Y& reference;
typedef const Y& const_reference;
template<typename U>
struct rebind {
typedef ms_allocator<T, U> other;
};
ms_allocator(type** data_)
: data(data_) {
}
ms_allocator(std::size_t size_, type** data_)
: ms_allocator_base<T>(size_),
data(data_) {
}
template<class U>
ms_allocator(const ms_allocator<T, U>& other)
: ms_allocator_base<T>(other),
data(other.data) {
}
pointer address(reference value) const {
return &value;
}
const_pointer address(const_reference value) const {
return &value;
}
size_type max_size() const {
enum {
N = static_cast<std::size_t>(-1) / sizeof(value_type)
};
return N;
}
pointer allocate(size_type count, const void* = 0) {
std::size_t a1 = boost::alignment_of<type>::value;
std::size_t n1 = count * sizeof(value_type) + a1 - 1;
void* p1 = ::operator new(n1 + size);
char* p2 = static_cast<char*>(p1) + n1;
while (std::size_t(p2) % a1 != 0) {
p2--;
}
*data = reinterpret_cast<type*>(p2);
return reinterpret_cast<value_type*>(p1);
}
void deallocate(pointer memory, size_type) {
void* p1 = memory;
::operator delete(p1);
}
template<typename U>
void construct(U* memory, const_reference value) {
void* p1 = memory;
::new(p1) U(value);
}
template<typename U>
void destroy(U* memory) {
memory->~U();
}
#if !defined(BOOST_NO_CXX11_ALLOCATOR) && \
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<typename U, typename... Args>
void construct(U* memory, Args&&... args) {
void* p1 = memory;
::new(p1) U(std::forward<Args>(args)...);
}
#endif
template<typename U>
bool operator==(const ms_allocator<T, U>&) const {
return true;
}
template<typename U>
bool operator!=(const ms_allocator<T, U>& other) const {
return !(*this == other);
}
private:
type** data;
};
}
}
#endif

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Glen Joseph Fernandes * Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com * glenfe at live dot com
* *
* Distributed under the Boost Software License, * Distributed under the Boost Software License,
@@ -9,114 +9,99 @@
#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP
#define BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP #define BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP
#include <boost/smart_ptr/detail/allocator_pair.hpp>
#include <boost/smart_ptr/detail/array_traits.hpp>
#include <boost/smart_ptr/detail/array_utility.hpp> #include <boost/smart_ptr/detail/array_utility.hpp>
#include <boost/smart_ptr/detail/sp_forward.hpp>
namespace boost { namespace boost {
namespace detail { namespace detail {
template<typename T> template<typename T>
class array_deleter; struct ms_deleter_base;
template<typename T> template<typename T>
class array_deleter<T[]> { struct ms_deleter_base<T[]> {
public: ms_deleter_base(std::size_t size_)
array_deleter(std::size_t size_) : size(size_) {
: size(size_),
object(0) {
} }
~array_deleter() {
if (object) {
array_destroy(object, size);
}
}
void init(T* memory) {
array_init(memory, size);
object = memory;
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
void init(T* memory, T&& value) {
array_init_value(memory, size, sp_forward<T>(value));
object = memory;
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<typename... Args>
void init(T* memory, Args&&... args) {
array_init_args(memory, size, sp_forward<Args>(args)...);
object = memory;
}
#endif
#endif
void init_list(T* memory, const T* list) {
array_init_list(memory, size, list);
object = memory;
}
template<std::size_t M>
void init_list(T* memory, const T* list) {
array_init_list<T, M>(memory, size, list);
object = memory;
}
void noinit(T* memory) {
array_noinit(memory, size);
object = memory;
}
void operator()(const void*) {
if (object) {
array_destroy(object, size);
object = 0;
}
}
private:
std::size_t size; std::size_t size;
T* object;
}; };
template<typename T, std::size_t N> template<typename T, std::size_t N>
class array_deleter<T[N]> { struct ms_deleter_base<T[N]> {
enum {
size = N
};
};
template<typename T, typename A>
class as_deleter
: ms_deleter_base<T> {
using ms_deleter_base<T>::size;
public: public:
array_deleter() typedef typename array_inner<T>::type type;
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef typename std::allocator_traits<A>::
template rebind_alloc<type> allocator;
#else
typedef typename A::
template rebind<type>::other allocator;
#endif
as_deleter(const A& allocator_)
: pair(allocator_, 0) {
}
as_deleter(const A& allocator_, std::size_t size_)
: ms_deleter_base<T>(size_),
pair(allocator_, 0) {
}
void set(type* memory) {
pair.data = memory;
}
void operator()(const void*) {
if (pair.data) {
as_destroy<type, allocator>(pair, pair.data, size);
}
}
private:
as_pair<allocator, type*> pair;
};
template<typename T>
class ms_deleter
: ms_deleter_base<T> {
using ms_deleter_base<T>::size;
public:
typedef typename array_inner<T>::type type;
ms_deleter()
: object(0) { : object(0) {
} }
~array_deleter() {
if (object) { ms_deleter(std::size_t size_)
array_destroy(object, N); : ms_deleter_base<T>(size_),
} object(0) {
} }
void init(T* memory) {
array_init(memory, N); void set(type* memory) {
object = memory;
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
void init(T* memory, T&& value) {
array_init_value(memory, N, sp_forward<T>(value));
object = memory;
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<typename... Args>
void init(T* memory, Args&&... args) {
array_init_args(memory, N, sp_forward<Args>(args)...);
object = memory;
}
#endif
#endif
void init_list(T* memory, const T* list) {
array_init_list(memory, N, list);
object = memory;
}
template<std::size_t M>
void init_list(T* memory, const T* list) {
array_init_list<T, M>(memory, N, list);
object = memory;
}
void noinit(T* memory) {
array_noinit(memory, N);
object = memory; object = memory;
} }
void operator()(const void*) { void operator()(const void*) {
if (object) { if (object) {
array_destroy(object, N); ms_destroy(object, size);
object = 0;
} }
} }
private: private:
T* object; type* object;
}; };
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Glen Joseph Fernandes * Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com * glenfe at live dot com
* *
* Distributed under the Boost Software License, * Distributed under the Boost Software License,
@@ -9,40 +9,47 @@
#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP
#define BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP #define BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP
#include <boost/type_traits/remove_cv.hpp> #include <cstddef>
namespace boost { namespace boost {
namespace detail { namespace detail {
template<typename T> template<typename T>
struct array_base { struct array_base {
typedef typename boost::remove_cv<T>::type type; typedef T type;
}; };
template<typename T> template<typename T>
struct array_base<T[]> { struct array_base<T[]> {
typedef typename array_base<T>::type type; typedef typename array_base<T>::type type;
}; };
template<typename T, std::size_t N> template<typename T, std::size_t N>
struct array_base<T[N]> { struct array_base<T[N]> {
typedef typename array_base<T>::type type; typedef typename array_base<T>::type type;
}; };
template<typename T> template<typename T>
struct array_total { struct array_total {
enum { enum {
size = 1 size = 1
}; };
}; };
template<typename T, std::size_t N> template<typename T, std::size_t N>
struct array_total<T[N]> { struct array_total<T[N]> {
enum { enum {
size = N * array_total<T>::size size = N * array_total<T>::size
}; };
}; };
template<typename T> template<typename T>
struct array_inner; struct array_inner;
template<typename T> template<typename T>
struct array_inner<T[]> { struct array_inner<T[]> {
typedef T type; typedef T type;
}; };
template<typename T, std::size_t N> template<typename T, std::size_t N>
struct array_inner<T[N]> { struct array_inner<T[N]> {
typedef T type; typedef T type;

View File

@@ -1,9 +1,9 @@
/* /*
* Copyright (c) 2012 Glen Joseph Fernandes * Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com * glenfe at live dot com
* *
* Distributed under the Boost Software License, * Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt * Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt) * or copy at http://boost.org/LICENSE_1_0.txt)
*/ */
#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP
@@ -12,31 +12,61 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/type_traits/has_trivial_constructor.hpp> #include <boost/type_traits/has_trivial_constructor.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp> #include <boost/type_traits/has_trivial_destructor.hpp>
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
#include <memory>
#endif
namespace boost { namespace boost {
namespace detail { namespace detail {
typedef boost::true_type ms_is_trivial;
typedef boost::false_type ms_no_trivial;
template<typename T> template<typename T>
inline void array_destroy(T*, std::size_t, boost::true_type) { inline void ms_destroy(T*, std::size_t, ms_is_trivial) {
} }
template<typename T> template<typename T>
inline void array_destroy(T* memory, std::size_t size, boost::false_type) { inline void ms_destroy(T* memory, std::size_t size, ms_no_trivial) {
for (std::size_t i = size; i > 0; ) { for (std::size_t i = size; i > 0;) {
memory[--i].~T(); memory[--i].~T();
} }
} }
template<typename T> template<typename T>
inline void array_destroy(T* memory, std::size_t size) { inline void ms_destroy(T* memory, std::size_t size) {
boost::has_trivial_destructor<T> type; boost::has_trivial_destructor<T> trivial;
array_destroy(memory, size, type); ms_destroy(memory, size, trivial);
} }
template<typename T>
inline void array_init(T* memory, std::size_t size, boost::true_type) { #if !defined(BOOST_NO_CXX11_ALLOCATOR)
for (std::size_t i = 0; i < size; i++) { template<typename T, typename A>
memory[i] = T(); inline void as_destroy(A& allocator, T* memory,
std::size_t size) {
typedef typename std::allocator_traits<A>::
template rebind_traits<T> TT;
for (std::size_t i = size; i > 0;) {
TT::destroy(allocator, &memory[--i]);
} }
} }
#else
template<typename T, typename A>
inline void as_destroy(const A&, T* memory,
std::size_t size) {
boost::has_trivial_destructor<T> trivial;
ms_destroy(memory, size, trivial);
}
#endif
template<typename T> template<typename T>
inline void array_init(T* memory, std::size_t size, boost::false_type) { inline void ms_init(T* memory, std::size_t size, ms_is_trivial) {
for (std::size_t i = 0; i < size; i++) {
void* p1 = memory + i;
::new(p1) T();
}
}
template<typename T>
inline void ms_init(T* memory, std::size_t size, ms_no_trivial) {
#if !defined(BOOST_NO_EXCEPTIONS) #if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0; std::size_t i = 0;
try { try {
@@ -45,7 +75,7 @@ namespace boost {
::new(p1) T(); ::new(p1) T();
} }
} catch (...) { } catch (...) {
array_destroy(memory, i); ms_destroy(memory, i);
throw; throw;
} }
#else #else
@@ -55,77 +85,68 @@ namespace boost {
} }
#endif #endif
} }
template<typename T> template<typename T>
inline void array_init(T* memory, std::size_t size) { inline void ms_init(T* memory, std::size_t size) {
boost::has_trivial_default_constructor<T> type; boost::has_trivial_default_constructor<T> trivial;
array_init(memory, size, type); ms_init(memory, size, trivial);
} }
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<typename T>
inline void array_init_value(T* memory, std::size_t size, T&& value) { #if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<typename T, typename A>
inline void as_init(const A& allocator, T* memory, std::size_t size,
ms_is_trivial) {
typedef typename std::allocator_traits<A>::
template rebind_alloc<T> TA;
typedef typename std::allocator_traits<A>::
template rebind_traits<T> TT;
TA a2(allocator);
for (std::size_t i = 0; i < size; i++) {
TT::construct(a2, memory + i);
}
}
template<typename T, typename A>
inline void as_init(const A& allocator, T* memory, std::size_t size,
ms_no_trivial) {
typedef typename std::allocator_traits<A>::
template rebind_alloc<T> TA;
typedef typename std::allocator_traits<A>::
template rebind_traits<T> TT;
TA a2(allocator);
#if !defined(BOOST_NO_EXCEPTIONS) #if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0; std::size_t i = 0;
try { try {
for (; i < size; i++) { for (; i < size; i++) {
void* p1 = memory + i; TT::construct(a2, memory + i);
::new(p1) T(value);
} }
} catch (...) { } catch (...) {
array_destroy(memory, i); as_destroy(a2, memory, i);
throw; throw;
} }
#else #else
for (std::size_t i = 0; i < size; i++) { for (std::size_t i = 0; i < size; i++) {
void* p1 = memory + i; TT::construct(a2, memory + i);
::new(p1) T(value);
} }
#endif #endif
} }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<typename T, typename... Args> template<typename T, typename A>
inline void array_init_args(T* memory, std::size_t size, Args&&... args) { inline void as_init(const A& allocator, T* memory, std::size_t size) {
#if !defined(BOOST_NO_EXCEPTIONS) boost::has_trivial_default_constructor<T> trivial;
std::size_t i = 0; as_init(allocator, memory, size, trivial);
try { }
for (; i < size; i++) {
void* p1 = memory + i;
::new(p1) T(args...);
}
} catch (...) {
array_destroy(memory, i);
throw;
}
#else #else
for (std::size_t i = 0; i < size; i++) { template<typename T, typename A>
void* p1 = memory + i; inline void as_init(const A&, T* memory, std::size_t size) {
::new(p1) T(args...); boost::has_trivial_default_constructor<T> trivial;
} ms_init(memory, size, trivial);
#endif
} }
#endif #endif
#endif
template<typename T>
inline void array_init_list(T* memory, std::size_t size, const T* list) {
#if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0;
try {
for (; i < size; i++) {
void* p1 = memory + i;
::new(p1) T(list[i]);
}
} catch (...) {
array_destroy(memory, i);
throw;
}
#else
for (std::size_t i = 0; i < size; i++) {
void* p1 = memory + i;
::new(p1) T(list[i]);
}
#endif
}
template<typename T, std::size_t N> template<typename T, std::size_t N>
inline void array_init_list(T* memory, std::size_t size, const T* list) { inline void ms_init(T* memory, std::size_t size, const T* list) {
#if !defined(BOOST_NO_EXCEPTIONS) #if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0; std::size_t i = 0;
try { try {
@@ -134,7 +155,7 @@ namespace boost {
::new(p1) T(list[i % N]); ::new(p1) T(list[i % N]);
} }
} catch (...) { } catch (...) {
array_destroy(memory, i); ms_destroy(memory, i);
throw; throw;
} }
#else #else
@@ -144,11 +165,62 @@ namespace boost {
} }
#endif #endif
} }
template<typename T>
inline void array_noinit(T*, std::size_t, boost::true_type) { #if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<typename T, typename A, std::size_t N>
inline void as_init(const A& allocator, T* memory, std::size_t size,
const T* list) {
typedef typename std::allocator_traits<A>::
template rebind_alloc<T> TA;
typedef typename std::allocator_traits<A>::
template rebind_traits<T> TT;
TA a2(allocator);
#if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0;
try {
for (; i < size; i++) {
TT::construct(a2, memory + i, list[i % N]);
}
} catch (...) {
as_destroy(a2, memory, i);
throw;
}
#else
for (std::size_t i = 0; i < size; i++) {
TT::construct(a2, memory + i, list[i % N]);
}
#endif
} }
#else
template<typename T, typename A, std::size_t N>
inline void as_init(const A&, T* memory, std::size_t size,
const T* list) {
#if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0;
try {
for (; i < size; i++) {
void* p1 = memory + i;
::new(p1) T(list[i % N]);
}
} catch (...) {
ms_destroy(memory, i);
throw;
}
#else
for (std::size_t i = 0; i < size; i++) {
void* p1 = memory + i;
::new(p1) T(list[i % N]);
}
#endif
}
#endif
template<typename T> template<typename T>
inline void array_noinit(T* memory, std::size_t size, boost::false_type) { inline void ms_noinit(T*, std::size_t, ms_is_trivial) {
}
template<typename T>
inline void ms_noinit(T* memory, std::size_t size, ms_no_trivial) {
#if !defined(BOOST_NO_EXCEPTIONS) #if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0; std::size_t i = 0;
try { try {
@@ -157,7 +229,7 @@ namespace boost {
::new(p1) T; ::new(p1) T;
} }
} catch (...) { } catch (...) {
array_destroy(memory, i); ms_destroy(memory, i);
throw; throw;
} }
#else #else
@@ -167,10 +239,11 @@ namespace boost {
} }
#endif #endif
} }
template<typename T> template<typename T>
inline void array_noinit(T* memory, std::size_t size) { inline void ms_noinit(T* memory, std::size_t size) {
boost::has_trivial_default_constructor<T> type; boost::has_trivial_default_constructor<T> trivial;
array_noinit(memory, size, type); ms_noinit(memory, size, trivial);
} }
} }
} }

View File

@@ -11,10 +11,11 @@
// boost/detail/atomic_count.hpp - thread/SMP safe reference counter // boost/detail/atomic_count.hpp - thread/SMP safe reference counter
// //
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2013 Peter Dimov
// //
// Distributed under the Boost Software License, Version 1.0. (See // Distributed under the Boost Software License, Version 1.0.
// accompanying file LICENSE_1_0.txt or copy at // See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt
// //
// typedef <implementation-defined> boost::detail::atomic_count; // typedef <implementation-defined> boost::detail::atomic_count;
// //
@@ -27,92 +28,68 @@
// a; // a;
// //
// Returns: (long) the current value of a // Returns: (long) the current value of a
// Memory Ordering: acquire
// //
// ++a; // ++a;
// //
// Effects: Atomically increments the value of a // Effects: Atomically increments the value of a
// Returns: (long) the new value of a // Returns: (long) the new value of a
// Memory Ordering: acquire/release
// //
// --a; // --a;
// //
// Effects: Atomically decrements the value of a // Effects: Atomically decrements the value of a
// Returns: (long) the new value of a // Returns: (long) the new value of a
// // Memory Ordering: acquire/release
// Important note: when --a returns zero, it must act as a
// read memory barrier (RMB); i.e. the calling thread must
// have a synchronized view of the memory
//
// On Intel IA-32 (x86) memory is always synchronized, so this
// is not a problem.
//
// On many architectures the atomic instructions already act as
// a memory barrier.
//
// This property is necessary for proper reference counting, since
// a thread can update the contents of a shared object, then
// release its reference, and another thread may immediately
// release the last reference causing object destruction.
//
// The destructor needs to have a synchronized view of the
// object to perform proper cleanup.
//
// Original example by Alexander Terekhov:
//
// Given:
//
// - a mutable shared object OBJ;
// - two threads THREAD1 and THREAD2 each holding
// a private smart_ptr object pointing to that OBJ.
//
// t1: THREAD1 updates OBJ (thread-safe via some synchronization)
// and a few cycles later (after "unlock") destroys smart_ptr;
//
// t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization
// with respect to shared mutable object OBJ; OBJ destructors
// are called driven by smart_ptr interface...
// //
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/smart_ptr/detail/sp_has_sync.hpp> #include <boost/smart_ptr/detail/sp_has_sync.hpp>
#ifndef BOOST_HAS_THREADS #if defined( BOOST_AC_DISABLE_THREADS )
# include <boost/smart_ptr/detail/atomic_count_nt.hpp>
namespace boost #elif defined( BOOST_AC_USE_STD_ATOMIC )
{ # include <boost/smart_ptr/detail/atomic_count_std_atomic.hpp>
namespace detail #elif defined( BOOST_AC_USE_SPINLOCK )
{ # include <boost/smart_ptr/detail/atomic_count_spin.hpp>
typedef long atomic_count; #elif defined( BOOST_AC_USE_PTHREADS )
# include <boost/smart_ptr/detail/atomic_count_pt.hpp>
} #elif defined( BOOST_SP_DISABLE_THREADS )
# include <boost/smart_ptr/detail/atomic_count_nt.hpp>
} #elif defined( BOOST_SP_USE_STD_ATOMIC )
# include <boost/smart_ptr/detail/atomic_count_std_atomic.hpp>
#elif defined(BOOST_AC_USE_PTHREADS) #elif defined( BOOST_SP_USE_SPINLOCK )
# include <boost/smart_ptr/detail/atomic_count_pthreads.hpp> # include <boost/smart_ptr/detail/atomic_count_spin.hpp>
#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) #elif defined( BOOST_SP_USE_PTHREADS )
# include <boost/smart_ptr/detail/atomic_count_gcc_x86.hpp> # include <boost/smart_ptr/detail/atomic_count_pt.hpp>
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) #elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 )
# include <boost/smart_ptr/detail/atomic_count_win32.hpp> # include <boost/smart_ptr/detail/atomic_count_nt.hpp>
#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined( __PATHSCALE__ )
# include <boost/smart_ptr/detail/atomic_count_gcc_x86.hpp>
#elif defined( BOOST_SP_HAS_SYNC ) #elif defined( BOOST_SP_HAS_SYNC )
# include <boost/smart_ptr/detail/atomic_count_sync.hpp> # include <boost/smart_ptr/detail/atomic_count_sync.hpp>
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# include <boost/smart_ptr/detail/atomic_count_win32.hpp>
#elif defined(__GLIBCPP__) || defined(__GLIBCXX__) #elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
# include <boost/smart_ptr/detail/atomic_count_gcc.hpp> # include <boost/smart_ptr/detail/atomic_count_gcc.hpp>
#elif defined(BOOST_HAS_PTHREADS) #elif !defined( BOOST_HAS_THREADS )
# include <boost/smart_ptr/detail/atomic_count_nt.hpp>
# define BOOST_AC_USE_PTHREADS
# include <boost/smart_ptr/detail/atomic_count_pthreads.hpp>
#else #else
# include <boost/smart_ptr/detail/atomic_count_spin.hpp>
// Use #define BOOST_DISABLE_THREADS to avoid the error
#error Unrecognized threading platform
#endif #endif

View File

@@ -0,0 +1,59 @@
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED
//
// boost/detail/atomic_count_nt.hpp
//
// Trivial atomic_count for the single-threaded case
//
// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html
//
// Copyright 2013 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
namespace boost
{
namespace detail
{
class atomic_count
{
public:
explicit atomic_count( long v ): value_( v )
{
}
long operator++()
{
return ++value_;
}
long operator--()
{
return --value_;
}
operator long() const
{
return value_;
}
private:
atomic_count(atomic_count const &);
atomic_count & operator=(atomic_count const &);
long value_;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED

View File

@@ -11,6 +11,7 @@
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
// //
#include <boost/assert.hpp>
#include <pthread.h> #include <pthread.h>
// //
@@ -37,12 +38,12 @@ private:
scoped_lock(pthread_mutex_t & m): m_(m) scoped_lock(pthread_mutex_t & m): m_(m)
{ {
pthread_mutex_lock(&m_); BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
} }
~scoped_lock() ~scoped_lock()
{ {
pthread_mutex_unlock(&m_); BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
} }
private: private:
@@ -54,12 +55,12 @@ public:
explicit atomic_count(long v): value_(v) explicit atomic_count(long v): value_(v)
{ {
pthread_mutex_init(&mutex_, 0); BOOST_VERIFY( pthread_mutex_init( &mutex_, 0 ) == 0 );
} }
~atomic_count() ~atomic_count()
{ {
pthread_mutex_destroy(&mutex_); BOOST_VERIFY( pthread_mutex_destroy( &mutex_ ) == 0 );
} }
long operator++() long operator++()

View File

@@ -0,0 +1,62 @@
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED
//
// boost/detail/atomic_count_spin.hpp
//
// Copyright (c) 2013 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/smart_ptr/detail/spinlock_pool.hpp>
namespace boost
{
namespace detail
{
class atomic_count
{
private:
public:
explicit atomic_count( long v ): value_( v )
{
}
long operator++()
{
spinlock_pool<0>::scoped_lock lock( &value_ );
return ++value_;
}
long operator--()
{
spinlock_pool<0>::scoped_lock lock( &value_ );
return --value_;
}
operator long() const
{
spinlock_pool<0>::scoped_lock lock( &value_ );
return value_;
}
private:
atomic_count(atomic_count const &);
atomic_count & operator=(atomic_count const &);
long value_;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED

View File

@@ -0,0 +1,60 @@
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED
//
// boost/detail/atomic_count_std_atomic.hpp
//
// atomic_count for std::atomic
//
// Copyright 2013 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <atomic>
#include <cstdint>
namespace boost
{
namespace detail
{
class atomic_count
{
public:
explicit atomic_count( long v ): value_( v )
{
}
long operator++()
{
return value_.fetch_add( 1, std::memory_order_acq_rel ) + 1;
}
long operator--()
{
return value_.fetch_sub( 1, std::memory_order_acq_rel ) - 1;
}
operator long() const
{
return value_.load( std::memory_order_acquire );
}
private:
atomic_count(atomic_count const &);
atomic_count & operator=(atomic_count const &);
std::atomic_int_least32_t value_;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED

View File

@@ -1,157 +0,0 @@
/*
* Copyright (c) 2012 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP
#define BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP
#include <boost/type_traits/alignment_of.hpp>
namespace boost {
namespace detail {
template<typename T, typename Y = char>
class make_array_helper;
template<typename T, typename Y>
class make_array_helper<T[], Y> {
template<typename T2, typename Y2>
friend class make_array_helper;
public:
typedef Y value_type;
typedef Y* pointer;
typedef const Y* const_pointer;
typedef Y& reference;
typedef const Y& const_reference;
typedef std::size_t size_type;
typedef ptrdiff_t difference_type;
template<typename U>
struct rebind {
typedef make_array_helper<T[], U> other;
};
make_array_helper(std::size_t size_, T** data_)
: size(sizeof(T) * size_),
data(data_) {
}
template<class U>
make_array_helper(const make_array_helper<T[], U>& other)
: size(other.size),
data(other.data) {
}
pointer address(reference value) const {
return &value;
}
const_pointer address(const_reference value) const {
return &value;
}
size_type max_size() const {
return static_cast<std::size_t>(-1) / sizeof(Y);
}
pointer allocate(size_type count, const void* = 0) {
std::size_t a1 = boost::alignment_of<T>::value;
std::size_t n1 = count * sizeof(Y) + a1 - 1;
void* p1 = ::operator new(n1 + size);
char* p2 = static_cast<char*>(p1) + n1;
while (std::size_t(p2) % a1 != 0) {
p2--;
}
*data = reinterpret_cast<T*>(p2);
return reinterpret_cast<Y*>(p1);
}
void deallocate(pointer memory, size_type) {
void* p1 = memory;
::operator delete(p1);
}
void construct(pointer memory, const Y& value) {
void* p1 = memory;
::new(p1) Y(value);
}
void destroy(pointer memory) {
memory->~Y();
}
template<typename U>
bool operator==(const make_array_helper<T[], U>&) const {
return true;
}
template<typename U>
bool operator!=(const make_array_helper<T[], U>& other) const {
return !(*this == other);
}
private:
std::size_t size;
T** data;
};
template<typename T, std::size_t N, typename Y>
class make_array_helper<T[N], Y> {
template<typename T2, typename Y2>
friend class make_array_helper;
public:
typedef Y value_type;
typedef Y* pointer;
typedef const Y* const_pointer;
typedef Y& reference;
typedef const Y& const_reference;
typedef std::size_t size_type;
typedef ptrdiff_t difference_type;
template<typename U>
struct rebind {
typedef make_array_helper<T[N], U> other;
};
make_array_helper(T** data_)
: data(data_) {
}
template<class U>
make_array_helper(const make_array_helper<T[N], U>& other)
: data(other.data) {
}
pointer address(reference value) const {
return &value;
}
const_pointer address(const_reference value) const {
return &value;
}
size_type max_size() const {
return static_cast<std::size_t>(-1) / sizeof(Y);
}
pointer allocate(size_type count, const void* = 0) {
std::size_t a1 = boost::alignment_of<T>::value;
std::size_t n1 = count * sizeof(Y) + a1 - 1;
void* p1 = ::operator new(n1 + N1);
char* p2 = static_cast<char*>(p1) + n1;
while (std::size_t(p2) % a1 != 0) {
p2--;
}
*data = reinterpret_cast<T*>(p2);
return reinterpret_cast<Y*>(p1);
}
void deallocate(pointer memory, size_type) {
void* p1 = memory;
::operator delete(p1);
}
void construct(pointer memory, const Y& value) {
void* p1 = memory;
::new(p1) Y(value);
}
void destroy(pointer memory) {
memory->~Y();
}
template<typename U>
bool operator==(const make_array_helper<T[N], U>&) const {
return true;
}
template<typename U>
bool operator!=(const make_array_helper<T[N], U>& other) const {
return !(*this == other);
}
private:
enum {
N1 = N * sizeof(T)
};
T** data;
};
}
}
#endif

View File

@@ -1,151 +0,0 @@
#ifndef BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED
//
// detail/shared_array_nmt.hpp - shared_array.hpp without member templates
//
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation.
//
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/smart_ptr/detail/atomic_count.hpp>
#include <cstddef> // for std::ptrdiff_t
#include <algorithm> // for std::swap
#include <functional> // for std::less
#include <new> // for std::bad_alloc
namespace boost
{
template<class T> class shared_array
{
private:
typedef detail::atomic_count count_type;
public:
typedef T element_type;
explicit shared_array(T * p = 0): px(p)
{
#ifndef BOOST_NO_EXCEPTIONS
try // prevent leak if new throws
{
pn = new count_type(1);
}
catch(...)
{
boost::checked_array_delete(p);
throw;
}
#else
pn = new count_type(1);
if(pn == 0)
{
boost::checked_array_delete(p);
boost::throw_exception(std::bad_alloc());
}
#endif
}
~shared_array()
{
if(--*pn == 0)
{
boost::checked_array_delete(px);
delete pn;
}
}
shared_array(shared_array const & r) : px(r.px) // never throws
{
pn = r.pn;
++*pn;
}
shared_array & operator=(shared_array const & r)
{
shared_array(r).swap(*this);
return *this;
}
void reset(T * p = 0)
{
BOOST_ASSERT(p == 0 || p != px);
shared_array(p).swap(*this);
}
T * get() const // never throws
{
return px;
}
T & operator[](std::ptrdiff_t i) const // never throws
{
BOOST_ASSERT(px != 0);
BOOST_ASSERT(i >= 0);
return px[i];
}
long use_count() const // never throws
{
return *pn;
}
bool unique() const // never throws
{
return *pn == 1;
}
void swap(shared_array<T> & other) // never throws
{
std::swap(px, other.px);
std::swap(pn, other.pn);
}
private:
T * px; // contained pointer
count_type * pn; // ptr to reference counter
}; // shared_array
template<class T, class U> inline bool operator==(shared_array<T> const & a, shared_array<U> const & b)
{
return a.get() == b.get();
}
template<class T, class U> inline bool operator!=(shared_array<T> const & a, shared_array<U> const & b)
{
return a.get() != b.get();
}
template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b)
{
return std::less<T*>()(a.get(), b.get());
}
template<class T> void swap(shared_array<T> & a, shared_array<T> & b)
{
a.swap(b);
}
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED

View File

@@ -225,16 +225,35 @@ public:
#endif #endif
{ {
typedef sp_counted_impl_pda<P, D, A> impl_type; typedef sp_counted_impl_pda<P, D, A> impl_type;
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
#else
typedef typename A::template rebind< impl_type >::other A2; typedef typename A::template rebind< impl_type >::other A2;
#endif
A2 a2( a ); A2 a2( a );
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
try try
{ {
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
pi_ = pi;
std::allocator_traits<A2>::construct( a2, pi, p, d, a );
#else
pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
#endif
} }
catch(...) catch(...)
{ {
@@ -248,13 +267,30 @@ public:
throw; throw;
} }
#else
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
pi_ = pi;
#else #else
pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
#endif
if( pi_ != 0 ) if( pi_ != 0 )
{ {
new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); #if !defined( BOOST_NO_CXX11_ALLOCATOR )
std::allocator_traits<A2>::construct( a2, pi, p, d, a );
#else
::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
#endif
} }
else else
{ {
@@ -273,16 +309,35 @@ public:
#endif #endif
{ {
typedef sp_counted_impl_pda< P, D, A > impl_type; typedef sp_counted_impl_pda< P, D, A > impl_type;
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
#else
typedef typename A::template rebind< impl_type >::other A2; typedef typename A::template rebind< impl_type >::other A2;
#endif
A2 a2( a ); A2 a2( a );
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
try try
{ {
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
pi_ = pi;
std::allocator_traits<A2>::construct( a2, pi, p, a );
#else
pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
new( static_cast< void* >( pi_ ) ) impl_type( p, a ); ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
#endif
} }
catch(...) catch(...)
{ {
@@ -296,13 +351,30 @@ public:
throw; throw;
} }
#else
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
pi_ = pi;
#else #else
pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
#endif
if( pi_ != 0 ) if( pi_ != 0 )
{ {
new( static_cast< void* >( pi_ ) ) impl_type( p, a ); #if !defined( BOOST_NO_CXX11_ALLOCATOR )
std::allocator_traits<A2>::construct( a2, pi, p, a );
#else
::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
#endif
} }
else else
{ {

View File

@@ -1,182 +0,0 @@
#ifndef BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED
//
// detail/shared_ptr_nmt.hpp - shared_ptr.hpp without member templates
//
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
//
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/smart_ptr/detail/atomic_count.hpp>
#ifndef BOOST_NO_AUTO_PTR
# include <memory> // for std::auto_ptr
#endif
#include <algorithm> // for std::swap
#include <functional> // for std::less
#include <new> // for std::bad_alloc
namespace boost
{
template<class T> class shared_ptr
{
private:
typedef detail::atomic_count count_type;
public:
typedef T element_type;
typedef T value_type;
explicit shared_ptr(T * p = 0): px(p)
{
#ifndef BOOST_NO_EXCEPTIONS
try // prevent leak if new throws
{
pn = new count_type(1);
}
catch(...)
{
boost::checked_delete(p);
throw;
}
#else
pn = new count_type(1);
if(pn == 0)
{
boost::checked_delete(p);
boost::throw_exception(std::bad_alloc());
}
#endif
}
~shared_ptr()
{
if(--*pn == 0)
{
boost::checked_delete(px);
delete pn;
}
}
shared_ptr(shared_ptr const & r): px(r.px) // never throws
{
pn = r.pn;
++*pn;
}
shared_ptr & operator=(shared_ptr const & r)
{
shared_ptr(r).swap(*this);
return *this;
}
#ifndef BOOST_NO_AUTO_PTR
explicit shared_ptr(std::auto_ptr<T> & r)
{
pn = new count_type(1); // may throw
px = r.release(); // fix: moved here to stop leak if new throws
}
shared_ptr & operator=(std::auto_ptr<T> & r)
{
shared_ptr(r).swap(*this);
return *this;
}
#endif
void reset(T * p = 0)
{
BOOST_ASSERT(p == 0 || p != px);
shared_ptr(p).swap(*this);
}
T & operator*() const // never throws
{
BOOST_ASSERT(px != 0);
return *px;
}
T * operator->() const // never throws
{
BOOST_ASSERT(px != 0);
return px;
}
T * get() const // never throws
{
return px;
}
long use_count() const // never throws
{
return *pn;
}
bool unique() const // never throws
{
return *pn == 1;
}
void swap(shared_ptr<T> & other) // never throws
{
std::swap(px, other.px);
std::swap(pn, other.pn);
}
private:
T * px; // contained pointer
count_type * pn; // ptr to reference counter
};
template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
{
return a.get() == b.get();
}
template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
{
return a.get() != b.get();
}
template<class T> inline bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b)
{
return std::less<T*>()(a.get(), b.get());
}
template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b)
{
a.swap(b);
}
// get_pointer() enables boost::mem_fn to recognize shared_ptr
template<class T> inline T * get_pointer(shared_ptr<T> const & p)
{
return p.get();
}
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED

View File

@@ -10,7 +10,7 @@
// //
// detail/sp_counted_base.hpp // detail/sp_counted_base.hpp
// //
// Copyright 2005, 2006 Peter Dimov // Copyright 2005-2013 Peter Dimov
// //
// Distributed under the Boost Software License, Version 1.0. (See // Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at // accompanying file LICENSE_1_0.txt or copy at
@@ -23,6 +23,9 @@
#if defined( BOOST_SP_DISABLE_THREADS ) #if defined( BOOST_SP_DISABLE_THREADS )
# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp> # include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
#elif defined( BOOST_SP_USE_STD_ATOMIC )
# include <boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp>
#elif defined( BOOST_SP_USE_SPINLOCK ) #elif defined( BOOST_SP_USE_SPINLOCK )
# include <boost/smart_ptr/detail/sp_counted_base_spin.hpp> # include <boost/smart_ptr/detail/sp_counted_base_spin.hpp>

View File

@@ -19,6 +19,7 @@
// //
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/assert.hpp>
#include <pthread.h> #include <pthread.h>
namespace boost namespace boost
@@ -46,15 +47,15 @@ public:
// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init // HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
#if defined(__hpux) && defined(_DECTHREADS_) #if defined(__hpux) && defined(_DECTHREADS_)
pthread_mutex_init( &m_, pthread_mutexattr_default ); BOOST_VERIFY( pthread_mutex_init( &m_, pthread_mutexattr_default ) == 0 );
#else #else
pthread_mutex_init( &m_, 0 ); BOOST_VERIFY( pthread_mutex_init( &m_, 0 ) == 0 );
#endif #endif
} }
virtual ~sp_counted_base() // nothrow virtual ~sp_counted_base() // nothrow
{ {
pthread_mutex_destroy( &m_ ); BOOST_VERIFY( pthread_mutex_destroy( &m_ ) == 0 );
} }
// dispose() is called when use_count_ drops to zero, to release // dispose() is called when use_count_ drops to zero, to release
@@ -74,24 +75,24 @@ public:
void add_ref_copy() void add_ref_copy()
{ {
pthread_mutex_lock( &m_ ); BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
++use_count_; ++use_count_;
pthread_mutex_unlock( &m_ ); BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
} }
bool add_ref_lock() // true on success bool add_ref_lock() // true on success
{ {
pthread_mutex_lock( &m_ ); BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
bool r = use_count_ == 0? false: ( ++use_count_, true ); bool r = use_count_ == 0? false: ( ++use_count_, true );
pthread_mutex_unlock( &m_ ); BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
return r; return r;
} }
void release() // nothrow void release() // nothrow
{ {
pthread_mutex_lock( &m_ ); BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
long new_use_count = --use_count_; long new_use_count = --use_count_;
pthread_mutex_unlock( &m_ ); BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
if( new_use_count == 0 ) if( new_use_count == 0 )
{ {
@@ -102,16 +103,16 @@ public:
void weak_add_ref() // nothrow void weak_add_ref() // nothrow
{ {
pthread_mutex_lock( &m_ ); BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
++weak_count_; ++weak_count_;
pthread_mutex_unlock( &m_ ); BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
} }
void weak_release() // nothrow void weak_release() // nothrow
{ {
pthread_mutex_lock( &m_ ); BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
long new_weak_count = --weak_count_; long new_weak_count = --weak_count_;
pthread_mutex_unlock( &m_ ); BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
if( new_weak_count == 0 ) if( new_weak_count == 0 )
{ {
@@ -121,9 +122,9 @@ public:
long use_count() const // nothrow long use_count() const // nothrow
{ {
pthread_mutex_lock( &m_ ); BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
long r = use_count_; long r = use_count_;
pthread_mutex_unlock( &m_ ); BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
return r; return r;
} }

View File

@@ -0,0 +1,137 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// detail/sp_counted_base_std_atomic.hpp - C++11 std::atomic
//
// Copyright (c) 2007, 2013 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/sp_typeinfo.hpp>
#include <atomic>
#include <cstdint>
namespace boost
{
namespace detail
{
inline void atomic_increment( std::atomic_int_least32_t * pw )
{
pw->fetch_add( 1, std::memory_order_relaxed );
}
inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw )
{
return pw->fetch_sub( 1, std::memory_order_acq_rel );
}
inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_t * pw )
{
// long r = *pw;
// if( r != 0 ) ++*pw;
// return r;
std::int_least32_t r = pw->load( std::memory_order_relaxed );
for( ;; )
{
if( r == 0 )
{
return r;
}
if( pw->compare_exchange_weak( r, r + 1, std::memory_order_relaxed, std::memory_order_relaxed ) )
{
return r;
}
}
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
std::atomic_int_least32_t use_count_; // #shared
std::atomic_int_least32_t weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_decrement( &use_count_ ) == 1 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_decrement( &weak_count_ ) == 1 )
{
destroy();
}
}
long use_count() const // nothrow
{
return use_count_.load( std::memory_order_acquire );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED

View File

@@ -213,7 +213,7 @@ public:
{ {
} }
sp_counted_impl_pda( P p, A a ): p_( p ), d_(), a_( a ) sp_counted_impl_pda( P p, A a ): p_( p ), d_( a ), a_( a )
{ {
} }
@@ -224,11 +224,28 @@ public:
virtual void destroy() // nothrow virtual void destroy() // nothrow
{ {
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
typedef typename std::allocator_traits<A>::template rebind_alloc< this_type > A2;
#else
typedef typename A::template rebind< this_type >::other A2; typedef typename A::template rebind< this_type >::other A2;
#endif
A2 a2( a_ ); A2 a2( a_ );
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
std::allocator_traits<A2>::destroy( a2, this );
#else
this->~this_type(); this->~this_type();
#endif
a2.deallocate( this, 1 ); a2.deallocate( this, 1 );
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Glen Joseph Fernandes * Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com * glenfe at live dot com
* *
* Distributed under the Boost Software License, * Distributed under the Boost Software License,
@@ -15,12 +15,15 @@ namespace boost {
namespace detail { namespace detail {
template<typename T> template<typename T>
struct sp_if_array; struct sp_if_array;
template<typename T> template<typename T>
struct sp_if_array<T[]> { struct sp_if_array<T[]> {
typedef boost::shared_ptr<T[]> type; typedef boost::shared_ptr<T[]> type;
}; };
template<typename T> template<typename T>
struct sp_if_size_array; struct sp_if_size_array;
template<typename T, std::size_t N> template<typename T, std::size_t N>
struct sp_if_size_array<T[N]> { struct sp_if_size_array<T[N]> {
typedef boost::shared_ptr<T[N]> type; typedef boost::shared_ptr<T[N]> type;

View File

@@ -0,0 +1,26 @@
/*
* Copyright (c) 2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_DETAIL_UP_IF_ARRAY_HPP
#define BOOST_SMART_PTR_DETAIL_UP_IF_ARRAY_HPP
#include <memory>
namespace boost {
namespace detail {
template<typename T>
struct up_if_array;
template<typename T>
struct up_if_array<T[]> {
typedef std::unique_ptr<T[]> type;
};
}
}
#endif

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_DETAIL_UP_IF_NOT_ARRAY_HPP
#define BOOST_SMART_PTR_DETAIL_UP_IF_NOT_ARRAY_HPP
#include <memory>
namespace boost {
namespace detail {
template<typename T>
struct up_if_not_array {
typedef std::unique_ptr<T> type;
};
template<typename T>
struct up_if_not_array<T[]> {
};
template<typename T, std::size_t N>
struct up_if_not_array<T[N]> {
};
}
}
#endif

View File

@@ -146,11 +146,23 @@ public:
this_type( rhs ).swap( *this ); this_type( rhs ).swap( *this );
} }
void reset( T * rhs, bool add_ref )
{
this_type( rhs, add_ref ).swap( *this );
}
T * get() const BOOST_NOEXCEPT T * get() const BOOST_NOEXCEPT
{ {
return px; return px;
} }
T * detach() BOOST_NOEXCEPT
{
T * ret = px;
px = 0;
return ret;
}
T & operator*() const T & operator*() const
{ {
BOOST_ASSERT( px != 0 ); BOOST_ASSERT( px != 0 );

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Glen Joseph Fernandes * Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com * glenfe at live dot com
* *
* Distributed under the Boost Software License, * Distributed under the Boost Software License,
@@ -9,14 +9,10 @@
#ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP #ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
#define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP #define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
#include <boost/smart_ptr/shared_ptr.hpp> #include <boost/smart_ptr/detail/array_allocator.hpp>
#include <boost/smart_ptr/detail/array_deleter.hpp> #include <boost/smart_ptr/detail/array_deleter.hpp>
#include <boost/smart_ptr/detail/array_traits.hpp>
#include <boost/smart_ptr/detail/make_array_helper.hpp>
#include <boost/smart_ptr/detail/sp_if_array.hpp> #include <boost/smart_ptr/detail/sp_if_array.hpp>
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include <boost/type_traits/remove_cv.hpp>
#include <initializer_list>
#endif
namespace boost { namespace boost {
template<typename T> template<typename T>
@@ -24,222 +20,139 @@ namespace boost {
make_shared(std::size_t size) { make_shared(std::size_t size) {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
typedef boost::detail::ms_allocator<T3[]> A1;
typedef boost::detail::ms_deleter<T3[]> D1;
T1* p1 = 0; T1* p1 = 0;
T2* p2 = 0; T3* p2 = 0;
std::size_t n1 = size * boost::detail::array_total<T1>::size; std::size_t n1 = size * boost::detail::array_total<T1>::size;
boost::detail::make_array_helper<T2[]> a1(n1, &p2); D1 d1(n1);
boost::detail::array_deleter<T2[]> d1(n1); A1 a1(n1, &p2);
boost::shared_ptr<T> s1(p1, d1, a1); boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[]>* D2;
p1 = reinterpret_cast<T1*>(p2); p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter()); boost::detail::ms_init(p2, n1);
d2->init(p2); D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1); return boost::shared_ptr<T>(s1, p1);
} }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<typename T, typename... Args>
inline typename boost::detail::sp_if_array<T>::type
make_shared(std::size_t size, Args&&... args) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
T1* p1 = 0;
T2* p2 = 0;
std::size_t n1 = size * boost::detail::array_total<T1>::size;
boost::detail::make_array_helper<T2[]> a1(n1, &p2);
boost::detail::array_deleter<T2[]> d1(n1);
boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[]>* D2;
p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
d2->init(p2, boost::detail::sp_forward<Args>(args)...);
return boost::shared_ptr<T>(s1, p1);
}
template<typename T, typename... Args>
inline typename boost::detail::sp_if_size_array<T>::type
make_shared(Args&&... args) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
enum {
N = boost::detail::array_total<T>::size
};
T1* p1 = 0;
T2* p2 = 0;
boost::detail::make_array_helper<T2[N]> a1(&p2);
boost::detail::array_deleter<T2[N]> d1;
boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[N]>* D2;
p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
d2->init(p2, boost::detail::sp_forward<Args>(args)...);
return boost::shared_ptr<T>(s1, p1);
}
#endif
#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
template<typename T> template<typename T>
inline typename boost::detail::sp_if_size_array<T>::type inline typename boost::detail::sp_if_size_array<T>::type
make_shared(const T& list) { make_shared() {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef const T2 T3; typedef typename boost::remove_cv<T2>::type T3;
enum { enum {
N = boost::detail::array_total<T>::size N = boost::detail::array_total<T>::size
}; };
typedef boost::detail::ms_allocator<T3[N]> A1;
typedef boost::detail::ms_deleter<T3[N]> D1;
T1* p1 = 0; T1* p1 = 0;
T2* p2 = 0; T3* p2 = 0;
T3* p3 = 0; D1 d1;
boost::detail::make_array_helper<T2[N]> a1(&p2); A1 a1(&p2);
boost::detail::array_deleter<T2[N]> d1;
boost::shared_ptr<T> s1(p1, d1, a1); boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[N]>* D2;
p3 = reinterpret_cast<T3*>(list);
p1 = reinterpret_cast<T1*>(p2); p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter()); boost::detail::ms_init(p2, N);
d2->init_list(p2, p3); D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1); return boost::shared_ptr<T>(s1, p1);
} }
template<typename T> template<typename T>
inline typename boost::detail::sp_if_array<T>::type inline typename boost::detail::sp_if_array<T>::type
make_shared(std::size_t size, make_shared(std::size_t size,
const typename boost::detail::array_inner<T>::type& list) { const typename boost::detail::array_inner<T>::type& value) {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef const T2 T3; typedef typename boost::remove_cv<T2>::type T3;
typedef const T2 T4;
typedef boost::detail::ms_allocator<T3[]> A1;
typedef boost::detail::ms_deleter<T3[]> D1;
enum { enum {
M = boost::detail::array_total<T1>::size M = boost::detail::array_total<T1>::size
}; };
T1* p1 = 0; T1* p1 = 0;
T2* p2 = 0; T3* p2 = 0;
T3* p3 = 0; T4* p3 = reinterpret_cast<T4*>(&value);
std::size_t n1 = M * size; std::size_t n1 = M * size;
boost::detail::make_array_helper<T2[]> a1(n1, &p2); D1 d1(n1);
boost::detail::array_deleter<T2[]> d1(n1); A1 a1(n1, &p2);
boost::shared_ptr<T> s1(p1, d1, a1); boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[]>* D2;
p3 = reinterpret_cast<T3*>(list);
p1 = reinterpret_cast<T1*>(p2); p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter()); boost::detail::ms_init<T3, M>(p2, n1, p3);
d2->template init_list<M>(p2, p3); D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1); return boost::shared_ptr<T>(s1, p1);
} }
template<typename T> template<typename T>
inline typename boost::detail::sp_if_size_array<T>::type inline typename boost::detail::sp_if_size_array<T>::type
make_shared(const typename boost::detail::array_inner<T>::type& list) { make_shared(const typename boost::detail::array_inner<T>::type& value) {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef const T2 T3; typedef typename boost::remove_cv<T2>::type T3;
typedef const T2 T4;
enum { enum {
M = boost::detail::array_total<T1>::size, M = boost::detail::array_total<T1>::size,
N = boost::detail::array_total<T>::size N = boost::detail::array_total<T>::size
}; };
typedef boost::detail::ms_allocator<T3[N]> A1;
typedef boost::detail::ms_deleter<T3[N]> D1;
T1* p1 = 0; T1* p1 = 0;
T2* p2 = 0; T3* p2 = 0;
T3* p3 = 0; T4* p3 = reinterpret_cast<T4*>(&value);
boost::detail::make_array_helper<T2[N]> a1(&p2); D1 d1;
boost::detail::array_deleter<T2[N]> d1; A1 a1(&p2);
boost::shared_ptr<T> s1(p1, d1, a1); boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[N]>* D2;
p3 = reinterpret_cast<T3*>(list);
p1 = reinterpret_cast<T1*>(p2); p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter()); boost::detail::ms_init<T3, M>(p2, N, p3);
d2->template init_list<M>(p2, p3); D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1); return boost::shared_ptr<T>(s1, p1);
} }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template<typename T>
inline typename boost::detail::sp_if_array<T>::type
make_shared(std::initializer_list<typename boost::detail::array_inner<T>::type> list) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef const T2 T3;
T1* p1 = 0;
T2* p2 = 0;
T3* p3 = 0;
std::size_t n1 = list.size() * boost::detail::array_total<T1>::size;
boost::detail::make_array_helper<T2[]> a1(n1, &p2);
boost::detail::array_deleter<T2[]> d1(n1);
boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[]>* D2;
p3 = reinterpret_cast<T3*>(list.begin());
p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
d2->init_list(p2, p3);
return boost::shared_ptr<T>(s1, p1);
}
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<typename T>
inline typename boost::detail::sp_if_array<T>::type
make_shared(std::size_t size,
typename boost::detail::array_base<T>::type&& value) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
T1* p1 = 0;
T2* p2 = 0;
std::size_t n1 = size * boost::detail::array_total<T1>::size;
boost::detail::make_array_helper<T2[]> a1(n1, &p2);
boost::detail::array_deleter<T2[]> d1(n1);
boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[]>* D2;
p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
d2->init(p2, boost::detail::sp_forward<T2>(value));
return boost::shared_ptr<T>(s1, p1);
}
template<typename T>
inline typename boost::detail::sp_if_size_array<T>::type
make_shared(typename boost::detail::array_base<T>::type&& value) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
enum {
N = boost::detail::array_total<T>::size
};
T1* p1 = 0;
T2* p2 = 0;
boost::detail::make_array_helper<T2[N]> a1(&p2);
boost::detail::array_deleter<T2[N]> d1;
boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[N]>* D2;
p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter());
d2->init(p2, boost::detail::sp_forward<T2>(value));
return boost::shared_ptr<T>(s1, p1);
}
#endif
#endif
template<typename T> template<typename T>
inline typename boost::detail::sp_if_array<T>::type inline typename boost::detail::sp_if_array<T>::type
make_shared_noinit(std::size_t size) { make_shared_noinit(std::size_t size) {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
typedef boost::detail::ms_allocator<T3[]> A1;
typedef boost::detail::ms_deleter<T3[]> D1;
T1* p1 = 0; T1* p1 = 0;
T2* p2 = 0; T3* p2 = 0;
std::size_t n1 = size * boost::detail::array_total<T1>::size; std::size_t n1 = size * boost::detail::array_total<T1>::size;
boost::detail::make_array_helper<T2[]> a1(n1, &p2); D1 d1(n1);
boost::detail::array_deleter<T2[]> d1(n1); A1 a1(n1, &p2);
boost::shared_ptr<T> s1(p1, d1, a1); boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[]>* D2;
p1 = reinterpret_cast<T1*>(p2); p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter()); boost::detail::ms_noinit(p2, n1);
d2->noinit(p2); D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1); return boost::shared_ptr<T>(s1, p1);
} }
template<typename T> template<typename T>
inline typename boost::detail::sp_if_size_array<T>::type inline typename boost::detail::sp_if_size_array<T>::type
make_shared_noinit() { make_shared_noinit() {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
enum { enum {
N = boost::detail::array_total<T>::size N = boost::detail::array_total<T>::size
}; };
typedef boost::detail::ms_allocator<T3[N]> A1;
typedef boost::detail::ms_deleter<T3[N]> D1;
T1* p1 = 0; T1* p1 = 0;
T2* p2 = 0; T3* p2 = 0;
boost::detail::make_array_helper<T2[N]> a1(&p2); D1 d1;
boost::detail::array_deleter<T2[N]> d1; A1 a1(&p2);
boost::shared_ptr<T> s1(p1, d1, a1); boost::shared_ptr<T> s1(p1, d1, a1);
typedef boost::detail::array_deleter<T2[N]>* D2;
p1 = reinterpret_cast<T1*>(p2); p1 = reinterpret_cast<T1*>(p2);
D2 d2 = static_cast<D2>(s1._internal_get_untyped_deleter()); boost::detail::ms_noinit(p2, N);
d2->noinit(p2); D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1); return boost::shared_ptr<T>(s1, p1);
} }
} }

View File

@@ -72,6 +72,10 @@ public:
{ {
} }
template<class A> explicit sp_ms_deleter( A const & ) BOOST_NOEXCEPT : initialized_( false )
{
}
// optimization: do not copy storage_ // optimization: do not copy storage_
sp_ms_deleter( sp_ms_deleter const & ) BOOST_NOEXCEPT : initialized_( false ) sp_ms_deleter( sp_ms_deleter const & ) BOOST_NOEXCEPT : initialized_( false )
{ {
@@ -102,6 +106,74 @@ public:
} }
}; };
template< class T, class A > class sp_as_deleter
{
private:
typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
storage_type storage_;
A a_;
bool initialized_;
private:
void destroy()
{
if( initialized_ )
{
T * p = reinterpret_cast< T* >( storage_.data_ );
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
std::allocator_traits<A>::destroy( a_, p );
#else
p->~T();
#endif
initialized_ = false;
}
}
public:
sp_as_deleter( A const & a ) BOOST_NOEXCEPT : a_( a ), initialized_( false )
{
}
// optimization: do not copy storage_
sp_as_deleter( sp_as_deleter const & r ) BOOST_NOEXCEPT : a_( r.a_), initialized_( false )
{
}
~sp_as_deleter()
{
destroy();
}
void operator()( T * )
{
destroy();
}
static void operator_fn( T* ) // operator() can't be static
{
}
void * address() BOOST_NOEXCEPT
{
return storage_.data_;
}
void set_initialized() BOOST_NOEXCEPT
{
initialized_ = true;
}
};
template< class T > struct sp_if_not_array template< class T > struct sp_if_not_array
{ {
typedef boost::shared_ptr< T > type; typedef boost::shared_ptr< T > type;
@@ -131,26 +203,7 @@ template< class T, std::size_t N > struct sp_if_not_array< T[N] >
# define BOOST_SP_MSD( T ) boost::detail::sp_ms_deleter< T >() # define BOOST_SP_MSD( T ) boost::detail::sp_ms_deleter< T >()
#endif #endif
// Zero-argument versions // _noinit versions
//
// Used even when variadic templates are available because of the new T() vs new T issue
template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared()
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
void * pv = pd->address();
::new( pv ) T();
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared_noinit() template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared_noinit()
{ {
@@ -169,23 +222,6 @@ template< class T > typename boost::detail::sp_if_not_array< T >::type make_shar
return boost::shared_ptr< T >( pt, pt2 ); return boost::shared_ptr< T >( pt, pt2 );
} }
template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
void * pv = pd->address();
::new( pv ) T();
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared_noinit( A const & a ) template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared_noinit( A const & a )
{ {
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
@@ -207,7 +243,7 @@ template< class T, class A > typename boost::detail::sp_if_not_array< T >::type
// Variadic templates, rvalue reference // Variadic templates, rvalue reference
template< class T, class Arg1, class... Args > typename boost::detail::sp_if_not_array< T >::type make_shared( Arg1 && arg1, Args && ... args ) template< class T, class... Args > typename boost::detail::sp_if_not_array< T >::type make_shared( Args && ... args )
{ {
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) ); boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
@@ -215,7 +251,7 @@ template< class T, class Arg1, class... Args > typename boost::detail::sp_if_not
void * pv = pd->address(); void * pv = pd->address();
::new( pv ) T( boost::detail::sp_forward<Arg1>( arg1 ), boost::detail::sp_forward<Args>( args )... ); ::new( pv ) T( boost::detail::sp_forward<Args>( args )... );
pd->set_initialized(); pd->set_initialized();
T * pt2 = static_cast< T* >( pv ); T * pt2 = static_cast< T* >( pv );
@@ -224,7 +260,68 @@ template< class T, class Arg1, class... Args > typename boost::detail::sp_if_not
return boost::shared_ptr< T >( pt, pt2 ); return boost::shared_ptr< T >( pt, pt2 );
} }
template< class T, class A, class Arg1, class... Args > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, Arg1 && arg1, Args && ... args ) template< class T, class A, class... Args > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, Args && ... args )
{
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
A2 a2( a );
typedef boost::detail::sp_as_deleter< T, A2 > D;
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
#else
typedef boost::detail::sp_ms_deleter< T > D;
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a );
#endif
D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
void * pv = pd->address();
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
std::allocator_traits<A2>::construct( a2, static_cast< T* >( pv ), boost::detail::sp_forward<Args>( args )... );
#else
::new( pv ) T( boost::detail::sp_forward<Args>( args )... );
#endif
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
#else // !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
// Common zero-argument versions
template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared()
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
void * pv = pd->address();
::new( pv ) T();
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a )
{ {
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a ); boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
@@ -232,7 +329,7 @@ template< class T, class A, class Arg1, class... Args > typename boost::detail::
void * pv = pd->address(); void * pv = pd->address();
::new( pv ) T( boost::detail::sp_forward<Arg1>( arg1 ), boost::detail::sp_forward<Args>( args )... ); ::new( pv ) T();
pd->set_initialized(); pd->set_initialized();
T * pt2 = static_cast< T* >( pv ); T * pt2 = static_cast< T* >( pv );
@@ -241,7 +338,7 @@ template< class T, class A, class Arg1, class... Args > typename boost::detail::
return boost::shared_ptr< T >( pt, pt2 ); return boost::shared_ptr< T >( pt, pt2 );
} }
#elif !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
// For example MSVC 10.0 // For example MSVC 10.0
@@ -695,7 +792,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a,
return boost::shared_ptr< T >( pt, pt2 ); return boost::shared_ptr< T >( pt, pt2 );
} }
#else #else // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
// C++03 version // C++03 version
@@ -1023,7 +1120,9 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a,
return boost::shared_ptr< T >( pt, pt2 ); return boost::shared_ptr< T >( pt, pt2 );
} }
#endif #endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
#endif // !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
#undef BOOST_SP_MSD #undef BOOST_SP_MSD

View File

@@ -0,0 +1,15 @@
/*
* Copyright (c) 2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_MAKE_UNIQUE_HPP
#define BOOST_SMART_PTR_MAKE_UNIQUE_HPP
#include <boost/smart_ptr/make_unique_array.hpp>
#include <boost/smart_ptr/make_unique_object.hpp>
#endif

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_MAKE_UNIQUE_ARRAY_HPP
#define BOOST_SMART_PTR_MAKE_UNIQUE_ARRAY_HPP
#include <boost/smart_ptr/detail/up_if_array.hpp>
#include <boost/smart_ptr/detail/array_traits.hpp>
namespace boost {
template<typename T>
inline typename boost::detail::up_if_array<T>::type
make_unique(std::size_t size) {
typedef typename boost::detail::array_inner<T>::type U;
return std::unique_ptr<T>(new U[size]());
}
template<typename T>
inline typename boost::detail::up_if_array<T>::type
make_unique_noinit(std::size_t size) {
typedef typename boost::detail::array_inner<T>::type U;
return std::unique_ptr<T>(new U[size]);
}
}
#endif

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_MAKE_UNIQUE_OBJECT_HPP
#define BOOST_SMART_PTR_MAKE_UNIQUE_OBJECT_HPP
#include <boost/config.hpp>
#include <boost/smart_ptr/detail/up_if_not_array.hpp>
#include <utility>
namespace boost {
template<typename T>
inline typename boost::detail::up_if_not_array<T>::type
make_unique() {
return std::unique_ptr<T>(new T());
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<typename T, typename... Args>
inline typename boost::detail::up_if_not_array<T>::type
make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
#endif
template<typename T>
inline typename boost::detail::up_if_not_array<T>::type
make_unique(T&& value) {
return std::unique_ptr<T>(new T(std::move(value)));
}
template<typename T>
inline typename boost::detail::up_if_not_array<T>::type
make_unique_noinit() {
return std::unique_ptr<T>(new T);
}
}
#endif

View File

@@ -16,10 +16,6 @@
#include <boost/config.hpp> // for broken compiler workarounds #include <boost/config.hpp> // for broken compiler workarounds
#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
#include <boost/smart_ptr/detail/shared_array_nmt.hpp>
#else
#include <memory> // TR1 cyclic inclusion fix #include <memory> // TR1 cyclic inclusion fix
#include <boost/assert.hpp> #include <boost/assert.hpp>
@@ -61,6 +57,14 @@ public:
{ {
} }
#if !defined( BOOST_NO_CXX11_NULLPTR )
shared_array( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn()
{
}
#endif
template<class Y> template<class Y>
explicit shared_array( Y * p ): px( p ), pn( p, checked_array_deleter<Y>() ) explicit shared_array( Y * p ): px( p ), pn( p, checked_array_deleter<Y>() )
{ {
@@ -285,6 +289,4 @@ template< class D, class T > D * get_deleter( shared_array<T> const & p )
} // namespace boost } // namespace boost
#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
#endif // #ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED #endif // #ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED

View File

@@ -16,10 +16,6 @@
#include <boost/config.hpp> // for broken compiler workarounds #include <boost/config.hpp> // for broken compiler workarounds
#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
#include <boost/smart_ptr/detail/shared_ptr_nmt.hpp>
#else
// In order to avoid circular dependencies with Boost.TR1 // In order to avoid circular dependencies with Boost.TR1
// we make sure that our include of <memory> doesn't try to // we make sure that our include of <memory> doesn't try to
// pull in the TR1 headers: that's why we use this header // pull in the TR1 headers: that's why we use this header
@@ -1030,6 +1026,4 @@ template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOO
} // namespace boost } // namespace boost
#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
#endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED #endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED

View File

@@ -1,15 +1,18 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>Smart Pointers</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="refresh" content="0; URL=smart_ptr.htm"> <meta http-equiv="refresh" content="0; URL=smart_ptr.htm">
</head> </head>
<body> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
Automatic redirection failed, please go to Automatic redirection failed, please go to
<a href="smart_ptr.htm">smart_ptr.htm</a>. <a href="smart_ptr.htm">smart_ptr.htm</a>.
</body> </body>
</html> </html>
<!-- <!--
<09> Copyright Beman Dawes, 2001 (C) Copyright Beman Dawes, 2001
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0.
See accompanying file LICENSE_1_0.txt or copy at See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt http://www.boost.org/LICENSE_1_0.txt
--> -->

View File

@@ -1,299 +1,320 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>intrusive_ptr</title> <title>intrusive_ptr</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> </head>
<body text="#000000" bgColor="#ffffff"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle" <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
border="0"></A>intrusive_ptr class template</h1> width="277" align="middle" border="0">intrusive_ptr class template</h1>
<p> <p>
<A href="#Introduction">Introduction</A><br> <a href="#Introduction">Introduction</a><br>
<A href="#Synopsis">Synopsis</A><br> <a href="#Synopsis">Synopsis</a><br>
<A href="#Members">Members</A><br> <a href="#Members">Members</a><br>
<A href="#functions">Free Functions</A><br> <a href="#functions">Free Functions</a><br>
</p> </p>
<h2><a name="Introduction">Introduction</a></h2> <h2><a name="Introduction">Introduction</a></h2>
<p>The <b>intrusive_ptr</b> class template stores a pointer to an object with an <p>The <code>intrusive_ptr</code> class template stores a pointer to an object with an
embedded reference count. Every new <b>intrusive_ptr</b> instance increments embedded reference count. Every new <code>intrusive_ptr</code> instance increments
the reference count by using an unqualified call to the function <STRONG>intrusive_ptr_add_ref</STRONG>, the reference count by using an unqualified call to the function <code>intrusive_ptr_add_ref</code>,
passing it the pointer as an argument. Similarly, when an <STRONG>intrusive_ptr</STRONG> passing it the pointer as an argument. Similarly, when an <code>intrusive_ptr</code>
is destroyed, it calls <STRONG>intrusive_ptr_release</STRONG>; this function is is destroyed, it calls <code>intrusive_ptr_release</code>; this function is
responsible for destroying the object when its reference count drops to zero. responsible for destroying the object when its reference count drops to zero.
The user is expected to provide suitable definitions of these two functions. On The user is expected to provide suitable definitions of these two functions. On
compilers that support argument-dependent lookup, <STRONG>intrusive_ptr_add_ref</STRONG> compilers that support argument-dependent lookup, <code>intrusive_ptr_add_ref</code>
and <STRONG>intrusive_ptr_release</STRONG> should be defined in the namespace and <code>intrusive_ptr_release</code> should be defined in the namespace
that corresponds to their parameter; otherwise, the definitions need to go in that corresponds to their parameter; otherwise, the definitions need to go in
namespace <STRONG>boost</STRONG>. The library provides a helper base class template namespace <code>boost</code>. The library provides a helper base class template
<STRONG><a href="intrusive_ref_counter.html">intrusive_ref_counter</a></STRONG> which may <code><a href="intrusive_ref_counter.html">intrusive_ref_counter</a></code> which may
help adding support for <STRONG>intrusive_ptr</STRONG> to user&apos;s types.</p> help adding support for <code>intrusive_ptr</code> to user types.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed <p>The class template is parameterized on <code>T</code>, the type of the object pointed
to. <STRONG>intrusive_ptr&lt;T&gt;</STRONG> can be implicitly converted to <STRONG>intrusive_ptr&lt;U&gt;</STRONG> to. <code>intrusive_ptr&lt;T&gt;</code> can be implicitly converted to <code>intrusive_ptr&lt;U&gt;</code>
whenever <STRONG>T*</STRONG> can be implicitly converted to <STRONG>U*</STRONG>.</p> whenever <code>T*</code> can be implicitly converted to <code>U*</code>.</p>
<P>The main reasons to use <STRONG>intrusive_ptr</STRONG> are:</P> <p>The main reasons to use <code>intrusive_ptr</code> are:</p>
<UL> <ul>
<LI> <li>
Some existing frameworks or OSes provide objects with embedded reference Some existing frameworks or OSes provide objects with embedded reference
counts; counts;</li>
<LI> <li>
The memory footprint of <STRONG>intrusive_ptr</STRONG> The memory footprint of <code>intrusive_ptr</code>
is the same as the corresponding raw pointer; is the same as the corresponding raw pointer;</li>
<LI> <li>
<STRONG>intrusive_ptr&lt;T&gt;</STRONG> can be constructed from an arbitrary <code>intrusive_ptr&lt;T&gt;</code> can be constructed from an arbitrary
raw pointer of type <STRONG>T *</STRONG>.</LI></UL> raw pointer of type <code>T *</code>.</li></ul>
<P>As a general rule, if it isn't obvious whether <STRONG>intrusive_ptr</STRONG> better <p>As a general rule, if it isn't obvious whether <code>intrusive_ptr</code> better
fits your needs than <STRONG>shared_ptr</STRONG>, try a <STRONG>shared_ptr</STRONG>-based fits your needs than <code>shared_ptr</code>, try a <code>shared_ptr</code>-based
design first.</P> design first.</p>
<h2><a name="Synopsis">Synopsis</a></h2> <h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost { <pre>namespace boost {
template&lt;class T&gt; class intrusive_ptr { template&lt;class T&gt; class intrusive_ptr {
public: public:
typedef T <A href="#element_type" >element_type</A>; typedef T <a href="#element_type" >element_type</a>;
<A href="#constructors" >intrusive_ptr</A>(); // never throws <a href="#constructors" >intrusive_ptr</a>(); // never throws
<A href="#constructors" >intrusive_ptr</A>(T * p, bool add_ref = true); <a href="#constructors" >intrusive_ptr</a>(T * p, bool add_ref = true);
<A href="#constructors" >intrusive_ptr</A>(intrusive_ptr const &amp; r); <a href="#constructors" >intrusive_ptr</a>(intrusive_ptr const &amp; r);
template&lt;class Y&gt; <A href="#constructors" >intrusive_ptr</A>(intrusive_ptr&lt;Y&gt; const &amp; r); template&lt;class Y&gt; <a href="#constructors" >intrusive_ptr</a>(intrusive_ptr&lt;Y&gt; const &amp; r);
<A href="#destructor" >~intrusive_ptr</A>(); <a href="#destructor" >~intrusive_ptr</a>();
intrusive_ptr &amp; <A href="#assignment" >operator=</A>(intrusive_ptr const &amp; r); intrusive_ptr &amp; <a href="#assignment" >operator=</a>(intrusive_ptr const &amp; r);
template&lt;class Y&gt; intrusive_ptr &amp; <A href="#assignment" >operator=</A>(intrusive_ptr&lt;Y&gt; const &amp; r); template&lt;class Y&gt; intrusive_ptr &amp; <a href="#assignment" >operator=</a>(intrusive_ptr&lt;Y&gt; const &amp; r);
intrusive_ptr &amp; <A href="#assignment" >operator=</A>(T * r); intrusive_ptr &amp; <a href="#assignment" >operator=</a>(T * r);
void <a href="#reset" >reset</a>(); void <a href="#reset" >reset</a>();
void <a href="#reset" >reset</a>(T * r); void <a href="#reset" >reset</a>(T * r);
void <a href="#reset" >reset</a>(T * r, bool add_ref);
T &amp; <A href="#indirection" >operator*</A>() const; // never throws T &amp; <a href="#indirection" >operator*</a>() const; // never throws
T * <A href="#indirection" >operator-&gt;</A>() const; // never throws T * <a href="#indirection" >operator-&gt;</a>() const; // never throws
T * <A href="#get" >get</A>() const; // never throws T * <a href="#get" >get</a>() const; // never throws
T * <a href="#detach" >detach</a>(); // never throws
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws operator <a href="#conversions" ><i>unspecified-bool-type</i></a>() const; // never throws
void <A href="#swap" >swap</A>(intrusive_ptr &amp; b); // never throws void <a href="#swap" >swap</a>(intrusive_ptr &amp; b); // never throws
}; };
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
bool <A href="#comparison" >operator==</A>(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws bool <a href="#comparison" >operator==</a>(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
bool <A href="#comparison" >operator!=</A>(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws bool <a href="#comparison" >operator!=</a>(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class T&gt; template&lt;class T&gt;
bool <A href="#comparison" >operator==</A>(intrusive_ptr&lt;T&gt; const &amp; a, T * b); // never throws bool <a href="#comparison" >operator==</a>(intrusive_ptr&lt;T&gt; const &amp; a, T * b); // never throws
template&lt;class T&gt; template&lt;class T&gt;
bool <A href="#comparison" >operator!=</A>(intrusive_ptr&lt;T&gt; const &amp; a, T * b); // never throws bool <a href="#comparison" >operator!=</a>(intrusive_ptr&lt;T&gt; const &amp; a, T * b); // never throws
template&lt;class T&gt; template&lt;class T&gt;
bool <A href="#comparison" >operator==</A>(T * a, intrusive_ptr&lt;T&gt; const &amp; b); // never throws bool <a href="#comparison" >operator==</a>(T * a, intrusive_ptr&lt;T&gt; const &amp; b); // never throws
template&lt;class T&gt; template&lt;class T&gt;
bool <A href="#comparison" >operator!=</A>(T * a, intrusive_ptr&lt;T&gt; const &amp; b); // never throws bool <a href="#comparison" >operator!=</a>(T * a, intrusive_ptr&lt;T&gt; const &amp; b); // never throws
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
bool <A href="#comparison" >operator&lt;</A>(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws bool <a href="#comparison" >operator&lt;</a>(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class T&gt; void <A href="#free-swap" >swap</A>(intrusive_ptr&lt;T&gt; &amp; a, intrusive_ptr&lt;T&gt; &amp; b); // never throws template&lt;class T&gt; void <a href="#free-swap" >swap</a>(intrusive_ptr&lt;T&gt; &amp; a, intrusive_ptr&lt;T&gt; &amp; b); // never throws
template&lt;class T&gt; T * <A href="#get_pointer" >get_pointer</A>(intrusive_ptr&lt;T&gt; const &amp; p); // never throws template&lt;class T&gt; T * <a href="#get_pointer" >get_pointer</a>(intrusive_ptr&lt;T&gt; const &amp; p); // never throws
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; <A href="#static_pointer_cast" >static_pointer_cast</A>(intrusive_ptr&lt;U&gt; const &amp; r); // never throws intrusive_ptr&lt;T&gt; <a href="#static_pointer_cast" >static_pointer_cast</a>(intrusive_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; <A href="#const_pointer_cast" >const_pointer_cast</A>(intrusive_ptr&lt;U&gt; const &amp; r); // never throws intrusive_ptr&lt;T&gt; <a href="#const_pointer_cast" >const_pointer_cast</a>(intrusive_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; <A href="#dynamic_pointer_cast" >dynamic_pointer_cast</A>(intrusive_ptr&lt;U&gt; const &amp; r); // never throws intrusive_ptr&lt;T&gt; <a href="#dynamic_pointer_cast" >dynamic_pointer_cast</a>(intrusive_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class E, class T, class Y&gt; template&lt;class E, class T, class Y&gt;
std::basic_ostream&lt;E, T&gt; &amp; <A href="#insertion-operator" >operator&lt;&lt;</A> (std::basic_ostream&lt;E, T&gt; &amp; os, intrusive_ptr&lt;Y&gt; const &amp; p); std::basic_ostream&lt;E, T&gt; &amp; <a href="#insertion-operator" >operator&lt;&lt;</a> (std::basic_ostream&lt;E, T&gt; &amp; os, intrusive_ptr&lt;Y&gt; const &amp; p);
}</pre> }</pre>
<h2><a name="Members">Members</a></h2> <h2><a name="Members">Members</a></h2>
<h3><a name="element_type">element_type</a></h3> <h3><a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre> <pre>typedef T element_type;</pre>
<blockquote> <blockquote>
<p>Provides the type of the template parameter T.</p> <p>Provides the type of the template parameter <code>T</code>.</p>
</blockquote> </blockquote>
<h3><a name="constructors">constructors</a></h3> <h3><a name="constructors">constructors</a></h3>
<pre>intrusive_ptr(); // never throws</pre> <pre>intrusive_ptr(); // never throws</pre>
<blockquote> <blockquote>
<p><b>Postconditions:</b> <code>get() == 0</code>.</p> <p><b>Postconditions:</b> <code>get() == 0</code>.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
</blockquote> </blockquote>
<pre>intrusive_ptr(T * p, bool add_ref = true);</pre> <pre>intrusive_ptr(T * p, bool add_ref = true);</pre>
<blockquote> <blockquote>
<p><b>Effects:</b> <code>if(p != 0 &amp;&amp; add_ref) intrusive_ptr_add_ref(p);</code>.</p> <p><b>Effects:</b> <code>if(p != 0 &amp;&amp; add_ref) intrusive_ptr_add_ref(p);</code>.</p>
<p><b>Postconditions:</b> <code>get() == p</code>.</p> <p><b>Postconditions:</b> <code>get() == p</code>.</p>
</blockquote> </blockquote>
<pre>intrusive_ptr(intrusive_ptr const &amp; r); <pre>intrusive_ptr(intrusive_ptr const &amp; r);
template&lt;class Y&gt; intrusive_ptr(intrusive_ptr&lt;Y&gt; const &amp; r);</pre> template&lt;class Y&gt; intrusive_ptr(intrusive_ptr&lt;Y&gt; const &amp; r);</pre>
<blockquote> <blockquote>
<p><b>Effects:</b> <code>if(r.get() != 0) intrusive_ptr_add_ref(r.get());</code>.</p> <p><b>Effects:</b> <code>if(r.get() != 0) intrusive_ptr_add_ref(r.get());</code>.</p>
<p><b>Postconditions:</b> <code>get() == r.get()</code>.</p> <p><b>Postconditions:</b> <code>get() == r.get()</code>.</p>
</blockquote> </blockquote>
<h3><a name="destructor">destructor</a></h3> <h3><a name="destructor">destructor</a></h3>
<pre>~intrusive_ptr();</pre> <pre>~intrusive_ptr();</pre>
<BLOCKQUOTE> <blockquote>
<P><B>Effects:</B> <code>if(get() != 0) intrusive_ptr_release(get());</code>.</P> <p><b>Effects:</b> <code>if(get() != 0) intrusive_ptr_release(get());</code>.</p>
</BLOCKQUOTE> </blockquote>
<H3><a name="assignment">assignment</a></H3> <h3><a name="assignment">assignment</a></h3>
<pre>intrusive_ptr &amp; operator=(intrusive_ptr const &amp; r); <pre>intrusive_ptr &amp; operator=(intrusive_ptr const &amp; r);
template&lt;class Y&gt; intrusive_ptr &amp; operator=(intrusive_ptr&lt;Y&gt; const &amp; r); template&lt;class Y&gt; intrusive_ptr &amp; operator=(intrusive_ptr&lt;Y&gt; const &amp; r);
intrusive_ptr &amp; operator=(T * r);</pre> intrusive_ptr &amp; operator=(T * r);</pre>
<BLOCKQUOTE> <blockquote>
<P><B>Effects:</B> Equivalent to <code>intrusive_ptr(r).swap(*this)</code>.</P> <p><b>Effects:</b> Equivalent to <code>intrusive_ptr(r).swap(*this)</code>.</p>
<P><B>Returns:</B> <code>*this</code>.</P> <p><b>Returns:</b> <code>*this</code>.</p>
</BLOCKQUOTE> </blockquote>
<H3><a name="reset">reset</a></H3> <h3><a name="reset">reset</a></h3>
<pre>void reset();</pre> <pre>void reset();</pre>
<BLOCKQUOTE> <blockquote>
<P><B>Effects:</B> Equivalent to <code>intrusive_ptr().swap(*this)</code>.</P> <p><b>Effects:</b> Equivalent to <code>intrusive_ptr().swap(*this)</code>.</p>
</BLOCKQUOTE> </blockquote>
<pre>void reset(T * r);</pre> <pre>void reset(T * r);</pre>
<BLOCKQUOTE> <blockquote>
<P><B>Effects:</B> Equivalent to <code>intrusive_ptr(r).swap(*this)</code>.</P> <p><b>Effects:</b> Equivalent to <code>intrusive_ptr(r).swap(*this)</code>.</p>
</BLOCKQUOTE> </blockquote>
<h3><a name="indirection">indirection</a></h3> <pre>void reset(T * r, bool add_ref);</pre>
<pre>T &amp; operator*() const; // never throws</pre> <blockquote>
<blockquote> <p><b>Effects:</b> Equivalent to <code>intrusive_ptr(r, add_ref).swap(*this)</code>.</p>
<p><b>Requirements:</b> <code>get() != 0</code>.</p> </blockquote>
<p><b>Returns:</b> <code>*get()</code>.</p> <h3><a name="indirection">indirection</a></h3>
<p><b>Throws:</b> nothing.</p> <pre>T &amp; operator*() const; // never throws</pre>
</blockquote> <blockquote>
<pre>T * operator-&gt;() const; // never throws</pre> <p><b>Requirements:</b> <code>get() != 0</code>.</p>
<blockquote> <p><b>Returns:</b> <code>*get()</code>.</p>
<p><b>Requirements:</b> <code>get() != 0</code>.</p> <p><b>Throws:</b> nothing.</p>
<p><b>Returns:</b> <code>get()</code>.</p> </blockquote>
<p><b>Throws:</b> nothing.</p> <pre>T * operator-&gt;() const; // never throws</pre>
</blockquote> <blockquote>
<h3><a name="get">get</a></h3> <p><b>Requirements:</b> <code>get() != 0</code>.</p>
<pre>T * get() const; // never throws</pre> <p><b>Returns:</b> <code>get()</code>.</p>
<blockquote> <p><b>Throws:</b> nothing.</p>
<p><b>Returns:</b> the stored pointer.</p> </blockquote>
<p><b>Throws:</b> nothing.</p> <h3><a name="get">get</a></h3>
</blockquote> <pre>T * get() const; // never throws</pre>
<h3><a name="conversions">conversions</a></h3> <blockquote>
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre> <p><b>Returns:</b> the stored pointer.</p>
<blockquote> <p><b>Throws:</b> nothing.</p>
<p><b>Returns:</b> an unspecified value that, when used in boolean contexts, is </blockquote>
equivalent to <code>get() != 0</code>.</p> <h3><a name="detach">detach</a></h3>
<p><b>Throws:</b> nothing.</p> <pre>T * detach(); // never throws</pre>
<P><B>Notes:</B> This conversion operator allows <b>intrusive_ptr</b> objects to be <blockquote>
used in boolean contexts, like <code>if (p &amp;&amp; p-&gt;valid()) {}</code>. <p><b>Returns:</b> the stored pointer.</p>
The actual target type is typically a pointer to a member function, avoiding <p><b>Throws:</b> nothing.</p>
many of the implicit conversion pitfalls.</P> <p><b>Postconditions:</b> <code>get() == 0</code>.</p>
</blockquote> <p><b>Notes:</b> The returned pointer has an elevated reference count. This
<h3><a name="swap">swap</a></h3> allows conversion of an <code>intrusive_ptr</code> back to a raw pointer,
<pre>void swap(intrusive_ptr &amp; b); // never throws</pre> without the performance overhead of acquiring and dropping an extra
<blockquote> reference. It can be viewed as the complement of the
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p> non-reference-incrementing constructor.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Caution:</b> Using <code>detach</code> escapes the safety of automatic
</blockquote> reference counting provided by <code>intrusive_ptr</code>. It should
<h2><a name="functions">Free Functions</a></h2> by used only where strictly necessary (such as when interfacing to an
<h3><a name="comparison">comparison</a></h3> existing API), and when the implications are thoroughly understood.</p>
<pre>template&lt;class T, class U&gt; </blockquote>
<h3><a name="conversions">conversions</a></h3>
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> an unspecified value that, when used in boolean contexts, is
equivalent to <code>get() != 0</code>.</p>
<p><b>Throws:</b> nothing.</p>
<p><b>Notes:</b> This conversion operator allows <code>intrusive_ptr</code> objects to be
used in boolean contexts, like <code>if (p &amp;&amp; p-&gt;valid()) {}</code>.
The actual target type is typically a pointer to a member function, avoiding
many of the implicit conversion pitfalls.</p>
</blockquote>
<h3><a name="swap">swap</a></h3>
<pre>void swap(intrusive_ptr &amp; b); // never throws</pre>
<blockquote>
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h2><a name="functions">Free Functions</a></h2>
<h3><a name="comparison">comparison</a></h3>
<pre>template&lt;class T, class U&gt;
bool operator==(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre> bool operator==(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote> <blockquote>
<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p> <p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
</blockquote> </blockquote>
<pre>template&lt;class T, class U&gt; <pre>template&lt;class T, class U&gt;
bool operator!=(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre> bool operator!=(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote> <blockquote>
<p><b>Returns:</b> <code>a.get() != b.get()</code>.</p> <p><b>Returns:</b> <code>a.get() != b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
</blockquote> </blockquote>
<pre>template&lt;class T, class U&gt; <pre>template&lt;class T, class U&gt;
bool operator==(intrusive_ptr&lt;T&gt; const &amp; a, U * b); // never throws</pre> bool operator==(intrusive_ptr&lt;T&gt; const &amp; a, U * b); // never throws</pre>
<blockquote> <blockquote>
<p><b>Returns:</b> <code>a.get() == b</code>.</p> <p><b>Returns:</b> <code>a.get() == b</code>.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
</blockquote> </blockquote>
<pre>template&lt;class T, class U&gt; <pre>template&lt;class T, class U&gt;
bool operator!=(intrusive_ptr&lt;T&gt; const &amp; a, U * b); // never throws</pre> bool operator!=(intrusive_ptr&lt;T&gt; const &amp; a, U * b); // never throws</pre>
<blockquote> <blockquote>
<p><b>Returns:</b> <code>a.get() != b</code>.</p> <p><b>Returns:</b> <code>a.get() != b</code>.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
</blockquote> </blockquote>
<pre>template&lt;class T, class U&gt; <pre>template&lt;class T, class U&gt;
bool operator==(T * a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre> bool operator==(T * a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote> <blockquote>
<p><b>Returns:</b> <code>a == b.get()</code>.</p> <p><b>Returns:</b> <code>a == b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
</blockquote> </blockquote>
<pre>template&lt;class T, class U&gt; <pre>template&lt;class T, class U&gt;
bool operator!=(T * a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre> bool operator!=(T * a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote> <blockquote>
<p><b>Returns:</b> <code>a != b.get()</code>.</p> <p><b>Returns:</b> <code>a != b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
</blockquote> </blockquote>
<pre>template&lt;class T, class U&gt; <pre>template&lt;class T, class U&gt;
bool operator&lt;(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre> bool operator&lt;(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote> <blockquote>
<p><b>Returns:</b> <code>std::less&lt;T *&gt;()(a.get(), b.get())</code>.</p> <p><b>Returns:</b> <code>std::less&lt;T *&gt;()(a.get(), b.get())</code>.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> Allows <STRONG>intrusive_ptr</STRONG> objects to be used as keys <p><b>Notes:</b> Allows <code>intrusive_ptr</code> objects to be used as keys
in associative containers.</P> in associative containers.</p>
</blockquote> </blockquote>
<h3><a name="free-swap">swap</a></h3> <h3><a name="free-swap">swap</a></h3>
<pre>template&lt;class T&gt; <pre>template&lt;class T&gt;
void swap(intrusive_ptr&lt;T&gt; &amp; a, intrusive_ptr&lt;T&gt; &amp; b); // never throws</pre> void swap(intrusive_ptr&lt;T&gt; &amp; a, intrusive_ptr&lt;T&gt; &amp; b); // never throws</pre>
<BLOCKQUOTE> <blockquote>
<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P> <p><b>Effects:</b> Equivalent to <code>a.swap(b)</code>.</p>
<P><B>Throws:</B> nothing.</P> <p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to <p><b>Notes:</b> Matches the interface of <code>std::swap</code>. Provided as an aid to
generic programming.</P> generic programming.</p>
</BLOCKQUOTE> </blockquote>
<h3><a name="get_pointer">get_pointer</a></h3> <h3><a name="get_pointer">get_pointer</a></h3>
<pre>template&lt;class T&gt; <pre>template&lt;class T&gt;
T * get_pointer(intrusive_ptr&lt;T&gt; const &amp; p); // never throws</pre> T * get_pointer(intrusive_ptr&lt;T&gt; const &amp; p); // never throws</pre>
<BLOCKQUOTE> <blockquote>
<P><B>Returns:</B> <code>p.get()</code>.</P> <p><b>Returns:</b> <code>p.get()</code>.</p>
<P><B>Throws:</B> nothing.</P> <p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> Provided as an aid to generic programming. Used by <A href="../bind/mem_fn.html"> <p><b>Notes:</b> Provided as an aid to generic programming. Used by <a href="../bind/mem_fn.html">
mem_fn</A>.</P> mem_fn</a>.</p>
</BLOCKQUOTE> </blockquote>
<h3><a name="static_pointer_cast">static_pointer_cast</a></h3> <h3><a name="static_pointer_cast">static_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt; <pre>template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; static_pointer_cast(intrusive_ptr&lt;U&gt; const &amp; r); // never throws</pre> intrusive_ptr&lt;T&gt; static_pointer_cast(intrusive_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE> <blockquote>
<P><B>Returns:</B> <code>intrusive_ptr&lt;T&gt;(static_cast&lt;T*&gt;(r.get()))</code>.</P> <p><b>Returns:</b> <code>intrusive_ptr&lt;T&gt;(static_cast&lt;T*&gt;(r.get()))</code>.</p>
<P><B>Throws:</B> nothing.</P> <p><b>Throws:</b> nothing.</p>
</BLOCKQUOTE> </blockquote>
<h3><a name="const_pointer_cast">const_pointer_cast</a></h3> <h3><a name="const_pointer_cast">const_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt; <pre>template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; const_pointer_cast(intrusive_ptr&lt;U&gt; const &amp; r); // never throws</pre> intrusive_ptr&lt;T&gt; const_pointer_cast(intrusive_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE> <blockquote>
<P><B>Returns:</B> <code>intrusive_ptr&lt;T&gt;(const_cast&lt;T*&gt;(r.get()))</code>.</P> <p><b>Returns:</b> <code>intrusive_ptr&lt;T&gt;(const_cast&lt;T*&gt;(r.get()))</code>.</p>
<P><B>Throws:</B> nothing.</P> <p><b>Throws:</b> nothing.</p>
</BLOCKQUOTE> </blockquote>
<h3><a name="dynamic_pointer_cast">dynamic_pointer_cast</a></h3> <h3><a name="dynamic_pointer_cast">dynamic_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt; <pre>template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; dynamic_pointer_cast(intrusive_ptr&lt;U&gt; const &amp; r);</pre> intrusive_ptr&lt;T&gt; dynamic_pointer_cast(intrusive_ptr&lt;U&gt; const &amp; r);</pre>
<BLOCKQUOTE> <blockquote>
<P><B>Returns:</B> <code>intrusive_ptr&lt;T&gt;(dynamic_cast&lt;T*&gt;(r.get()))</code>.</P> <p><b>Returns:</b> <code>intrusive_ptr&lt;T&gt;(dynamic_cast&lt;T*&gt;(r.get()))</code>.</p>
<P><B>Throws:</B> nothing.</P> <p><b>Throws:</b> nothing.</p>
</BLOCKQUOTE> </blockquote>
<h3><a name="insertion-operator">operator&lt;&lt;</a></h3> <h3><a name="insertion-operator">operator&lt;&lt;</a></h3>
<pre>template&lt;class E, class T, class Y&gt; <pre>template&lt;class E, class T, class Y&gt;
std::basic_ostream&lt;E, T&gt; &amp; operator&lt;&lt; (std::basic_ostream&lt;E, T&gt; &amp; os, intrusive_ptr&lt;Y&gt; const &amp; p);</pre> std::basic_ostream&lt;E, T&gt; &amp; operator&lt;&lt; (std::basic_ostream&lt;E, T&gt; &amp; os, intrusive_ptr&lt;Y&gt; const &amp; p);</pre>
<BLOCKQUOTE> <blockquote>
<p><STRONG>Effects:</STRONG> <code>os &lt;&lt; p.get();</code>.</p> <p><b>Effects:</b> <code>os &lt;&lt; p.get();</code>.</p>
<P><B>Returns:</B> <code>os</code>.</P> <p><b>Returns:</b> <code>os</code>.</p>
</BLOCKQUOTE> </blockquote>
<hr> <hr>
<p> <p>$Date$</p>
$Date$</p> <p>
<p> <small>Copyright &copy; 2003-2005, 2013 Peter Dimov. Distributed under the Boost Software License, Version
<small>Copyright <20> 2003-2005 Peter Dimov. Distributed under the Boost Software License, Version 1.0. See accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>.</small></p>
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p> </body>
</body>
</html> </html>

View File

@@ -1,12 +1,12 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>intrusive_ref_counter</title> <title>intrusive_ref_counter</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> </head>
<body text="#000000" bgColor="#ffffff"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle" <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
border="0"></A>basic_intrusive_ref_counter class template</h1> width="277" align="middle" border="0">basic_intrusive_ref_counter class template</h1>
<p> <p>
<A href="#Introduction">Introduction</A><br> <A href="#Introduction">Introduction</A><br>
<A href="#Synopsis">Synopsis</A><br> <A href="#Synopsis">Synopsis</A><br>
@@ -14,11 +14,11 @@
</p> </p>
<h2><a name="Introduction">Introduction</a></h2> <h2><a name="Introduction">Introduction</a></h2>
<p>The <STRONG>intrusive_ref_counter</STRONG> class template implements a reference counter for a derived <p>The <STRONG>intrusive_ref_counter</STRONG> class template implements a reference counter for a derived
user&apos;s class that is intended to be used with <STRONG><a href="intrusive_ptr.html">intrusive_ptr</a></STRONG>. user's class that is intended to be used with <STRONG><a href="intrusive_ptr.html">intrusive_ptr</a></STRONG>.
The base class has associated <STRONG>intrusive_ptr_add_ref</STRONG> and <STRONG>intrusive_ptr_release</STRONG> functions The base class has associated <STRONG>intrusive_ptr_add_ref</STRONG> and <STRONG>intrusive_ptr_release</STRONG> functions
which modify the reference counter as needed and destroy the user's object when the counter drops to zero.</p> which modify the reference counter as needed and destroy the user's object when the counter drops to zero.</p>
<p>The class template is parameterized on <STRONG>DerivedT</STRONG> and <STRONG>CounterPolicyT</STRONG> parameters. <p>The class template is parameterized on <STRONG>DerivedT</STRONG> and <STRONG>CounterPolicyT</STRONG> parameters.
The first parameter is the user&apos;s class that derives from <STRONG>intrusive_ref_counter</STRONG>. This type The first parameter is the user's class that derives from <STRONG>intrusive_ref_counter</STRONG>. This type
is needed in order to destroy the object correctly when there are no references to it left.</p> is needed in order to destroy the object correctly when there are no references to it left.</p>
<p>The second parameter is a policy that defines the nature of the reference counter. <p>The second parameter is a policy that defines the nature of the reference counter.
Boost.SmartPtr provides two such policies: <STRONG>thread_unsafe_counter</STRONG> and <STRONG>thread_safe_counter</STRONG>. The former Boost.SmartPtr provides two such policies: <STRONG>thread_unsafe_counter</STRONG> and <STRONG>thread_safe_counter</STRONG>. The former
@@ -85,11 +85,10 @@
<P><B>Notes:</B> The returned value may not be actual in multi-threaded applications.</P> <P><B>Notes:</B> The returned value may not be actual in multi-threaded applications.</P>
</BLOCKQUOTE> </BLOCKQUOTE>
<hr> <hr>
<p>$Date$</p>
<p> <p>
$Date$</p> <small>Copyright &copy; 2013 Andrey Semashev. Distributed under the Boost Software License, Version
<p> 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
<small>Copyright <20> 2013 Andrey Semashev. Distributed under the Boost Software License, Version copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body> </body>
</html> </html>

View File

@@ -1,37 +1,38 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>make_shared and allocate_shared</title> <title>make_shared and allocate_shared</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> </head>
<body text="#000000" bgColor="#ffffff"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle" <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
border="0"></A>make_shared and allocate_shared function templates</h1> width="277" align="middle" border="0">make_shared and allocate_shared
<p><A href="#Introduction">Introduction</A><br> function templates</h1>
<A href="#Synopsis">Synopsis</A><br> <p><A href="#Introduction">Introduction</A><br>
<A href="#functions">Free Functions</A><br> <A href="#Synopsis">Synopsis</A><br>
<A href="#example">Example</A><br> <A href="#functions">Free Functions</A><br>
<h2><a name="Introduction">Introduction</a></h2> <A href="#example">Example</A><br>
<p>Consistent use of <a href="shared_ptr.htm"><code>shared_ptr</code></a> <h2><a name="Introduction">Introduction</a></h2>
can eliminate the need to use an explicit <code>delete</code>, <p>Consistent use of <a href="shared_ptr.htm"><code>shared_ptr</code></a>
but alone it provides no support in avoiding explicit <code>new</code>. can eliminate the need to use an explicit <code>delete</code>,
There have been repeated requests from users for a factory function that creates but alone it provides no support in avoiding explicit <code>new</code>.
an object of a given type and returns a <code>shared_ptr</code> to it. There have been repeated requests from users for a factory function that creates
Besides convenience and style, such a function is also exception safe and an object of a given type and returns a <code>shared_ptr</code> to it.
considerably faster because it can use a single allocation for both the object Besides convenience and style, such a function is also exception safe and
and its corresponding control block, eliminating a significant portion of considerably faster because it can use a single allocation for both the object
<code>shared_ptr</code>'s construction overhead. and its corresponding control block, eliminating a significant portion of
This eliminates one of the major efficiency complaints about <code>shared_ptr</code>. <code>shared_ptr</code>'s construction overhead.
</p> This eliminates one of the major efficiency complaints about <code>shared_ptr</code>.
<p>The header file &lt;boost/make_shared.hpp&gt; provides a family of overloaded function templates, </p>
<code>make_shared</code> and <code>allocate_shared</code>, to address this need. <p>The header file &lt;boost/make_shared.hpp&gt; provides a family of overloaded function templates,
<code>make_shared</code> uses the global operator <code>new</code> to allocate memory, <code>make_shared</code> and <code>allocate_shared</code>, to address this need.
whereas <code>allocate_shared</code> uses an user-supplied allocator, allowing finer control.</p> <code>make_shared</code> uses the global operator <code>new</code> to allocate memory,
<p> whereas <code>allocate_shared</code> uses an user-supplied allocator, allowing finer control.</p>
The rationale for choosing the name <code>make_shared</code> is that the expression <p>
<code>make_shared&lt;Widget&gt;()</code> can be read aloud and conveys the intended meaning.</p> The rationale for choosing the name <code>make_shared</code> is that the expression
<h2><a name="Synopsis">Synopsis</a></h2> <code>make_shared&lt;Widget&gt;()</code> can be read aloud and conveys the intended meaning.</p>
<pre>namespace boost { <h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost {
template&lt;typename T&gt; class shared_ptr; template&lt;typename T&gt; class shared_ptr;
@@ -41,7 +42,7 @@
template&lt;typename T, typename A&gt; template&lt;typename T, typename A&gt;
shared_ptr&lt;T&gt; <a href="#functions">allocate_shared</a>( A const &amp; ); shared_ptr&lt;T&gt; <a href="#functions">allocate_shared</a>( A const &amp; );
#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) // C++0x prototypes #if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) // C++0x prototypes
template&lt;typename T, typename... Args&gt; template&lt;typename T, typename... Args&gt;
shared_ptr&lt;T&gt; <a href="#functions">make_shared</a>( Args &amp;&amp; ... args ); shared_ptr&lt;T&gt; <a href="#functions">make_shared</a>( Args &amp;&amp; ... args );
@@ -69,51 +70,50 @@
#endif #endif
}</pre> }</pre>
<h2><a name="functions">Free Functions</a></h2> <h2><a name="functions">Free Functions</a></h2>
<pre>template&lt;class T, class... Args&gt; <pre>template&lt;class T, class... Args&gt;
shared_ptr&lt;T&gt; make_shared( Args &amp;&amp; ... args ); shared_ptr&lt;T&gt; make_shared( Args &amp;&amp; ... args );
template&lt;class T, class A, class... Args&gt; template&lt;class T, class A, class... Args&gt;
shared_ptr&lt;T&gt; allocate_shared( A const &amp; a, Args &amp;&amp; ... args );</pre> shared_ptr&lt;T&gt; allocate_shared( A const &amp; a, Args &amp;&amp; ... args );</pre>
<blockquote> <blockquote>
<p><b>Requires:</b> The expression <code>new( pv ) T( std::forward&lt;Args&gt;(args)... )</code>, <p><b>Requires:</b> The expression <code>new( pv ) T( std::forward&lt;Args&gt;(args)... )</code>,
where <code>pv</code> is a <code>void*</code> pointing to storage suitable where <code>pv</code> is a <code>void*</code> pointing to storage suitable
to hold an object of type <code>T</code>, to hold an object of type <code>T</code>,
shall be well-formed. <code>A</code> shall be an <em>Allocator</em>, shall be well-formed. <code>A</code> shall be an <em>Allocator</em>,
as described in section 20.1.5 (<stong>Allocator requirements</strong>) of the C++ Standard. as described in section 20.1.5 (<strong>Allocator requirements</strong>) of the C++ Standard.
The copy constructor and destructor of <code>A</code> shall not throw.</p> The copy constructor and destructor of <code>A</code> shall not throw.</p>
<p><b>Effects:</b> Allocates memory suitable for an object of type <code>T</code> <p><b>Effects:</b> Allocates memory suitable for an object of type <code>T</code>
and constructs an object in it via the placement new expression <code>new( pv ) T()</code> and constructs an object in it via the placement new expression <code>new( pv ) T()</code>
or <code>new( pv ) T( std::forward&lt;Args&gt;(args)... )</code>. or <code>new( pv ) T( std::forward&lt;Args&gt;(args)... )</code>.
<code>allocate_shared</code> uses a copy of <code>a</code> to allocate memory. <code>allocate_shared</code> uses a copy of <code>a</code> to allocate memory.
If an exception is thrown, has no effect.</p> If an exception is thrown, has no effect.</p>
<p><b>Returns:</b> A <code>shared_ptr</code> instance that stores and owns the address <p><b>Returns:</b> A <code>shared_ptr</code> instance that stores and owns the address
of the newly constructed object of type <code>T</code>.</p> of the newly constructed object of type <code>T</code>.</p>
<p><b>Postconditions:</b> <code>get() != 0 &amp;&amp; use_count() == 1</code>.</p> <p><b>Postconditions:</b> <code>get() != 0 &amp;&amp; use_count() == 1</code>.</p>
<p><b>Throws:</b> <code>bad_alloc</code>, or an exception thrown from <code>A::allocate</code> <p><b>Throws:</b> <code>bad_alloc</code>, or an exception thrown from <code>A::allocate</code>
or the constructor of <code>T</code>.</p> or the constructor of <code>T</code>.</p>
<p><b>Notes:</b> This implementation allocates the memory required for the <p><b>Notes:</b> This implementation allocates the memory required for the
returned <code>shared_ptr</code> and an object of type <code>T</code> in a single returned <code>shared_ptr</code> and an object of type <code>T</code> in a single
allocation. This provides efficiency equivalent to an intrusive smart pointer.</p> allocation. This provides efficiency equivalent to an intrusive smart pointer.</p>
<p>The prototypes shown above are used if your compiler supports rvalue references <p>The prototypes shown above are used if your compiler supports rvalue references
and variadic templates. They perfectly forward the <code>args</code> parameters to and variadic templates. They perfectly forward the <code>args</code> parameters to
the constructors of <code>T</code>.</p> the constructors of <code>T</code>.</p>
<p>Otherwise, the implementation will fall back on <p>Otherwise, the implementation will fall back on
forwarding the arguments to the constructors of <code>T</code> as const references. forwarding the arguments to the constructors of <code>T</code> as const references.
If you need to pass a non-const reference to a constructor of <code>T</code>, If you need to pass a non-const reference to a constructor of <code>T</code>,
you may do so by wrapping the parameter in a call to <code>boost::ref</code>. you may do so by wrapping the parameter in a call to <code>boost::ref</code>.
In addition, you will be In addition, you will be
limited to a maximum of 9 arguments (not counting the allocator argument of limited to a maximum of 9 arguments (not counting the allocator argument of
allocate_shared).</p> allocate_shared).</p>
</blockquote> </blockquote>
<h2><a name="example">Example</a></h2> <h2><a name="example">Example</a></h2>
<pre>boost::shared_ptr&lt;std::string&gt; x = boost::make_shared&lt;std::string&gt;("hello, world!"); <pre>boost::shared_ptr&lt;std::string&gt; x = boost::make_shared&lt;std::string&gt;("hello, world!");
std::cout << *x;</pre> std::cout << *x;</pre>
<hr> <hr>
<p> <p>$Date$</p>
$Date: 2008-05-19 15:42:39 -0400 (Mon, 19 May 2008) $</p> <p><small>Copyright 2008 Peter Dimov. Copyright 2008 Frank Mori Hess.
<p><small>Copyright 2008 Peter Dimov. Copyright 2008 Frank Mori Hess. Distributed under the Boost Software License,
Distributed under the Boost Software License, Version 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A>
Version 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p> </body>
</body>
</html> </html>

View File

@@ -1,257 +1,272 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>make_shared and allocate_shared</title> <title>make_shared and allocate_shared for arrays</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> </head>
<body text="#000000" bgColor="#ffffff" link="#0000ff" vlink="#0000ff"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
width="277" align="middle" border="0">make_shared and allocate_shared width="277" align="middle" border="0">make_shared and allocate_shared
for arrays</h1> for arrays</h1>
<p><A href="#Introduction">Introduction</A><br> <p><a href="#introduction">Introduction</a><br>
<A href="#Synopsis">Synopsis</A><br> <a href="#synopsis">Synopsis</a><br>
<A href="#functions">Free Functions</A><br> <a href="#common">Common Requirements</a><br>
<A href="#example">Example</A><br> <a href="#functions">Free Functions</a><br>
<A href="#history">History</A><br></p> <a href="#history">History</a><br>
<h2><a name="Introduction">Introduction</a></h2> <a href="#references">References</a></p>
<h2><a name="introduction">Introduction</a></h2>
<p>Originally the Boost function templates <code>make_shared</code> and <p>Originally the Boost function templates <code>make_shared</code> and
<code>allocate_shared</code> were for efficient allocation of single <code>allocate_shared</code> were for efficient allocation of shared
objects only. There was a need to have efficient, single, allocation of objects only. There was a need to have efficient allocation of
arrays. One criticism of <a href="shared_array.htm">shared_array</a> was shared arrays. One criticism of class template <code>shared_array</code>
always the lack of a <a href="make_shared.html">make_shared</a> utility was always the lack of a <a href="make_shared.html">make_shared</a>
which ensures only a single allocation for an array.</p> utility which ensures only a single allocation.</p>
<p>The header files &lt;boost/smart_ptr/make_shared_array.hpp&gt; and <p>The header files &lt;boost/smart_ptr/make_shared_array.hpp&gt; and
&lt;boost/smart_ptr/allocate_shared_array.hpp&gt; provide new function &lt;boost/smart_ptr/allocate_shared_array.hpp&gt; provide function
templates, <code>make_shared</code> and <code>allocate_shared</code>, templates, overloads of <code>make_shared</code> and
to address this need. <code>make_shared</code> uses the global <code>allocate_shared</code> for array types, to address this need.
operator <code>new</code> to allocate memory, whereas <code>make_shared</code> uses the global operator <code>new</code> to
<code>allocate_shared</code> uses an user-supplied allocator, allocate memory, whereas <code>allocate_shared</code> uses an
allowing finer control.</p> user-supplied allocator, allowing finer control.</p>
<h2><a name="Synopsis">Synopsis</a></h2> <h2><a name="synopsis">Synopsis</a></h2>
<pre>namespace boost { <pre>namespace boost {
template&lt;typename U&gt; // U = T[] template&lt;typename U&gt; // U is T[]
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(size_t size); shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(size_t size);
template&lt;typename U, typename A&gt; // U = T[] template&lt;typename U, typename A&gt; // U is T[]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, size_t size); shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, size_t size);
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) &amp;&amp; !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template&lt;typename U&gt; // U is T[N]
template&lt;typename U, typename... Args&gt; // U = T[] shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>();
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(size_t size, Args&amp;&amp;... args);
template&lt;typename U, typename... Args&gt; // U = T[N] template&lt;typename U, typename A&gt; // U is T[N]
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(Args&amp;&amp;... args); shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator);
template&lt;typename U, typename A, typename... Args&gt; // U = T[] template&lt;typename U&gt; // U is T[]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, size_t size, Args&amp;&amp;... args); shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(size_t size, const T&amp; value);
template&lt;typename U, typename A, typename... Args&gt; // U = T[N] template&lt;typename U, typename A&gt; // U is T[]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, Args&amp;&amp;... args); shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, size_t size, const T&amp; value);
#endif
#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) template&lt;typename U&gt; // U is T[N]
template&lt;typename U, typename... Args&gt; // U = T[N] shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(const T&amp; value);
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(const T (&amp;list)[N]);
template&lt;typename U, typename... Args&gt; // U = T[][N] template&lt;typename U, typename A&gt; // U is T[N]
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(size_t size, const T (&amp;list)[N]); shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, const T&amp; value);
template&lt;typename U, typename... Args&gt; // U = T[M][N] template&lt;typename U&gt; // U is T[]
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(const T (&amp;list)[N]);
template&lt;typename U, typename A, typename... Args&gt; // U = T[N]
shared_ptr&lt;T[&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, const T (&amp;list)[N]);
template&lt;typename U, typename A, typename... Args&gt; // U = T[][N]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, size_t size, const T (&amp;list)[N]);
template&lt;typename U, typename A, typename... Args&gt; // U = T[M][N]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, const T (&amp;list)[N]);
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template&lt;typename U, typename... Args&gt; // U = T[]
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(initializer_list&lt;T&gt; list);
template&lt;typename U, typename A, typename... Args&gt; // U = T[]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, initializer_list&lt;T&gt; list);
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template&lt;typename U&gt; // U = T[]
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(size_t size, T&amp;&amp; value);
template&lt;typename U&gt; // U = T[N]
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(T&amp;&amp; value);
template&lt;typename U, typename A&gt; // U = T[]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, size_t size, T&amp;&amp; value);
template&lt;typename U, typename A&gt; // U = T[N]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator, T&amp;&amp; value);
#endif
#endif
template&lt;typename U&gt; // U = T[]
shared_ptr&lt;U&gt; <a href="#functions">make_shared_noinit</a>(size_t size); shared_ptr&lt;U&gt; <a href="#functions">make_shared_noinit</a>(size_t size);
template&lt;typename U&gt; // U = T[N] template&lt;typename U, typename A&gt; // U is T[]
shared_ptr&lt;U&gt; <a href="#functions">make_shared_noinit</a>();
template&lt;typename U, typename A&gt; // U = T[]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared_noinit</a>(const A&amp; allocator, size_t size); shared_ptr&lt;U&gt; <a href="#functions">allocate_shared_noinit</a>(const A&amp; allocator, size_t size);
template&lt;typename U, typename A&gt; // U = T[N] template&lt;typename U&gt; // U is T[N]
shared_ptr&lt;U&gt; <a href="#functions">make_shared_noinit</a>();
template&lt;typename U, typename A&gt; // U is T[N]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared_noinit</a>(const A&amp; allocator); shared_ptr&lt;U&gt; <a href="#functions">allocate_shared_noinit</a>(const A&amp; allocator);
}</pre> }</pre>
<h2><a name="functions">Free Functions</a></h2> <h2><a name="common">Common Requirements</a></h2>
<pre>template&lt;typename U, typename... Args&gt; // U = T[] <pre>template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared(size_t size, Args&amp;&amp;... args); shared_ptr&lt;U&gt; make_shared(<em>args</em>);
template&lt;typename U, typename A&gt;
template&lt;typename U, typename A, typename... Args&gt; // U = T[] shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, <em>args</em>);
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, size_t size, Args&amp;&amp;... args);</pre> template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared_noinit(<em>args</em>);
template&lt;typename U, typename A&gt;
shared_ptr&lt;U&gt; allocate_shared_noinit(const A&amp; allocator, <em>args</em>);</pre>
<blockquote> <blockquote>
<p><b>Requires:</b> The expression <p><b>Requires:</b> <code>U</code> is of the form <code>T[]</code> or
<code>new(pointer) T(forward&lt;Args&gt;(args)...)</code>, where <code>T[N]</code>. <code>A</code> shall be an <em>Allocator</em>, as
<code>pointer</code> is a <code>void*</code> pointing to storage described in section 17.6.3.5 [<strong>Allocator
suitable to hold an object of type <code>T</code>, shall be requirements</strong>] of the C++ Standard. The copy constructor and
well-formed. <code>A</code> shall be an <em>Allocator</em>, as destructor of <code>A</code> shall not throw exceptions.</p>
described in section 20.1.5 (<strong>Allocator requirements</strong>) <p><b>Effects:</b> Allocates memory for an object of type <code>U</code>
of the C++ Standard. The copy constructor and destructor of (or <code>T[size]</code> when <code>U</code> is <code>T[]</code>,
<code>A</code> shall not throw.</p> where <code>size</code> is determined from <code><em>args</em></code>
<p><b>Effects:</b> Allocates memory suitable for an array of type as specified by the concrete overload). The object is initialized as
<code>T</code> and size <code>size</code> and constructs an array specified by the concrete overload. The templates
of objects in it via the placement new expression <code>allocate_shared</code> and <code>allocate_shared_noinit</code>
<code>new(pointer) T()</code> or use a copy of <code>allocator</code> to allocate memory. If an
<code>new(pointer) T(args...)</code>. exception is thrown, the functions have no effect.</p>
<code>allocate_shared</code> uses a copy of
<code>allocator</code> to allocate memory. If an exception is thrown,
has no effect.</p>
<p><b>Returns:</b> A <code>shared_ptr</code> instance that stores and <p><b>Returns:</b> A <code>shared_ptr</code> instance that stores and
owns the address of the newly constructed array of type <code>T</code> owns the address of the newly constructed object.</p>
and size <code>size</code>.</p> <p><b>Postconditions:</b> <code>r.get() != 0 &amp;&amp;
<p><b>Postconditions:</b> r.use_count() == 1</code>, where <code>r</code> is the return
<code>get() != 0 &amp;&amp; use_count() == 1</code>.</p> value.</p>
<p><b>Throws:</b> <code>bad_alloc</code>, or an exception thrown from <p><b>Throws:</b> <code>bad_alloc</code>, an exception thrown from
<code>A::allocate</code> or the constructor of <code>T</code>.</p> <code>A::allocate</code>, or from the initialization of the
<p><b>Notes:</b> This implementation allocates the memory required for object.</p>
the returned <code>shared_ptr</code> and an array of type <p><b>Remarks:</b></p>
<code>T</code> of size <code>size</code> in a single allocation. This <blockquote>
provides efficiency to equivalent to an intrusive smart array <p>This implementation performs no more than one memory
pointer.</p> allocation. This provides efficiency to equivalent to an intrusive
<p>The prototypes shown above are used if your compiler supports r-value smart pointer.</p>
references and variadic templates. They perfectly forward the <p>When an object of an array type <code>T</code> is specified to be
<code>args</code> parameters to the constructors of initialized to a value of the same type <code>value</code>, this
<code>T</code> for each array element.</p> shall be interpreted to mean that each array element of the object
<p>Otherwise, you can use the overloads which take only the array size is initialized to the corresponding element from
(and the allocator in case of <code>allocate_shared</code>) and do not <code>value</code>.</p>
take any constructor arguments. These overloads invoke the default <p>When an object of an array type is specified to be
constructor of <code>T</code> for each array element.</p> value-initialized, this shall be interpreted to mean that each
array element of the object is value-initialized.</p>
<p>Array elements are initialized in ascending order of their
addresses.</p>
<p>When a subobject of a non-array type <code>T</code> is specified to
be initialized to a value <code>value</code>,
<code>make_shared</code> shall perform this initialization via the
expression <code>::new(ptr) T(value)</code>, where <code>ptr</code>
has type <code>void*</code> and points to storage suitable to hold
an object of type <code>T</code>.</p>
<p>When a subobject of non-array type <code>T</code> is specified to
be initialized to a value <code>value</code>,
<code>allocate_shared</code> shall perform this initialization via
the expression <code>allocator_traits&lt;A2&gt;::construct(a2, ptr,
value)</code>, where <code>ptr</code> points to storage suitable to
hold an object of type <code>T</code> and <code>a2</code> of type A2
is a rebound copy of the allocator <code>allocator</code> passed to
<code>allocate_shared</code> such that its <code>value_type</code>
is <code>T</code>.</p>
<p>When a subobject of non-array type <code>T</code> is specified to
be value-initialized, <code>make_shared</code> shall perform this
initialization via the expression <code>::new(ptr) T()</code>, where
<code>ptr</code> has type <code>void*</code> and points to storage
suitable to hold an object of type <code>T</code>.</p>
<p>When a subobject of non-array type <code>T</code> is specified to
be value-initialized, <code>allocate_shared</code> shall perform
this initialization via the expression
<code>allocator_traits&lt;A2&gt;::construct(a2, ptr)</code>, where
<code>ptr</code> points to storage suitable to hold an object
of type <code>T</code> and <code>a2</code> of type A2 is a rebound
copy of the allocator <code>allocator</code> passed to
<code>allocate_shared</code> such that its <code>value_type</code>
is <code>T</code>.</p>
<p>When a subobject of non-array type <code>T</code> is specified to
be default-initialized, <code>make_shared_noinit</code> and
<code>allocate_shared_noinit</code> shall perform this
initialization via the expression <code>::new(ptr) T</code>, where
<code>ptr</code> has type <code>void*</code> and points to storage
suitable to hold an object of type <code>T</code>.</p>
<p>When the lifetime of the object managed by the return value ends,
or when the initialization of an array element throws an exception,
the initialized elements should be destroyed in the reverse order
of their construction.</p>
</blockquote>
<p><b>Notes:</b> These functions will typically allocate more memory
than <code>sizeof(U)</code> to allow for internal bookkeeping
structures such as the reference counts.</p>
</blockquote> </blockquote>
<pre>template&lt;typename U, typename... Args&gt; // U = T[N] <h2><a name="functions">Free Functions</a></h2>
shared_ptr&lt;U&gt; make_shared(Args&amp;&amp;... args); <pre>template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared(size_t size);
template&lt;typename U, typename A, typename... Args&gt; // U = T[N] template&lt;typename U, typename A&gt;
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, Args&amp;&amp;... args);</pre> shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, size_t size);</pre>
<blockquote> <blockquote>
<p><b>Description:</b> These overloads of the utilities above are for a <p><b>Returns:</b> A <code>shared_ptr</code> to a value-initialized
fixed size array.</p> object of type <code>T[size]</code>.</p>
<p><b>Remarks:</b> These overloads shall only participate in overload
resolution when <code>U</code> is of the form <code>T[]</code>.</p>
<p><b>Examples:</b></p>
<blockquote>
<pre>boost::shared_ptr&lt;int[]&gt; a1 = boost::make_shared&lt;int[]&gt;(size);
boost::shared_ptr&lt;int[][2]&gt; a2 = boost::make_shared&lt;int[][2]&gt;(size);</pre>
</blockquote>
</blockquote> </blockquote>
<pre>template&lt;typename U, typename... Args&gt; // U = T[] <pre>template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared(initializer_list&lt;T&gt; list); shared_ptr&lt;U&gt; make_shared();
template&lt;typename U, typename A&gt;
template&lt;typename U, typename A, typename... Args&gt; // U = T[] shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator);</pre>
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, initializer_list&lt;T&gt; list);</pre>
<blockquote> <blockquote>
<p><b>Description:</b> These overloads initialize the array elements <p><b>Returns:</b> A <code>shared_ptr</code> to a value-initialized
from the initializer list.</p> object of type <code>T[N]</code>.</p>
<p><b>Remarks:</b> These overloads shall only participate in overload
resolution when <code>U</code> is of the form <code>T[N]</code>.</p>
<p><b>Examples:</b></p>
<blockquote>
<pre>boost::shared_ptr&lt;int[8]&gt; a1 = boost::make_shared&lt;int[8]&gt;();
boost::shared_ptr&lt;int[4][2]&gt; a2 = boost::make_shared&lt;int[4][2]&gt;();</pre>
</blockquote>
</blockquote> </blockquote>
<pre>template&lt;typename U, typename... Args&gt; // U = T[N] <pre>template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared(const T (&amp;list)[N]); shared_ptr&lt;U&gt; make_shared(size_t size, const T&amp; value);
template&lt;typename U, typename A&gt;
template&lt;typename U, typename A, typename... Args&gt; // U = T[N] shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, size_t size, const T&amp; value);</pre>
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, const T (&amp;list)[N]);</pre>
<blockquote> <blockquote>
<p><b>Description:</b> These overloads of the utilities above are for a <p><b>Returns:</b> A <code>shared_ptr</code> to an object of type
fixed size array.</p> <code>T[size]</code>, where each array element of type <code>T</code>
is initialized to <code>value</code>.</p>
<p><b>Remarks:</b> These overloads shall only participate in overload
resolution when <code>U</code> is of the form <code>T[]</code>.</p>
<p><b>Examples:</b></p>
<blockquote>
<pre>boost::shared_ptr&lt;int[]&gt; a1 = boost::make_shared&lt;int[]&gt;(size, 1);
boost::shared_ptr&lt;int[][2]&gt; a2 = boost::make_shared&lt;int[][2]&gt;(size, {1, 2});</pre>
</blockquote>
</blockquote> </blockquote>
<pre>template&lt;typename U, typename... Args&gt; // U = T[][N] <pre>template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared(size_t size, const T (&amp;list)[N]); shared_ptr&lt;U&gt; make_shared(const T&amp; value);
template&lt;typename U, typename A&gt;
template&lt;typename U, typename A, typename... Args&gt; // U = T[][N] shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, const T&amp; value);</pre>
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, size_t size, const T (&amp;list)[N]);</pre>
<blockquote> <blockquote>
<p><b>Description:</b> These overloads initialize inner array elements <p><b>Returns:</b> A <code>shared_ptr</code> to an object of type
from the initializer list.</p> <code>T[N]</code>, where each array element of type <code>T</code> is
initialized to <code>value</code>.</p>
<p><b>Remarks:</b> These overloads shall only participate in overload
resolution when <code>U</code> is of the form <code>T[N]</code>.</p>
<p><b>Examples:</b></p>
<blockquote>
<pre>boost::shared_ptr&lt;int[8]&gt; a1 = boost::make_shared&lt;int[8]&gt;(1);
boost::shared_ptr&lt;int[4][2]&gt; a2 = boost::make_shared&lt;int[4][2]&gt;({1, 2});</pre>
</blockquote>
</blockquote> </blockquote>
<pre>template&lt;typename U, typename... Args&gt; // U = T[M][N] <pre>template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared(const T (&amp;list)[N]); shared_ptr&lt;U&gt; make_shared_noinit(size_t size);
template&lt;typename U, typename A&gt;
template&lt;typename U, typename A, typename... Args&gt; // U = T[M][N] shared_ptr&lt;U&gt; allocate_shared_noinit(const A&amp; allocator, size_t size);</pre>
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, const T (&amp;list)[N]);</pre>
<blockquote> <blockquote>
<p><b>Description:</b> These overloads of the utilities above are for a <p><b>Returns:</b> A <code>shared_ptr</code> to a default-initialized
fixed size array.</p> object of type <code>T[size]</code>.</p>
</blockquote> <p><b>Remarks:</b> These overloads shall only participate in overload
<pre>template&lt;typename U&gt; // U = T[] resolution when <code>U</code> is of the form <code>T[]</code>.</p>
shared_ptr&lt;U&gt; make_shared(size_t size, T&amp;&amp; value); <p><b>Examples:</b></p>
<blockquote>
template&lt;typename U, typename A&gt; // U = T[] <pre>boost::shared_ptr&lt;int[]&gt; a1 = boost::make_shared_noinit&lt;int[]&gt;(size);
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, size_t size, T&amp;&amp; value);</pre> boost::shared_ptr&lt;int[][2]&gt; a2 = boost::make_shared_noinit&lt;int[][2]&gt;(size);</pre>
<blockquote> </blockquote>
<p><b>Description:</b> These overloads initialize array elements with
the given value.</p>
</blockquote> </blockquote>
<pre>template&lt;typename U&gt; // U = T[N] <pre>template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared(T&amp;&amp; value); shared_ptr&lt;U&gt; make_shared_noinit();
template&lt;typename U, typename A&gt;
template&lt;typename U, typename A&gt; // U = T[N] shared_ptr&lt;U&gt; allocate_shared_noinit(const A&amp; allocator);</pre>
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, T&amp;&amp; value);</pre>
<blockquote> <blockquote>
<p><b>Description:</b> These overloads of the utilities above are for a <p><b>Returns:</b> A <code>shared_ptr</code> to a default-initialized
fixed size array.</p> object of type <code>T[N]</code>.</p>
</blockquote> <p><b>Remarks:</b> These overloads shall only participate in overload
<pre>template&lt;typename U&gt; // U = T[] resolution when <code>U</code> is of the form <code>T[N]</code>.</p>
shared_ptr&lt;U&gt; make_shared_noinit(size_t size); <p><b>Examples:</b></p>
<blockquote>
template&lt;typename U, typename A&gt; // U = T[] <pre>boost::shared_ptr&lt;int[8]&gt; a1 = boost::make_shared_noinit&lt;int[8]&gt;();
shared_ptr&lt;U&gt; allocate_shared_noinit(const A&amp; allocator, size_t size);</pre> boost::shared_ptr&lt;int[4][2]&gt; a2 = boost::make_shared_noinit&lt;int[4][2]&gt;();</pre>
<blockquote> </blockquote>
<p><b>Description:</b> These overloads do not perform any value
initialization of elements.</p>
</blockquote>
<pre>template&lt;typename U&gt; // U = T[N]
shared_ptr&lt;U&gt; make_shared_noinit();
template&lt;typename U, typename A&gt; // U = T[N]
shared_ptr&lt;U&gt; allocate_shared_noinit(const A&amp; allocator);</pre>
<blockquote>
<p><b>Description:</b> These overloads of the utilities above are for a
fixed size array.</p>
</blockquote>
<h2><a name="example">Example</a></h2>
<p>An example of each overload of make_shared for arrays:</p>
<blockquote>
<pre>boost::shared_ptr&lt;int[]&gt; a1 = boost::make_shared&lt;int[]&gt;(size);
boost::shared_ptr&lt;point[]&gt; a2 = boost::make_shared&lt;point[]&gt;(size, x, y);
boost::shared_ptr&lt;point[5]&gt; a3 = boost::make_shared&lt;point[5]&gt;(x, y);
boost::shared_ptr&lt;int[]&gt; a4 = boost::make_shared&lt;int[]&gt;({1, 2, 3});
boost::shared_ptr&lt;int[3]&gt; a5 = boost::make_shared&lt;int[3]&gt;({1, 2, 3});
boost::shared_ptr&lt;int[][3]&gt; a6 = boost::make_shared&lt;int[][3]&gt;(size, {1, 2, 3});
boost::shared_ptr&lt;int[5][3]&gt; a7 = boost::make_shared&lt;int[5][3]&gt;({1, 2, 3});
boost::shared_ptr&lt;point[]&gt; a8 = boost::make_shared&lt;point[]&gt;(size, {x, y});
boost::shared_ptr&lt;point[5]&gt; a9 = boost::make_shared&lt;point[5]&gt;({x, y});
boost::shared_ptr&lt;int[]&gt; a10 = boost::make_shared_noinit&lt;int[]&gt;(size);
boost::shared_ptr&lt;int[5]&gt; a11 = boost::make_shared_noinit&lt;int[5]&gt;();</pre>
</blockquote> </blockquote>
<h2><a name="history">History</a></h2> <h2><a name="history">History</a></h2>
<p>February 2014. Glen Fernandes updated overloads of make_shared and
allocate_shared to conform to the specification in C++ standard paper
<a href="#N3870">N3870</a> including resolving C++ standard library
defect report 2070.</p>
<p>November 2012. Glen Fernandes contributed implementations of <p>November 2012. Glen Fernandes contributed implementations of
make_shared and allocate_shared for arrays.</p> make_shared and allocate_shared for arrays.</p>
<h2><a name="references">References</a></h2>
<p><a name="N3870">N3870</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3870.html">
Extending make_shared to Support Arrays, Revision 1</a>, Peter Dimov
&amp; Glen Fernandes, January, 2014.</p>
<hr> <hr>
<p>$Date: 2012-10-30 10:12:25 -0800 (Tue, 30 Oct 2012) $</p> <p>$Date$</p>
<p><small>Copyright 2012 Glen Fernandes. Distributed under the Boost <p><small>Copyright 2012-2014 Glen Fernandes. Distributed under the
Software License, Version 1.0. See accompanying file Boost Software License, Version 1.0. See accompanying file
<A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or copy at <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at
<A href="http://www.boost.org/LICENSE_1_0.txt"> <a href="http://www.boost.org/LICENSE_1_0.txt">
http://www.boost.org/LICENSE_1_0.txt</A>.</small></p> http://www.boost.org/LICENSE_1_0.txt</a>.</small></p>
</body> </body>
</html> </html>

152
make_unique.html Normal file
View File

@@ -0,0 +1,152 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>make_unique</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
width="277" align="middle" border="0">make_unique</h1>
<p><a href="#introduction">Introduction</a><br>
<a href="#synopsis">Synopsis</a><br>
<a href="#common">Common Requirements</a><br>
<a href="#functions">Free Functions</a><br>
<a href="#history">History</a></p>
<h2><a name="introduction">Introduction</a></h2>
<p>The header file &lt;boost/make_unique.hpp&gt; provides overloaded
function template <code>make_unique</code> for convenient creation of
<code>unique_ptr</code> objects.</p>
<h2><a name="synopsis">Synopsis</a></h2>
<pre>namespace boost {
template&lt;typename U&gt; // U is not array
unique_ptr&lt;U&gt; <a href="#functions">make_unique</a>();
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template&lt;typename U, typename... Args&gt; // U is not array
unique_ptr&lt;U&gt; <a href="#functions">make_unique</a>(Args&amp;&amp;... args);
#endif
template&lt;typename U&gt; // U is not array
unique_ptr&lt;U&gt; <a href="#functions">make_unique</a>(U&amp;&amp; value);
template&lt;typename U&gt; // U is T[]
unique_ptr&lt;U&gt; <a href="#functions">make_unique</a>(size_t size);
template&lt;typename U&gt; // U is not array
unique_ptr&lt;U&gt; <a href="#functions">make_unique_noinit</a>();
template&lt;typename U&gt; // U is T[]
unique_ptr&lt;U&gt; <a href="#functions">make_unique_noinit</a>(size_t size);
}</pre>
<h2><a name="common">Common Requirements</a></h2>
<pre>template&lt;typename U&gt;
unique_ptr&lt;U&gt; make_unique(<em>args</em>);
template&lt;typename U&gt;
unique_ptr&lt;U&gt; make_unique_noinit(<em>args</em>);</pre>
<blockquote>
<p><b>Effects:</b> Allocates memory for an object of type <code>U</code>
(or <code>T[size]</code> when <code>U</code> is <code>T[]</code>,
where <code>size</code> is determined from <code>args</code> as
specified by the concrete overload). The object is initialized from
<code>args</code> as specified by the concrete overload. If an
exception is thrown, the functions have no effect.</p>
<p><b>Returns:</b> A <code>unique_ptr</code> instance that stores and
owns the address of the newly constructed object.</p>
<p><b>Postconditions:</b> <code>r.get() != 0</code>, where
<code>r</code> is the return value.</p>
<p><b>Throws:</b> <code>bad_alloc</code>, or an exception thrown from
the initialization of the object.</p>
<p><b>Remarks:</b></p>
<blockquote>
<p>When an object of a non-array type <code>T</code> is specified to
be initialized to a value <code>value</code>, or to
<code>T(list...)</code>, where <code>list...</code> is a list of
constructor arguments, <code>make_unique</code> shall perform this
initialization via the expression <code>new T(value)</code> or
<code>new T(list...)</code> respectively.</p>
<p>When an object of type <code>T</code> is specified to be
value-initialized, <code>make_unique</code> shall perform this
initialization via the expression <code>new T()</code>.</p>
<p>When an object of type <code>T</code> is specified to be
default-initialized, <code>make_unique_noinit</code> shall perform
this initialization via the expression <code>new T</code>.</p>
</blockquote>
</blockquote>
<h2><a name="functions">Free Functions</a></h2>
<pre>template&lt;typename U, typename... Args&gt;
unique_ptr&lt;U&gt; make_unique(Args&amp;&amp;... args);</pre>
<blockquote>
<p><b>Returns:</b> A unique_ptr to an object of type <code>U</code>,
initialized to <code>U(forward&lt;Args&gt;(args)...)</code>.</p>
<p><b>Remarks:</b> This overload shall only participate in overload
resolution when <code>U</code> is not an array type.</p>
<p><b>Examples:</b></p>
<blockquote>
<pre>unique_ptr&lt;float&gt; p1 = boost::make_unique&lt;float&gt;();
unique_ptr&lt;point&gt; p2 = boost::make_unique&lt;point&gt;(x, y);</pre>
</blockquote>
</blockquote>
<pre>template&lt;typename U&gt;
unique_ptr&lt;U&gt; make_unique(U&amp;&amp; value);</pre>
<blockquote>
<p><b>Returns:</b> A unique_ptr to an object of type <code>U</code>,
initialized to <code>move(value)</code>.</p>
<p><b>Remarks:</b> This overload shall only participate in overload
resolution when <code>U</code> is not an array type.</p>
<p><b>Examples:</b></p>
<blockquote>
<pre>unique_ptr&lt;string&gt; p1 = boost::make_unique&lt;string&gt;({'a', 'b'});
unique_ptr&lt;point&gt; p2 = boost::make_unique&lt;point&gt;({-10, 25});</pre>
</blockquote>
</blockquote>
<pre>template&lt;typename U&gt;
unique_ptr&lt;U&gt; make_unique(size_t size);</pre>
<blockquote>
<p><b>Returns:</b> A unique_ptr to a value-initialized object of type
<code>T[size]</code>.</p>
<p><b>Remarks:</b> This overload shall only participate in overload
resolution when <code>U</code> is of the form <code>T[]</code>.</p>
<p><b>Examples:</b></p>
<blockquote>
<pre>unique_ptr&lt;double[]&gt; p1 = boost::make_unique&lt;double[]&gt;(4);
unique_ptr&lt;int[][2]&gt; p2 = boost::make_unique&lt;int[][2]&gt;(2);</pre>
</blockquote>
</blockquote>
<pre>template&lt;typename U&gt;
unique_ptr&lt;U&gt; make_unique_noinit();</pre>
<blockquote>
<p><b>Returns:</b> A unique_ptr to a default-initialized object of
type <code>U</code>.</p>
<p><b>Remarks:</b> This overload shall only participate in overload
resolution when <code>U</code> is not an array type.</p>
<p><b>Examples:</b></p>
<blockquote>
<pre>unique_ptr&lt;float&gt; p1 = boost::make_unique_noinit&lt;float&gt;();
unique_ptr&lt;point&gt; p2 = boost::make_unique_noinit&lt;point&gt;();</pre>
</blockquote>
</blockquote>
<pre>template&lt;typename U&gt;
unique_ptr&lt;U&gt; make_unique_noinit(size_t size);</pre>
<blockquote>
<p><b>Returns:</b> A unique_ptr to a default-initialized object of
type <code>T[size]</code>.</p>
<p><b>Remarks:</b> This overload shall only participate in overload
resolution when <code>U</code> is of the form <code>T[]</code>.</p>
<p><b>Examples:</b></p>
<blockquote>
<pre>unique_ptr&lt;double[]&gt; p1 = boost::make_unique_noinit&lt;double[]&gt;(4);
unique_ptr&lt;int[][2]&gt; p2 = boost::make_unique_noinit&lt;int[][2]&gt;(2);</pre>
</blockquote>
</blockquote>
<h2><a name="history">History</a></h2>
<p>January 2014. Glen Fernandes contributed implementations of
make_unique for objects and arrays.</p>
<hr>
<p>$Date$</p>
<p><small>Copyright 2012-2014 Glen Fernandes. Distributed under the
Boost Software License, Version 1.0. See accompanying file
<a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at
<a href="http://www.boost.org/LICENSE_1_0.txt">
http://www.boost.org/LICENSE_1_0.txt</a>.</small></p>
</body>
</html>

View File

@@ -1,33 +1,34 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>pointer_cast.hpp</title> <title>pointer_cast</title>
</head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<body> </head>
<h1><IMG height="86" alt="C++ Boost" src="../../boost.png" width="277" align="middle" border="0">Pointer <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
cast functions</h1> <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
<p>The pointer cast functions (<code>boost::static_pointer_cast</code> <code>boost::dynamic_pointer_cast</code> width="277" align="middle" border="0">pointer_cast</h1>
<code>boost::reinterpret_pointer_cast</code> <code>boost::const_pointer_cast</code>) <p>The pointer cast functions (<code>boost::static_pointer_cast</code> <code>boost::dynamic_pointer_cast</code>
provide a way to write generic pointer castings for raw pointers. The functions <code>boost::reinterpret_pointer_cast</code> <code>boost::const_pointer_cast</code>)
are defined in <CITE><A href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</A>.</CITE></p> provide a way to write generic pointer castings for raw pointers. The functions
<P>There is test/example code in <CITE><A href="test/pointer_cast_test.cpp">pointer_cast_test.cpp</A></CITE>.</p> are defined in <CITE><A href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</A>.</CITE></p>
<h2><a name="rationale">Rationale</a></h2> <P>There is test/example code in <CITE><A href="test/pointer_cast_test.cpp">pointer_cast_test.cpp</A></CITE>.</p>
<P>Boost smart pointers usually overload those functions to provide a mechanism to <h2><a name="rationale">Rationale</a></h2>
emulate pointers casts. For example, <code>boost::shared_ptr&lt;...&gt;</code> implements <P>Boost smart pointers usually overload those functions to provide a mechanism to
a static pointer cast this way:</P> emulate pointers casts. For example, <code>boost::shared_ptr&lt;...&gt;</code> implements
<pre> a static pointer cast this way:</P>
<pre>
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; static_pointer_cast(shared_ptr&lt;U&gt; const &amp;r); shared_ptr&lt;T&gt; static_pointer_cast(shared_ptr&lt;U&gt; const &amp;r);
</pre> </pre>
<P>Pointer cast functions from <CITE><A href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</A></CITE> <P>Pointer cast functions from <CITE><A href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</A></CITE>
are overloads of <code>boost::static_pointer_cast</code>, <code>boost::dynamic_pointer_cast</code>, are overloads of <code>boost::static_pointer_cast</code>, <code>boost::dynamic_pointer_cast</code>,
<code>boost::reinterpret_pointer_cast</code> and <code>boost::const_pointer_cast</code> <code>boost::reinterpret_pointer_cast</code> and <code>boost::const_pointer_cast</code>
for raw pointers. This way when developing pointer type independent classes, for raw pointers. This way when developing pointer type independent classes,
for example, memory managers or shared memory compatible classes, the same code for example, memory managers or shared memory compatible classes, the same code
can be used for raw and smart pointers.</p> can be used for raw and smart pointers.</p>
<H2><A name="synopsis">Synopsis</A></H2> <H2><A name="synopsis">Synopsis</A></H2>
<BLOCKQUOTE> <BLOCKQUOTE>
<PRE> <PRE>
namespace boost { namespace boost {
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
@@ -48,12 +49,12 @@ inline T* reinterpret_pointer_cast(U *ptr)
} // namespace boost } // namespace boost
</PRE> </PRE>
</BLOCKQUOTE> </BLOCKQUOTE>
<P>As you can see from the above synopsis, the pointer cast functions are just <P>As you can see from the above synopsis, the pointer cast functions are just
wrappers around standard C++ cast operators.</P> wrappers around standard C++ cast operators.</P>
<H2><A name="example">Example</A></H2> <H2><A name="example">Example</A></H2>
<BLOCKQUOTE> <BLOCKQUOTE>
<PRE> <PRE>
#include &lt;boost/pointer_cast.hpp&gt; #include &lt;boost/pointer_cast.hpp&gt;
#include &lt;boost/shared_ptr.hpp&gt; #include &lt;boost/shared_ptr.hpp&gt;
@@ -93,13 +94,13 @@ int main()
delete ptr; delete ptr;
return 0; return 0;
}</PRE> }</PRE>
</BLOCKQUOTE> </BLOCKQUOTE>
<P>The example demonstrates how the generic pointer casts help us create pointer <P>The example demonstrates how the generic pointer casts help us create pointer
independent code.</P> independent code.</P>
<hr> <hr>
<p>Revised: $Date$</p> <p>$Date$</p>
<p>Copyright 2005 Ion Gazta<74>aga. Use, modification, and distribution are subject to <p>Copyright 2005 Ion Gazta<74>aga. Use, modification, and distribution are subject to
the Boost Software License, Version 1.0. (See accompanying file <A href="../../LICENSE_1_0.txt"> the Boost Software License, Version 1.0. (See accompanying file <A href="../../LICENSE_1_0.txt">
LICENSE_1_0.txt</A> or a copy at &lt;<A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>&gt;.)</p> LICENSE_1_0.txt</A> or a copy at &lt;<A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>&gt;.)</p>
</body> </body>
</html> </html>

View File

@@ -1,33 +1,33 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>pointer_to_other.hpp</title> <title>pointer_to_other</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> </head>
<body bgcolor="#ffffff" text="#000000"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" WIDTH="277" HEIGHT="86">Header <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
<a href="../../boost/pointer_to_other.hpp">boost/pointer_to_other.hpp</a></h1> width="277" align="middle" border="0">pointer_to_other</h1>
<p> <p>
The pointer to other utility provides a way, given a source pointer type, The pointer to other utility provides a way, given a source pointer type,
to obtain a pointer of the same type to another pointee type. The utility is to obtain a pointer of the same type to another pointee type. The utility is
defined in <cite><a href="../../boost/pointer_to_other.hpp">boost/pointer_to_other.hpp</a>.</cite></p> defined in <cite><a href="../../boost/pointer_to_other.hpp">boost/pointer_to_other.hpp</a>.</cite></p>
<p>There is test/example code in <cite><a href="test/pointer_to_other_test.cpp">pointer_to_other_test.cpp</a></cite>.</p> <p>There is test/example code in <cite><a href="test/pointer_to_other_test.cpp">pointer_to_other_test.cpp</a></cite>.</p>
<h2><a name="contents">Contents</a></h2> <h2><a name="contents">Contents</a></h2>
<ul> <ul>
<li> <li>
<a href="#rationale">Rationale</a> <a href="#rationale">Rationale</a>
<li> <li>
<a href="#synopsis">Synopsis</a> <a href="#synopsis">Synopsis</a>
<li> <li>
<a href="#example">Example</a></li> <a href="#example">Example</a></li>
</ul> </ul>
<h2><a name="rationale">Rationale</a></h2> <h2><a name="rationale">Rationale</a></h2>
<p>When building pointer independent classes, like memory managers, allocators, or <p>When building pointer independent classes, like memory managers, allocators, or
containers, there is often a need to define pointers generically, so that if a containers, there is often a need to define pointers generically, so that if a
template parameter represents a pointer (for example, a raw or smart pointer to template parameter represents a pointer (for example, a raw or smart pointer to
an int), we can define another pointer of the same type to another pointee (a an int), we can define another pointer of the same type to another pointee (a
raw or smart pointer to a float.)</p> raw or smart pointer to a float.)</p>
<pre>template &lt;class IntPtr&gt; <pre>template &lt;class IntPtr&gt;
class FloatPointerHolder class FloatPointerHolder
{ {
<em>// Let's define a pointer to a float</em> <em>// Let's define a pointer to a float</em>
@@ -35,8 +35,8 @@ class FloatPointerHolder
&lt;IntPtr, float&gt;::type float_ptr_t; &lt;IntPtr, float&gt;::type float_ptr_t;
float_ptr_t float_ptr; float_ptr_t float_ptr;
};</pre> };</pre>
<h2><a name="synopsis">Synopsis</a></h2> <h2><a name="synopsis">Synopsis</a></h2>
<pre> <pre>
namespace boost { namespace boost {
template&lt;class T, class U&gt; template&lt;class T, class U&gt;
@@ -69,10 +69,10 @@ struct pointer_to_other&lt; T*, U &gt;
}; };
} <em>// namespace boost</em></pre> } <em>// namespace boost</em></pre>
<p>If these definitions are not correct for a specific smart pointer, we can define <p>If these definitions are not correct for a specific smart pointer, we can define
a specialization of pointer_to_other.</p> a specialization of pointer_to_other.</p>
<h2><a name="example">Example</a></h2> <h2><a name="example">Example</a></h2>
<pre><em>// Let's define a memory allocator that can <pre><em>// Let's define a memory allocator that can
// work with raw and smart pointers</em> // work with raw and smart pointers</em>
#include &lt;boost/pointer_to_other.hpp&gt; #include &lt;boost/pointer_to_other.hpp&gt;
@@ -97,12 +97,12 @@ class memory_allocator
block_ptr_t free_blocks; block_ptr_t free_blocks;
};</pre> };</pre>
<p>As we can see, using pointer_to_other we can create pointer independent code.</p> <p>As we can see, using pointer_to_other we can create pointer independent code.</p>
<hr> <hr>
<p>Last revised: $Date$</p> <p>$Date$</p>
<p><small>Copyright 2005, 2006 Ion Gazta<74>aga and Peter Dimov. Use, modification, <p><small>Copyright 2005, 2006 Ion Gazta<74>aga and Peter Dimov. Use, modification,
and distribution are subject to the Boost Software License, Version 1.0.<br> and distribution are subject to the Boost Software License, Version 1.0.<br>
(See accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a (See accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a
copy at &lt; <a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>&gt;.)</small></p> copy at &lt; <a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>&gt;.)</small></p>
</body> </body>
</html> </html>

View File

@@ -1,38 +1,38 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>scoped_array</title> <title>scoped_array</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> </head>
<body bgcolor="#ffffff" text="#000000"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86" <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
border="0"></A>scoped_array class template</h1> width="277" align="middle" border="0">scoped_array class template</h1>
<p>The <b>scoped_array</b> class template stores a pointer to a dynamically <p>The <b>scoped_array</b> class template stores a pointer to a dynamically
allocated array. (Dynamically allocated arrays are allocated with the C++ <b>new[]</b> allocated array. (Dynamically allocated arrays are allocated with the C++ <b>new[]</b>
expression.) The array pointed to is guaranteed to be deleted, either on expression.) The array pointed to is guaranteed to be deleted, either on
destruction of the <b>scoped_array</b>, or via an explicit <b>reset</b>.</p> destruction of the <b>scoped_array</b>, or via an explicit <b>reset</b>.</p>
<p>The <b>scoped_array</b> template is a simple solution for simple needs. It <p>The <b>scoped_array</b> template is a simple solution for simple needs. It
supplies a basic "resource acquisition is initialization" facility, without supplies a basic "resource acquisition is initialization" facility, without
shared-ownership or transfer-of-ownership semantics. Both its name and shared-ownership or transfer-of-ownership semantics. Both its name and
enforcement of semantics (by being <a href="../utility/utility.htm#Class_noncopyable"> enforcement of semantics (by being <a href="../utility/utility.htm#Class_noncopyable">
noncopyable</a>) signal its intent to retain ownership solely within the noncopyable</a>) signal its intent to retain ownership solely within the
current scope. Because it is <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a>, current scope. Because it is <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a>,
it is safer than <b>shared_array</b> for pointers which should not be copied.</p> it is safer than <b>shared_array</b> for pointers which should not be copied.</p>
<p>Because <b>scoped_array</b> is so simple, in its usual implementation every <p>Because <b>scoped_array</b> is so simple, in its usual implementation every
operation is as fast as a built-in array pointer and it has no more space operation is as fast as a built-in array pointer and it has no more space
overhead that a built-in array pointer.</p> overhead that a built-in array pointer.</p>
<p>It cannot be used in C++ standard library containers. See <a href="shared_array.htm"> <p>It cannot be used in C++ standard library containers. See <a href="shared_array.htm">
<b>shared_array</b></a> if <b>scoped_array</b> does not meet your needs.</p> <b>shared_array</b></a> if <b>scoped_array</b> does not meet your needs.</p>
<p>It cannot correctly hold a pointer to a single object. See <a href="scoped_ptr.htm"><b>scoped_ptr</b></a> <p>It cannot correctly hold a pointer to a single object. See <a href="scoped_ptr.htm"><b>scoped_ptr</b></a>
for that usage.</p> for that usage.</p>
<p>A <b>std::vector</b> is an alternative to a <b>scoped_array</b> that is a bit <p>A <b>std::vector</b> is an alternative to a <b>scoped_array</b> that is a bit
heavier duty but far more flexible. A <b>boost::array</b> is an alternative heavier duty but far more flexible. A <b>boost::array</b> is an alternative
that does not use dynamic allocation.</p> that does not use dynamic allocation.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed <p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements"> to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p> common requirements</a>.</p>
<h2>Synopsis</h2> <h2>Synopsis</h2>
<pre>namespace boost { <pre>namespace boost {
template&lt;class T&gt; class scoped_array : <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a> { template&lt;class T&gt; class scoped_array : <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a> {
@@ -55,62 +55,61 @@
template&lt;class T&gt; void <a href="#free-swap">swap</a>(scoped_array&lt;T&gt; &amp; a, scoped_array&lt;T&gt; &amp; b); // never throws template&lt;class T&gt; void <a href="#free-swap">swap</a>(scoped_array&lt;T&gt; &amp; a, scoped_array&lt;T&gt; &amp; b); // never throws
}</pre> }</pre>
<h2>Members</h2> <h2>Members</h2>
<h3> <h3>
<a name="element_type">element_type</a></h3> <a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre> <pre>typedef T element_type;</pre>
<p>Provides the type of the stored pointer.</p> <p>Provides the type of the stored pointer.</p>
<h3><a name="ctor">constructors</a></h3> <h3><a name="ctor">constructors</a></h3>
<pre>explicit scoped_array(T * p = 0); // never throws</pre> <pre>explicit scoped_array(T * p = 0); // never throws</pre>
<p>Constructs a <b>scoped_array</b>, storing a copy of <b>p</b>, which must have <p>Constructs a <b>scoped_array</b>, storing a copy of <b>p</b>, which must have
been allocated via a C++ <b>new</b>[] expression or be 0. <b>T</b> is not been allocated via a C++ <b>new</b>[] expression or be 0. <b>T</b> is not
required be a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements"> required be a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p> common requirements</a>.</p>
<h3><a name="destructor">destructor</a></h3> <h3><a name="destructor">destructor</a></h3>
<pre>~scoped_array(); // never throws</pre> <pre>~scoped_array(); // never throws</pre>
<p>Deletes the array pointed to by the stored pointer. Note that <b>delete[]</b> on <p>Deletes the array pointed to by the stored pointer. Note that <b>delete[]</b> on
a pointer with a value of 0 is harmless. The guarantee that this does not throw a pointer with a value of 0 is harmless. The guarantee that this does not throw
exceptions depends on the requirement that the deleted array's objects' exceptions depends on the requirement that the deleted array's objects'
destructors do not throw exceptions. See the smart pointer <a href="smart_ptr.htm#common_requirements"> destructors do not throw exceptions. See the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p> common requirements</a>.</p>
<h3><a name="reset">reset</a></h3> <h3><a name="reset">reset</a></h3>
<pre>void reset(T * p = 0); // never throws</pre> <pre>void reset(T * p = 0); // never throws</pre>
<p> <p>
Deletes the array pointed to by the stored pointer and then stores a copy of p, Deletes the array pointed to by the stored pointer and then stores a copy of p,
which must have been allocated via a C++ <b>new[]</b> expression or be 0. The which must have been allocated via a C++ <b>new[]</b> expression or be 0. The
guarantee that this does not throw exceptions depends on the requirement that guarantee that this does not throw exceptions depends on the requirement that
the deleted array's objects' destructors do not throw exceptions. See the smart the deleted array's objects' destructors do not throw exceptions. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p> pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="operator[]">subscripting</a></h3> <h3><a name="operator[]">subscripting</a></h3>
<pre>T &amp; operator[](std::ptrdiff_t i) const; // never throws</pre> <pre>T &amp; operator[](std::ptrdiff_t i) const; // never throws</pre>
<p>Returns a reference to element <b>i</b> of the array pointed to by the stored <p>Returns a reference to element <b>i</b> of the array pointed to by the stored
pointer. Behavior is undefined and almost certainly undesirable if the stored pointer. Behavior is undefined and almost certainly undesirable if the stored
pointer is 0, or if <b>i</b> is less than 0 or is greater than or equal to the pointer is 0, or if <b>i</b> is less than 0 or is greater than or equal to the
number of elements in the array.</p> number of elements in the array.</p>
<h3><a name="get">get</a></h3> <h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre> <pre>T * get() const; // never throws</pre>
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart <p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p> pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="conversions">conversions</a></h3> <h3><a name="conversions">conversions</a></h3>
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre> <pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent <p>Returns an unspecified value that, when used in boolean contexts, is equivalent
to <code>get() != 0</code>.</p> to <code>get() != 0</code>.</p>
<h3><a name="swap">swap</a></h3> <h3><a name="swap">swap</a></h3>
<pre>void swap(scoped_array &amp; b); // never throws</pre> <pre>void swap(scoped_array &amp; b); // never throws</pre>
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a <p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
requirements</a>.</p> requirements</a>.</p>
<h2><a name="functions">Free Functions</a></h2> <h2><a name="functions">Free Functions</a></h2>
<h3><a name="free-swap">swap</a></h3> <h3><a name="free-swap">swap</a></h3>
<pre>template&lt;class T&gt; void swap(scoped_array&lt;T&gt; &amp; a, scoped_array&lt;T&gt; &amp; b); // never throws</pre> <pre>template&lt;class T&gt; void swap(scoped_array&lt;T&gt; &amp; a, scoped_array&lt;T&gt; &amp; b); // never throws</pre>
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>. <p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
Provided as an aid to generic programming.</p> Provided as an aid to generic programming.</p>
<hr> <hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan--> <p>$Date$</p>
09 January 2003<!--webbot bot="Timestamp" endspan i-checksum="32310"--></p> <p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version
Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p> </body>
</body>
</html> </html>

View File

@@ -1,38 +1,38 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>scoped_ptr</title> <title>scoped_ptr</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> </head>
<body bgcolor="#ffffff" text="#000000"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86" <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
border="0"></A>scoped_ptr class template</h1> width="277" align="middle" border="0">scoped_ptr class template</h1>
<p>The <b>scoped_ptr</b> class template stores a pointer to a dynamically allocated <p>The <b>scoped_ptr</b> class template stores a pointer to a dynamically allocated
object. (Dynamically allocated objects are allocated with the C++ <b>new</b> expression.) object. (Dynamically allocated objects are allocated with the C++ <b>new</b> expression.)
The object pointed to is guaranteed to be deleted, either on destruction of the <b>scoped_ptr</b>, The object pointed to is guaranteed to be deleted, either on destruction of the <b>scoped_ptr</b>,
or via an explicit <b>reset</b>. See the <a href="#example">example</a>.</p> or via an explicit <b>reset</b>. See the <a href="#example">example</a>.</p>
<p>The <b>scoped_ptr</b> template is a simple solution for simple needs. It <p>The <b>scoped_ptr</b> template is a simple solution for simple needs. It
supplies a basic "resource acquisition is initialization" facility, without supplies a basic "resource acquisition is initialization" facility, without
shared-ownership or transfer-of-ownership semantics. Both its name and shared-ownership or transfer-of-ownership semantics. Both its name and
enforcement of semantics (by being <a href="../utility/utility.htm#Class_noncopyable"> enforcement of semantics (by being <a href="../utility/utility.htm#Class_noncopyable">
noncopyable</a>) signal its intent to retain ownership solely within the noncopyable</a>) signal its intent to retain ownership solely within the
current scope. Because it is <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a>, current scope. Because it is <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a>,
it is safer than <b>shared_ptr</b> or <b>std::auto_ptr</b> for pointers which it is safer than <b>shared_ptr</b> or <b>std::auto_ptr</b> for pointers which
should not be copied.</p> should not be copied.</p>
<p>Because <b>scoped_ptr</b> is simple, in its usual implementation every operation <p>Because <b>scoped_ptr</b> is simple, in its usual implementation every operation
is as fast as for a built-in pointer and it has no more space overhead that a is as fast as for a built-in pointer and it has no more space overhead that a
built-in pointer.</p> built-in pointer.</p>
<p><STRONG>scoped_ptr</STRONG> cannot be used in C++ Standard Library containers. <p><STRONG>scoped_ptr</STRONG> cannot be used in C++ Standard Library containers.
Use <a href="shared_ptr.htm"><b>shared_ptr</b></a> if you need a smart pointer Use <a href="shared_ptr.htm"><b>shared_ptr</b></a> if you need a smart pointer
that can.</p> that can.</p>
<p><STRONG>scoped_ptr</STRONG> cannot correctly hold a pointer to a dynamically <p><STRONG>scoped_ptr</STRONG> cannot correctly hold a pointer to a dynamically
allocated array. See <a href="scoped_array.htm"><b>scoped_array</b></a> for allocated array. See <a href="scoped_array.htm"><b>scoped_array</b></a> for
that usage.</p> that usage.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed <p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements"> to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p> common requirements</a>.</p>
<h2>Synopsis</h2> <h2>Synopsis</h2>
<pre>namespace boost { <pre>namespace boost {
template&lt;class T&gt; class scoped_ptr : <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a> { template&lt;class T&gt; class scoped_ptr : <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a> {
@@ -56,60 +56,60 @@
template&lt;class T&gt; void <a href="#free-swap">swap</a>(scoped_ptr&lt;T&gt; &amp; a, scoped_ptr&lt;T&gt; &amp; b); // never throws template&lt;class T&gt; void <a href="#free-swap">swap</a>(scoped_ptr&lt;T&gt; &amp; a, scoped_ptr&lt;T&gt; &amp; b); // never throws
}</pre> }</pre>
<h2>Members</h2> <h2>Members</h2>
<h3><a name="element_type">element_type</a></h3> <h3><a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre> <pre>typedef T element_type;</pre>
<p>Provides the type of the stored pointer.</p> <p>Provides the type of the stored pointer.</p>
<h3><a name="constructors">constructors</a></h3> <h3><a name="constructors">constructors</a></h3>
<pre>explicit scoped_ptr(T * p = 0); // never throws</pre> <pre>explicit scoped_ptr(T * p = 0); // never throws</pre>
<p>Constructs a <b>scoped_ptr</b>, storing a copy of <b>p</b>, which must have been <p>Constructs a <b>scoped_ptr</b>, storing a copy of <b>p</b>, which must have been
allocated via a C++ <b>new</b> expression or be 0. <b>T</b> is not required be allocated via a C++ <b>new</b> expression or be 0. <b>T</b> is not required be
a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
requirements</a>.</p> requirements</a>.</p>
<h3><a name="destructor">destructor</a></h3> <h3><a name="destructor">destructor</a></h3>
<pre>~scoped_ptr(); // never throws</pre> <pre>~scoped_ptr(); // never throws</pre>
<p>Destroys the object pointed to by the stored pointer, if any, as if by using <tt>delete <p>Destroys the object pointed to by the stored pointer, if any, as if by using <tt>delete
this-&gt;get()</tt>.</p> this-&gt;get()</tt>.</p>
<P> <P>
The guarantee that this does not throw exceptions depends on the requirement The guarantee that this does not throw exceptions depends on the requirement
that the deleted object's destructor does not throw exceptions. See the smart that the deleted object's destructor does not throw exceptions. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</P> pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</P>
<h3><a name="reset">reset</a></h3> <h3><a name="reset">reset</a></h3>
<pre>void reset(T * p = 0); // never throws</pre> <pre>void reset(T * p = 0); // never throws</pre>
<p> <p>
Deletes the object pointed to by the stored pointer and then stores a copy of Deletes the object pointed to by the stored pointer and then stores a copy of
p, which must have been allocated via a C++ <b>new</b> expression or be 0. The p, which must have been allocated via a C++ <b>new</b> expression or be 0. The
guarantee that this does not throw exceptions depends on the requirement that guarantee that this does not throw exceptions depends on the requirement that
the deleted object's destructor does not throw exceptions. See the smart the deleted object's destructor does not throw exceptions. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p> pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="indirection">indirection</a></h3> <h3><a name="indirection">indirection</a></h3>
<pre>T &amp; operator*() const; // never throws</pre> <pre>T &amp; operator*() const; // never throws</pre>
<p>Returns a reference to the object pointed to by the stored pointer. Behavior is <p>Returns a reference to the object pointed to by the stored pointer. Behavior is
undefined if the stored pointer is 0.</p> undefined if the stored pointer is 0.</p>
<pre>T * operator-&gt;() const; // never throws</pre> <pre>T * operator-&gt;() const; // never throws</pre>
<p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p> <p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
<h3><a name="get">get</a></h3> <h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre> <pre>T * get() const; // never throws</pre>
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart <p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p> pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="conversions">conversions</a></h3> <h3><a name="conversions">conversions</a></h3>
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre> <pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent <p>Returns an unspecified value that, when used in boolean contexts, is equivalent
to <code>get() != 0</code>.</p> to <code>get() != 0</code>.</p>
<h3><a name="swap">swap</a></h3> <h3><a name="swap">swap</a></h3>
<pre>void swap(scoped_ptr &amp; b); // never throws</pre> <pre>void swap(scoped_ptr &amp; b); // never throws</pre>
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a <p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
requirements</a>.</p> requirements</a>.</p>
<h2><a name="functions">Free Functions</a></h2> <h2><a name="functions">Free Functions</a></h2>
<h3><a name="free-swap">swap</a></h3> <h3><a name="free-swap">swap</a></h3>
<pre>template&lt;class T&gt; void swap(scoped_ptr&lt;T&gt; &amp; a, scoped_ptr&lt;T&gt; &amp; b); // never throws</pre> <pre>template&lt;class T&gt; void swap(scoped_ptr&lt;T&gt; &amp; a, scoped_ptr&lt;T&gt; &amp; b); // never throws</pre>
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>. <p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
Provided as an aid to generic programming.</p> Provided as an aid to generic programming.</p>
<h2><a name="example">Example</a></h2> <h2><a name="example">Example</a></h2>
<p>Here's an example that uses <b>scoped_ptr</b>.</p> <p>Here's an example that uses <b>scoped_ptr</b>.</p>
<blockquote> <blockquote>
<pre>#include &lt;boost/scoped_ptr.hpp&gt; <pre>#include &lt;boost/scoped_ptr.hpp&gt;
#include &lt;iostream&gt; #include &lt;iostream&gt;
struct Shoe { ~Shoe() { std::cout &lt;&lt; "Buckle my shoe\n"; } }; struct Shoe { ~Shoe() { std::cout &lt;&lt; "Buckle my shoe\n"; } };
@@ -128,54 +128,53 @@ int main()
std::cout &lt;&lt; my_instance.add_one() &lt;&lt; '\n'; std::cout &lt;&lt; my_instance.add_one() &lt;&lt; '\n';
std::cout &lt;&lt; my_instance.add_one() &lt;&lt; '\n'; std::cout &lt;&lt; my_instance.add_one() &lt;&lt; '\n';
}</pre> }</pre>
</blockquote> </blockquote>
<p>The example program produces the beginning of a child's nursery rhyme:</p> <p>The example program produces the beginning of a child's nursery rhyme:</p>
<blockquote> <blockquote>
<pre>1 <pre>1
2 2
Buckle my shoe</pre> Buckle my shoe</pre>
</blockquote> </blockquote>
<h2>Rationale</h2> <h2>Rationale</h2>
<p>The primary reason to use <b>scoped_ptr</b> rather than <b>auto_ptr</b> is to <p>The primary reason to use <b>scoped_ptr</b> rather than <b>auto_ptr</b> is to
let readers of your code know that you intend "resource acquisition is let readers of your code know that you intend "resource acquisition is
initialization" to be applied only for the current scope, and have no intent to initialization" to be applied only for the current scope, and have no intent to
transfer ownership.</p> transfer ownership.</p>
<p>A secondary reason to use <b>scoped_ptr</b> is to prevent a later maintenance <p>A secondary reason to use <b>scoped_ptr</b> is to prevent a later maintenance
programmer from adding a function that transfers ownership by returning the <b>auto_ptr</b>, programmer from adding a function that transfers ownership by returning the <b>auto_ptr</b>,
because the maintenance programmer saw <b>auto_ptr</b>, and assumed ownership because the maintenance programmer saw <b>auto_ptr</b>, and assumed ownership
could safely be transferred.</p> could safely be transferred.</p>
<p>Think of <b>bool</b> vs <b>int</b>. We all know that under the covers <b>bool</b> <p>Think of <b>bool</b> vs <b>int</b>. We all know that under the covers <b>bool</b>
is usually just an <b>int</b>. Indeed, some argued against including <b>bool</b> is usually just an <b>int</b>. Indeed, some argued against including <b>bool</b>
in the C++ standard because of that. But by coding <b>bool</b> rather than <b>int</b>, in the C++ standard because of that. But by coding <b>bool</b> rather than <b>int</b>,
you tell your readers what your intent is. Same with <b>scoped_ptr</b>; by you tell your readers what your intent is. Same with <b>scoped_ptr</b>; by
using it you are signaling intent.</p> using it you are signaling intent.</p>
<p>It has been suggested that <b>scoped_ptr&lt;T&gt;</b> is equivalent to <b>std::auto_ptr&lt;T&gt; <p>It has been suggested that <b>scoped_ptr&lt;T&gt;</b> is equivalent to <b>std::auto_ptr&lt;T&gt;
const</b>. Ed Brey pointed out, however, that <b>reset</b> will not work on const</b>. Ed Brey pointed out, however, that <b>reset</b> will not work on
a <b>std::auto_ptr&lt;T&gt; const.</b></p> a <b>std::auto_ptr&lt;T&gt; const.</b></p>
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2> <h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
<p>One common usage of <b>scoped_ptr</b> is to implement a handle/body (also called <p>One common usage of <b>scoped_ptr</b> is to implement a handle/body (also called
pimpl) idiom which avoids exposing the body (implementation) in the header pimpl) idiom which avoids exposing the body (implementation) in the header
file.</p> file.</p>
<p>The <a href="example/scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a> <p>The <a href="example/scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a>
sample program includes a header file, <a href="example/scoped_ptr_example.hpp">scoped_ptr_example.hpp</a>, sample program includes a header file, <a href="example/scoped_ptr_example.hpp">scoped_ptr_example.hpp</a>,
which uses a <b>scoped_ptr&lt;&gt;</b> to an incomplete type to hide the which uses a <b>scoped_ptr&lt;&gt;</b> to an incomplete type to hide the
implementation. The instantiation of member functions which require a complete implementation. The instantiation of member functions which require a complete
type occurs in the <a href="example/scoped_ptr_example.cpp">scoped_ptr_example.cpp</a> type occurs in the <a href="example/scoped_ptr_example.cpp">scoped_ptr_example.cpp</a>
implementation file.</p> implementation file.</p>
<h2>Frequently Asked Questions</h2> <h2>Frequently Asked Questions</h2>
<p><b>Q</b>. Why doesn't <b>scoped_ptr</b> have a release() member?<br> <p><b>Q</b>. Why doesn't <b>scoped_ptr</b> have a release() member?<br>
<b>A</b>. When reading source code, it is valuable to be able to draw <b>A</b>. When reading source code, it is valuable to be able to draw
conclusions about program behavior based on the types being used. If <STRONG>scoped_ptr</STRONG> conclusions about program behavior based on the types being used. If <STRONG>scoped_ptr</STRONG>
had a release() member, it would become possible to transfer ownership of the had a release() member, it would become possible to transfer ownership of the
held pointer, weakening its role as a way of limiting resource lifetime to a held pointer, weakening its role as a way of limiting resource lifetime to a
given context. Use <STRONG>std::auto_ptr</STRONG> where transfer of ownership given context. Use <STRONG>std::auto_ptr</STRONG> where transfer of ownership
is required. (supplied by Dave Abrahams)</p> is required. (supplied by Dave Abrahams)</p>
<hr> <hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan --> <p>$Date</p>
09 January 2003<!--webbot bot="Timestamp" endspan i-checksum="32310" --></p> <p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version
Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p> </body>
</body>
</html> </html>

View File

@@ -1,35 +1,35 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>shared_array</title> <title>shared_array</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> </head>
<body bgcolor="#ffffff" text="#000000"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86" <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
border="0"></A>shared_array class template</h1> width="277" align="middle" border="0">shared_array class template</h1>
<p>The <b>shared_array</b> class template stores a pointer to a dynamically <p>The <b>shared_array</b> class template stores a pointer to a dynamically
allocated array. (Dynamically allocated array are allocated with the C++ <b>new[]</b> allocated array. (Dynamically allocated array are allocated with the C++ <b>new[]</b>
expression.) The object pointed to is guaranteed to be deleted when the last <b>shared_array</b> expression.) The object pointed to is guaranteed to be deleted when the last <b>shared_array</b>
pointing to it is destroyed or reset.</p> pointing to it is destroyed or reset.</p>
<p>Every <b>shared_array</b> meets the <b>CopyConstructible</b> and <b>Assignable</b> <p>Every <b>shared_array</b> meets the <b>CopyConstructible</b> and <b>Assignable</b>
requirements of the C++ Standard Library, and so can be used in standard requirements of the C++ Standard Library, and so can be used in standard
library containers. Comparison operators are supplied so that <b>shared_array</b> library containers. Comparison operators are supplied so that <b>shared_array</b>
works with the standard library's associative containers.</p> works with the standard library's associative containers.</p>
<p>Normally, a <b>shared_array</b> cannot correctly hold a pointer to an object <p>Normally, a <b>shared_array</b> cannot correctly hold a pointer to an object
that has been allocated with the non-array form of <STRONG>new</STRONG>. See <a href="shared_ptr.htm"> that has been allocated with the non-array form of <STRONG>new</STRONG>. See <a href="shared_ptr.htm">
<b>shared_ptr</b></a> for that usage.</p> <b>shared_ptr</b></a> for that usage.</p>
<p>Because the implementation uses reference counting, cycles of <b>shared_array</b> <p>Because the implementation uses reference counting, cycles of <b>shared_array</b>
instances will not be reclaimed. For example, if <b>main()</b> holds a <b>shared_array</b> instances will not be reclaimed. For example, if <b>main()</b> holds a <b>shared_array</b>
to <b>A</b>, which directly or indirectly holds a <b>shared_array</b> back to <b>A</b>, to <b>A</b>, which directly or indirectly holds a <b>shared_array</b> back to <b>A</b>,
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_array</b> <b>A</b>'s use count will be 2. Destruction of the original <b>shared_array</b>
will leave <b>A</b> dangling with a use count of 1.</p> will leave <b>A</b> dangling with a use count of 1.</p>
<p>A <b>shared_ptr</b> to a <b>std::vector</b> is an alternative to a <b>shared_array</b> <p>A <b>shared_ptr</b> to a <b>std::vector</b> is an alternative to a <b>shared_array</b>
that is a bit heavier duty but far more flexible.</p> that is a bit heavier duty but far more flexible.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed <p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements"> to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p> common requirements</a>.</p>
<h2>Synopsis</h2> <h2>Synopsis</h2>
<pre>namespace boost { <pre>namespace boost {
template&lt;class T&gt; class shared_array { template&lt;class T&gt; class shared_array {
@@ -68,118 +68,116 @@
template&lt;class T&gt; void <a href="#free-swap">swap</a>(shared_array&lt;T&gt; &amp; a, shared_array&lt;T&gt; &amp; b); // never throws template&lt;class T&gt; void <a href="#free-swap">swap</a>(shared_array&lt;T&gt; &amp; a, shared_array&lt;T&gt; &amp; b); // never throws
}</pre> }</pre>
<h2>Members</h2> <h2>Members</h2>
<h3><a name="element_type">element_type</a></h3> <h3><a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre> <pre>typedef T element_type;</pre>
<p>Provides the type of the stored pointer.</p> <p>Provides the type of the stored pointer.</p>
<h3><a name="constructors">constructors</a></h3> <h3><a name="constructors">constructors</a></h3>
<pre>explicit shared_array(T * p = 0);</pre> <pre>explicit shared_array(T * p = 0);</pre>
<p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b>, which must be a <p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b>, which must be a
pointer to an array that was allocated via a C++ <b>new[]</b> expression or be pointer to an array that was allocated via a C++ <b>new[]</b> expression or be
0. Afterwards, the <a href="#use_count">use count</a> is 1 (even if p == 0; see <a href="#destructor"> 0. Afterwards, the <a href="#use_count">use count</a> is 1 (even if p == 0; see <a href="#destructor">
~shared_array</a>). The only exception which may be thrown by this ~shared_array</a>). The only exception which may be thrown by this
constructor is <b>std::bad_alloc</b>. If an exception is thrown, <b>delete[] p</b> constructor is <b>std::bad_alloc</b>. If an exception is thrown, <b>delete[] p</b>
is called.</p> is called.</p>
<pre>template&lt;class D&gt; shared_array(T * p, D d);</pre> <pre>template&lt;class D&gt; shared_array(T * p, D d);</pre>
<p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b> and of <b>d</b>. <p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b> and of <b>d</b>.
Afterwards, the <a href="#use_count">use count</a> is 1. <b>D</b>'s copy Afterwards, the <a href="#use_count">use count</a> is 1. <b>D</b>'s copy
constructor and destructor must not throw. When the the time comes to delete constructor and destructor must not throw. When the the time comes to delete
the array pointed to by <b>p</b>, the object <b>d</b> is used in the statement <b>d(p)</b>. the array pointed to by <b>p</b>, the object <b>d</b> is used in the statement <b>d(p)</b>.
Invoking the object <b>d</b> with parameter <b>p</b> in this way must not Invoking the object <b>d</b> with parameter <b>p</b> in this way must not
throw. The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>. throw. The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
If an exception is thrown, <b>d(p)</b> is called.</p> If an exception is thrown, <b>d(p)</b> is called.</p>
<pre>shared_array(shared_array const &amp; r); // never throws</pre> <pre>shared_array(shared_array const &amp; r); // never throws</pre>
<p>Constructs a <b>shared_array</b>, as if by storing a copy of the pointer stored <p>Constructs a <b>shared_array</b>, as if by storing a copy of the pointer stored
in <b>r</b>. Afterwards, the <a href="#use_count">use count</a> for all copies in <b>r</b>. Afterwards, the <a href="#use_count">use count</a> for all copies
is 1 more than the initial use count.</p> is 1 more than the initial use count.</p>
<h3><a name="destructor">destructor</a></h3> <h3><a name="destructor">destructor</a></h3>
<pre>~shared_array(); // never throws</pre> <pre>~shared_array(); // never throws</pre>
<p>Decrements the <a href="#use_count">use count</a>. Then, if the use count is 0, <p>Decrements the <a href="#use_count">use count</a>. Then, if the use count is 0,
deletes the array pointed to by the stored pointer. Note that <b>delete[]</b> on deletes the array pointed to by the stored pointer. Note that <b>delete[]</b> on
a pointer with a value of 0 is harmless. <b>T</b> need not be a complete type. a pointer with a value of 0 is harmless. <b>T</b> need not be a complete type.
The guarantee that this does not throw exceptions depends on the requirement The guarantee that this does not throw exceptions depends on the requirement
that the deleted object's destructor does not throw exceptions. See the smart that the deleted object's destructor does not throw exceptions. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p> pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="assignment">assignment</a></h3> <h3><a name="assignment">assignment</a></h3>
<pre>shared_array &amp; operator=(shared_array const &amp; r); // never throws</pre> <pre>shared_array &amp; operator=(shared_array const &amp; r); // never throws</pre>
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>, <p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
then replaces this <b>shared_array</b> with the new one, destroying the then replaces this <b>shared_array</b> with the new one, destroying the
replaced object.</p> replaced object.</p>
<h3><a name="reset">reset</a></h3> <h3><a name="reset">reset</a></h3>
<pre>void reset(T * p = 0);</pre> <pre>void reset(T * p = 0);</pre>
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>, <p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
then replaces this <b>shared_array</b> with the new one, destroying the then replaces this <b>shared_array</b> with the new one, destroying the
replaced object. The only exception which may be thrown is <b>std::bad_alloc</b>. replaced object. The only exception which may be thrown is <b>std::bad_alloc</b>.
If an exception is thrown, <b>delete[] p</b> is called.</p> If an exception is thrown, <b>delete[] p</b> is called.</p>
<pre>template&lt;class D&gt; void reset(T * p, D d);</pre> <pre>template&lt;class D&gt; void reset(T * p, D d);</pre>
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>, <p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
then replaces this <b>shared_array</b> with the new one, destroying the then replaces this <b>shared_array</b> with the new one, destroying the
replaced object. <b>D</b>'s copy constructor must not throw. The only exception replaced object. <b>D</b>'s copy constructor must not throw. The only exception
which may be thrown is <b>std::bad_alloc</b>. If an exception is thrown, <b>d(p)</b> which may be thrown is <b>std::bad_alloc</b>. If an exception is thrown, <b>d(p)</b>
is called.</p> is called.</p>
<h3><a name="indexing">indexing</a></h3> <h3><a name="indexing">indexing</a></h3>
<pre>T &amp; operator[](std::ptrdiff_t i) const; // never throws</pre> <pre>T &amp; operator[](std::ptrdiff_t i) const; // never throws</pre>
<p>Returns a reference to element <b>i</b> of the array pointed to by the stored <p>Returns a reference to element <b>i</b> of the array pointed to by the stored
pointer. Behavior is undefined and almost certainly undesirable if the stored pointer. Behavior is undefined and almost certainly undesirable if the stored
pointer is 0, or if <b>i</b> is less than 0 or is greater than or equal to the pointer is 0, or if <b>i</b> is less than 0 or is greater than or equal to the
number of elements in the array.</p> number of elements in the array.</p>
<h3><a name="get">get</a></h3> <h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre> <pre>T * get() const; // never throws</pre>
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart <p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p> pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="unique">unique</a></h3> <h3><a name="unique">unique</a></h3>
<pre>bool unique() const; // never throws</pre> <pre>bool unique() const; // never throws</pre>
<p>Returns true if no other <b>shared_array</b> is sharing ownership of the stored <p>Returns true if no other <b>shared_array</b> is sharing ownership of the stored
pointer, false otherwise. <b>T</b> need not be a complete type. See the smart pointer, false otherwise. <b>T</b> need not be a complete type. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p> pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="use_count">use_count</a></h3> <h3><a name="use_count">use_count</a></h3>
<pre>long use_count() const; // never throws</pre> <pre>long use_count() const; // never throws</pre>
<p>Returns the number of <b>shared_array</b> objects sharing ownership of the <p>Returns the number of <b>shared_array</b> objects sharing ownership of the
stored pointer. <b>T</b> need not be a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements"> stored pointer. <b>T</b> need not be a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p> common requirements</a>.</p>
<p>Because <b>use_count</b> is not necessarily efficient to implement for <p>Because <b>use_count</b> is not necessarily efficient to implement for
implementations of <b>shared_array</b> that do not use an explicit reference implementations of <b>shared_array</b> that do not use an explicit reference
count, it might be removed from some future version. Thus it should be used for count, it might be removed from some future version. Thus it should be used for
debugging purposes only, and not production code.</p> debugging purposes only, and not production code.</p>
<h3><a name="conversions">conversions</a></h3> <h3><a name="conversions">conversions</a></h3>
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre> <pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent <p>Returns an unspecified value that, when used in boolean contexts, is equivalent
to <code>get() != 0</code>.</p> to <code>get() != 0</code>.</p>
<h3><a name="swap">swap</a></h3> <h3><a name="swap">swap</a></h3>
<pre>void swap(shared_ptr &amp; b); // never throws</pre> <pre>void swap(shared_ptr &amp; b); // never throws</pre>
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a <p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
requirements</a>.</p> requirements</a>.</p>
<h2><a name="functions">Free Functions</a></h2> <h2><a name="functions">Free Functions</a></h2>
<h3><a name="comparison">comparison</a></h3> <h3><a name="comparison">comparison</a></h3>
<pre>template&lt;class T&gt; <pre>template&lt;class T&gt;
bool operator==(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws bool operator==(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws
template&lt;class T&gt; template&lt;class T&gt;
bool operator!=(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws bool operator!=(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws
template&lt;class T&gt; template&lt;class T&gt;
bool operator&lt;(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws</pre> bool operator&lt;(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws</pre>
<p>Compares the stored pointers of the two smart pointers. <b>T</b> need not be a <p>Compares the stored pointers of the two smart pointers. <b>T</b> need not be a
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
requirements</a>.</p> requirements</a>.</p>
<p>The <b>operator&lt;</b> overload is provided to define an ordering so that <b>shared_array</b> <p>The <b>operator&lt;</b> overload is provided to define an ordering so that <b>shared_array</b>
objects can be used in associative containers such as <b>std::map</b>. The objects can be used in associative containers such as <b>std::map</b>. The
implementation uses <b>std::less&lt;T *&gt;</b> to perform the comparison. This implementation uses <b>std::less&lt;T *&gt;</b> to perform the comparison. This
ensures that the comparison is handled correctly, since the standard mandates ensures that the comparison is handled correctly, since the standard mandates
that relational operations on pointers are unspecified (5.9 [expr.rel] that relational operations on pointers are unspecified (5.9 [expr.rel]
paragraph 2) but <b>std::less&lt;&gt;</b> on pointers is well-defined (20.3.3 paragraph 2) but <b>std::less&lt;&gt;</b> on pointers is well-defined (20.3.3
[lib.comparisons] paragraph 8).</p> [lib.comparisons] paragraph 8).</p>
<h3><a name="free-swap">swap</a></h3> <h3><a name="free-swap">swap</a></h3>
<pre>template&lt;class T&gt; <pre>template&lt;class T&gt;
void swap(shared_array&lt;T&gt; &amp; a, shared_array&lt;T&gt; &amp; b) // never throws</pre> void swap(shared_array&lt;T&gt; &amp; a, shared_array&lt;T&gt; &amp; b) // never throws</pre>
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>. <p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
Provided as an aid to generic programming.</p> Provided as an aid to generic programming.</p>
<hr> <hr>
<p>Revised <p>$Date$</p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan --> <p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
09 January 2003<!--webbot bot="Timestamp" endspan i-checksum="32310" --></p> Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or </body>
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html> </html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,207 +1,221 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>Smart Pointers</title> <title>Smart Pointers</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> </head>
<body bgcolor="#ffffff" text="#000000"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86" <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
border="0"></A>Smart Pointers</h1> width="277" align="middle" border="0">Smart Pointers</h1>
<p><a href="#Introduction">Introduction</a><br> <p><a href="#Introduction">Introduction</a><br>
<a href="#common_requirements">Common Requirements</a><br> <a href="#common_requirements">Common Requirements</a><br>
<a href="#Exception_Safety">Exception Safety</a><br> <a href="#Exception_Safety">Exception Safety</a><br>
<a href="#Exception-specifications">Exception-specifications</a><br> <a href="#Exception-specifications">Exception-specifications</a><br>
<a href="#History">History and Acknowledgements</a><br> <a href="#History">History and Acknowledgements</a><br>
<a href="#References">References</a></p> <a href="#References">References</a></p>
<h2><a name="Introduction">Introduction</a></h2> <h2><a name="Introduction">Introduction</a></h2>
<p>Smart pointers are objects which store pointers to dynamically allocated (heap) <p>Smart pointers are objects which store pointers to dynamically allocated (heap)
objects. They behave much like built-in C++ pointers except that they objects. They behave much like built-in C++ pointers except that they
automatically delete the object pointed to at the appropriate time. Smart automatically delete the object pointed to at the appropriate time. Smart
pointers are particularly useful in the face of exceptions as they ensure pointers are particularly useful in the face of exceptions as they ensure
proper destruction of dynamically allocated objects. They can also be used to proper destruction of dynamically allocated objects. They can also be used to
keep track of dynamically allocated objects shared by multiple owners.</p> keep track of dynamically allocated objects shared by multiple owners.</p>
<p>Conceptually, smart pointers are seen as owning the object pointed to, and thus <p>Conceptually, smart pointers are seen as owning the object pointed to, and thus
responsible for deletion of the object when it is no longer needed.</p> responsible for deletion of the object when it is no longer needed.</p>
<p>The smart pointer library provides six smart pointer class templates:</p> <p>The smart pointer library provides six smart pointer class templates:</p>
<div align="left"> <div align="left">
<table border="1" cellpadding="4" cellspacing="0"> <table border="1" cellpadding="4" cellspacing="0">
<tr> <tr>
<td><a href="scoped_ptr.htm"><b>scoped_ptr</b></a></td> <td><a href="scoped_ptr.htm"><b>scoped_ptr</b></a></td>
<td><a href="../../boost/scoped_ptr.hpp">&lt;boost/scoped_ptr.hpp&gt;</a></td> <td><a href="../../boost/scoped_ptr.hpp">&lt;boost/scoped_ptr.hpp&gt;</a></td>
<td>Simple sole ownership of single objects. Noncopyable.</td> <td>Simple sole ownership of single objects. Noncopyable.</td>
</tr> </tr>
<tr> <tr>
<td><a href="scoped_array.htm"><b>scoped_array</b></a></td> <td><a href="scoped_array.htm"><b>scoped_array</b></a></td>
<td><a href="../../boost/scoped_array.hpp">&lt;boost/scoped_array.hpp&gt;</a></td> <td><a href="../../boost/scoped_array.hpp">&lt;boost/scoped_array.hpp&gt;</a></td>
<td>Simple sole ownership of arrays. Noncopyable.</td> <td>Simple sole ownership of arrays. Noncopyable.</td>
</tr> </tr>
<tr> <tr>
<td><a href="shared_ptr.htm"><b>shared_ptr</b></a></td> <td><a href="shared_ptr.htm"><b>shared_ptr</b></a></td>
<td><a href="../../boost/shared_ptr.hpp">&lt;boost/shared_ptr.hpp&gt;</a></td> <td><a href="../../boost/shared_ptr.hpp">&lt;boost/shared_ptr.hpp&gt;</a></td>
<td>Object ownership shared among multiple pointers.</td> <td>Object ownership shared among multiple pointers.</td>
</tr> </tr>
<tr> <tr>
<td><a href="shared_array.htm"><b>shared_array</b></a></td> <td><a href="shared_array.htm"><b>shared_array</b></a></td>
<td><a href="../../boost/shared_array.hpp">&lt;boost/shared_array.hpp&gt;</a></td> <td><a href="../../boost/shared_array.hpp">&lt;boost/shared_array.hpp&gt;</a></td>
<td>Array ownership shared among multiple pointers.</td> <td>Array ownership shared among multiple pointers.</td>
</tr> </tr>
<tr> <tr>
<td><a href="weak_ptr.htm"><b>weak_ptr</b></a></td> <td><a href="weak_ptr.htm"><b>weak_ptr</b></a></td>
<td><a href="../../boost/weak_ptr.hpp">&lt;boost/weak_ptr.hpp&gt;</a></td> <td><a href="../../boost/weak_ptr.hpp">&lt;boost/weak_ptr.hpp&gt;</a></td>
<td>Non-owning observers of an object owned by <b>shared_ptr</b>.</td> <td>Non-owning observers of an object owned by <b>shared_ptr</b>.</td>
</tr> </tr>
<tr> <tr>
<td><a href="intrusive_ptr.html"><b>intrusive_ptr</b></a></td> <td><a href="intrusive_ptr.html"><b>intrusive_ptr</b></a></td>
<td><a href="../../boost/intrusive_ptr.hpp">&lt;boost/intrusive_ptr.hpp&gt;</a></td> <td><a href="../../boost/intrusive_ptr.hpp">&lt;boost/intrusive_ptr.hpp&gt;</a></td>
<td>Shared ownership of objects with an embedded reference count.</td> <td>Shared ownership of objects with an embedded reference count.</td>
</tr> </tr>
</table> </table>
</div> </div>
<p>These templates are designed to complement the <b>std::auto_ptr</b> template.</p> <p>These templates are designed to complement the <b>std::auto_ptr</b> template.</p>
<p>They are examples of the "resource acquisition is initialization" idiom <p>They are examples of the "resource acquisition is initialization" idiom
described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition, described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition,
Section 14.4, Resource Management.</p> Section 14.4, Resource Management.</p>
<p>Additionally, the smart pointer library provides efficient factory functions <p>Additionally, the smart pointer library provides efficient factory functions
for creating <code>shared_ptr</code> objects:</p> for creating smart pointer objects:</p>
<div align="left"> <div align="left">
<table border="1" cellpadding="4" cellspacing="0"> <table border="1" cellpadding="4" cellspacing="0">
<tr> <tr>
<td><a href="make_shared.html"><b>make_shared and allocate_shared</b></a></td> <td><a href="make_shared.html"><b>make_shared, allocate_shared</b></a> for objects</td>
<td><a href="../../boost/make_shared.hpp">&lt;boost/make_shared.hpp&gt;</a></td> <td><a href="../../boost/make_shared.hpp">&lt;boost/make_shared.hpp&gt;</a></td>
<td>Efficient creation of <code>shared_ptr</code> objects.</td> <td>Efficient creation of <code>shared_ptr</code> objects.</td>
</tr> </tr>
<tr> <tr>
<td><a href="make_shared_array.html"><b>make_shared and allocate_shared for arrays</b></a></td> <td><a href="make_shared_array.html"><b>make_shared, allocate_shared</b></a> for arrays</td>
<td><a href="../../boost/make_shared.hpp">&lt;boost/make_shared.hpp&gt;</a></td> <td><a href="../../boost/make_shared.hpp">&lt;boost/make_shared.hpp&gt;</a></td>
<td>Efficient creation of <code>shared_ptr</code> arrays.</td> <td>Efficient creation of <code>shared_ptr</code> arrays.</td>
</tr> </tr>
</table> <tr>
</div> <td><a href="make_unique.html"><b>make_unique</b></a></td>
<p>A test program, <a href="test/smart_ptr_test.cpp">smart_ptr_test.cpp</a>, is <td><a href="../../boost/make_unique.hpp">&lt;boost/make_unique.hpp&gt;</a></td>
provided to verify correct operation.</p> <td>Creation of <code>unique_ptr</code> objects and arrays.</td>
<p>A page on <a href="compatibility.htm">compatibility</a> with older versions of </tr>
the Boost smart pointer library describes some of the changes since earlier </table>
versions of the smart pointer implementation.</p> </div>
<p>A page on <a href="smarttests.htm">smart pointer timings</a> will be of interest <p>A test program, <a href="test/smart_ptr_test.cpp">smart_ptr_test.cpp</a>, is
to those curious about performance issues.</p> provided to verify correct operation.</p>
<P>A page on <A href="sp_techniques.html">smart pointer programming techniques</A> lists <p>A page on <a href="compatibility.htm">compatibility</a> with older versions of
some advanced applications of <code>shared_ptr</code> and <code>weak_ptr</code>.</P> the Boost smart pointer library describes some of the changes since earlier
<h2><a name="common_requirements">Common Requirements</a></h2> versions of the smart pointer implementation.</p>
<p>These smart pointer class templates have a template parameter, <b>T</b>, which <p>A page on <a href="smarttests.htm">smart pointer timings</a> will be of interest
specifies the type of the object pointed to by the smart pointer. The behavior to those curious about performance issues.</p>
of the smart pointer templates is undefined if the destructor or <b>operator delete</b> <P>A page on <A href="sp_techniques.html">smart pointer programming techniques</A> lists
for objects of type <b>T</b> throw exceptions.</p> some advanced applications of <code>shared_ptr</code> and <code>weak_ptr</code>.</P>
<p><b>T</b> may be an incomplete type at the point of smart pointer declaration. <h2><a name="common_requirements">Common Requirements</a></h2>
Unless otherwise specified, it is required that <b>T</b> be a complete type at <p>These smart pointer class templates have a template parameter, <b>T</b>, which
points of smart pointer instantiation. Implementations are required to diagnose specifies the type of the object pointed to by the smart pointer. The behavior
(treat as an error) all violations of this requirement, including deletion of of the smart pointer templates is undefined if the destructor or <b>operator delete</b>
an incomplete type. See the description of the <a href="../utility/utility.htm#checked_delete"> for objects of type <b>T</b> throw exceptions.</p>
<b>checked_delete</b></a> function template.</p> <p><b>T</b> may be an incomplete type at the point of smart pointer declaration.
<P>Note that <STRONG>shared_ptr</STRONG> does not have this restriction, as most of Unless otherwise specified, it is required that <b>T</b> be a complete type at
its member functions do not require <STRONG>T</STRONG> to be a complete type.</P> points of smart pointer instantiation. Implementations are required to diagnose
<h3>Rationale</h3> (treat as an error) all violations of this requirement, including deletion of
<p>The requirements on <b>T</b> are carefully crafted to maximize safety yet allow an incomplete type. See the description of the <a href="../utility/utility.htm#checked_delete">
handle-body (also called pimpl) and similar idioms. In these idioms a smart <b>checked_delete</b></a> function template.</p>
pointer may appear in translation units where <b>T</b> is an incomplete type. <P>Note that <STRONG>shared_ptr</STRONG> does not have this restriction, as most of
This separates interface from implementation and hides implementation from its member functions do not require <STRONG>T</STRONG> to be a complete type.</P>
translation units which merely use the interface. Examples described in the <h3>Rationale</h3>
documentation for specific smart pointers illustrate use of smart pointers in <p>The requirements on <b>T</b> are carefully crafted to maximize safety yet allow
these idioms.</p> handle-body (also called pimpl) and similar idioms. In these idioms a smart
<p>Note that <b>scoped_ptr</b> requires that <b>T</b> be a complete type at pointer may appear in translation units where <b>T</b> is an incomplete type.
destruction time, but <b>shared_ptr</b> does not.</p> This separates interface from implementation and hides implementation from
<h2><a name="Exception_Safety">Exception Safety</a></h2> translation units which merely use the interface. Examples described in the
<p>Several functions in these smart pointer classes are specified as having "no documentation for specific smart pointers illustrate use of smart pointers in
effect" or "no effect except such-and-such" if an exception is thrown. This these idioms.</p>
means that when an exception is thrown by an object of one of these classes, <p>Note that <b>scoped_ptr</b> requires that <b>T</b> be a complete type at
the entire program state remains the same as it was prior to the function call destruction time, but <b>shared_ptr</b> does not.</p>
which resulted in the exception being thrown. This amounts to a guarantee that <h2><a name="Exception_Safety">Exception Safety</a></h2>
there are no detectable side effects. Other functions never throw exceptions. <p>Several functions in these smart pointer classes are specified as having "no
The only exception ever thrown by functions which do throw (assuming <b>T</b> meets effect" or "no effect except such-and-such" if an exception is thrown. This
the <a href="#common_requirements">common requirements</a>) is <b>std::bad_alloc</b>, means that when an exception is thrown by an object of one of these classes,
and that is thrown only by functions which are explicitly documented as the entire program state remains the same as it was prior to the function call
possibly throwing <b>std::bad_alloc</b>.</p> which resulted in the exception being thrown. This amounts to a guarantee that
<h2><a name="Exception-specifications">Exception-specifications</a></h2> there are no detectable side effects. Other functions never throw exceptions.
<p>Exception-specifications are not used; see <a href="http://www.boost.org/more/lib_guide.htm#Exception-specification"> The only exception ever thrown by functions which do throw (assuming <b>T</b> meets
exception-specification rationale</a>.</p> the <a href="#common_requirements">common requirements</a>) is <b>std::bad_alloc</b>,
<p>All the smart pointer templates contain member functions which can never throw and that is thrown only by functions which are explicitly documented as
exceptions, because they neither throw exceptions themselves nor call other possibly throwing <b>std::bad_alloc</b>.</p>
functions which may throw exceptions. These members are indicated by a comment: <code> <h2><a name="Exception-specifications">Exception-specifications</a></h2>
// never throws</code>. <p>Exception-specifications are not used; see <a href="http://www.boost.org/more/lib_guide.htm#Exception-specification">
</p> exception-specification rationale</a>.</p>
<p>Functions which destroy objects of the pointed to type are prohibited from <p>All the smart pointer templates contain member functions which can never throw
throwing exceptions by the <a href="#common_requirements">common requirements</a>.</p> exceptions, because they neither throw exceptions themselves nor call other
<h2><a name="History">History</a> and Acknowledgements</h2> functions which may throw exceptions. These members are indicated by a comment: <code>
<p>November 2012. Glen Fernandes provided implementations of <b>make_shared</b> // never throws</code>.
and <b>allocate_shared</b> for arrays. They achieve a single allocation for an </p>
array that can be initialized with constructor arguments or initializer lists <p>Functions which destroy objects of the pointed to type are prohibited from
as well as overloads for default initialization and no value initialization. throwing exceptions by the <a href="#common_requirements">common requirements</a>.</p>
See the <a href="make_shared_array.html">make_shared and allocate_shared for <h2><a name="History">History</a> and Acknowledgements</h2>
arrays</a> page for more information.</p> <p>February 2014. Glen Fernandes updated overloads of <b>make_shared</b> and
<p>January 2002. Peter Dimov reworked all four classes, adding features, fixing <b>allocate_shared</b> to conform to the specification in C++ standard paper
bugs, and splitting them into four separate headers, and added <b>weak_ptr</b>. <a href="#D&amp;F-14">[D&amp;F-14]</a>, and implemented <b>make_unique</b> for
See the <a href="compatibility.htm">compatibility</a> page for a summary of the arrays and objects. Peter Dimov and Glen Fernandes updated the scalar and
changes.</p> array implementations, respectively, to resolve C++ standard library defect
<p>May 2001. Vladimir Prus suggested requiring a complete type on destruction. 2070.</p>
Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman <p>November 2012. Glen Fernandes provided implementations of <b>make_shared</b>
Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and and <b>allocate_shared</b> for arrays. They achieve a single allocation for an
others.</p> array that can be initialized with constructor arguments or initializer lists
<p>November 1999. Darin Adler provided <b>operator ==</b>, <b>operator !=</b>, and <b>std::swap</b> as well as overloads for default initialization and no value initialization.
and <b>std::less</b> specializations for shared types.</p> See the <a href="make_shared_array.html">make_shared and allocate_shared for
<p>September 1999. Luis Coelho provided <b>shared_ptr::swap</b> and <b>shared_array::swap</b></p> arrays</a> page for more information.</p>
<p>May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a <p>January 2002. Peter Dimov reworked all four classes, adding features, fixing
number of suggestions resulting in numerous improvements.</p> bugs, and splitting them into four separate headers, and added <b>weak_ptr</b>.
<p>October 1998. Beman Dawes proposed reviving the original semantics under the See the <a href="compatibility.htm">compatibility</a> page for a summary of the
names <b>safe_ptr</b> and <b>counted_ptr</b>, meeting of Per Andersson, Matt changes.</p>
Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar K&uuml;hl, <p>May 2001. Vladimir Prus suggested requiring a complete type on destruction.
Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman
class names were finalized, it was decided that there was no need to exactly Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and
follow the <b>std::auto_ptr</b> interface, and various function signatures and others.</p>
semantics were finalized.</p> <p>November 1999. Darin Adler provided <b>operator ==</b>, <b>operator !=</b>, and <b>std::swap</b>
<p>Over the next three months, several implementations were considered for <b>shared_ptr</b>, and <b>std::less</b> specializations for shared types.</p>
and discussed on the <a href="http://www.boost.org">boost.org</a> mailing list. <p>September 1999. Luis Coelho provided <b>shared_ptr::swap</b> and <b>shared_array::swap</b></p>
The implementation questions revolved around the reference count which must be <p>May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a
kept, either attached to the pointed to object, or detached elsewhere. Each of number of suggestions resulting in numerous improvements.</p>
those variants have themselves two major variants: <p>October 1998. Beman Dawes proposed reviving the original semantics under the
<ul> names <b>safe_ptr</b> and <b>counted_ptr</b>, meeting of Per Andersson, Matt
<li> Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar K&uuml;hl,
Direct detached: the shared_ptr contains a pointer to the object, and a pointer Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new
to the count. class names were finalized, it was decided that there was no need to exactly
<li> follow the <b>std::auto_ptr</b> interface, and various function signatures and
Indirect detached: the shared_ptr contains a pointer to a helper object, which semantics were finalized.</p>
in turn contains a pointer to the object and the count. <p>Over the next three months, several implementations were considered for <b>shared_ptr</b>,
<li> and discussed on the <a href="http://www.boost.org">boost.org</a> mailing list.
Embedded attached: the count is a member of the object pointed to. The implementation questions revolved around the reference count which must be
<li> kept, either attached to the pointed to object, or detached elsewhere. Each of
Placement attached: the count is attached via operator new manipulations.</li> those variants have themselves two major variants:
</ul> <ul>
<p>Each implementation technique has advantages and disadvantages. We went so far <li>
as to run various timings of the direct and indirect approaches, and found that Direct detached: the shared_ptr contains a pointer to the object, and a pointer
at least on Intel Pentium chips there was very little measurable difference. to the count.
Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar <li>
K&uuml;hl suggested an elegant partial template specialization technique to allow Indirect detached: the shared_ptr contains a pointer to a helper object, which
users to choose which implementation they preferred, and that was also in turn contains a pointer to the object and the count.
experimented with.</p> <li>
<p>But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage Embedded attached: the count is a member of the object pointed to.
users", and in the end we choose to supply only the direct implementation.</p> <li>
<p>Summer, 1994. Greg Colvin proposed to the C++ Standards Committee classes named <b>auto_ptr</b> Placement attached: the count is attached via operator new manipulations.</li>
and <b>counted_ptr</b> which were very similar to what we now call <b>scoped_ptr</b> </ul>
and <b>shared_ptr</b>. <a href="#Col-94">[Col-94]</a> In one of the very few <p>Each implementation technique has advantages and disadvantages. We went so far
cases where the Library Working Group's recommendations were not followed by as to run various timings of the direct and indirect approaches, and found that
the full committee, <b>counted_ptr</b> was rejected and surprising at least on Intel Pentium chips there was very little measurable difference.
transfer-of-ownership semantics were added to <b>auto_ptr</b>.</p> Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar
<h2><a name="References">References</a></h2> K&uuml;hl suggested an elegant partial template specialization technique to allow
<p>[<a name="Col-94">Col-94</a>] Gregory Colvin, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1994/N0555.pdf"> users to choose which implementation they preferred, and that was also
Exception Safe Smart Pointers</a>, C++ committee document 94-168/N0555, experimented with.</p>
July, 1994.</p> <p>But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage
<p>[<a name="E&amp;D-94">E&amp;D-94</a>] John R. Ellis &amp; David L. Detlefs, <a href="http://www.usenix.org/publications/library/proceedings/c++94/full_papers/ellis.a"> users", and in the end we choose to supply only the direct implementation.</p>
Safe, Efficient Garbage Collection for C++</a>, Usenix Proceedings, <p>Summer, 1994. Greg Colvin proposed to the C++ Standards Committee classes named <b>auto_ptr</b>
February, 1994. This paper includes an extensive discussion of weak pointers and <b>counted_ptr</b> which were very similar to what we now call <b>scoped_ptr</b>
and an extensive bibliography.</p> and <b>shared_ptr</b>. <a href="#Col-94">[Col-94]</a> In one of the very few
<hr> cases where the Library Working Group's recommendations were not followed by
<p>$Date$</p> the full committee, <b>counted_ptr</b> was rejected and surprising
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. transfer-of-ownership semantics were added to <b>auto_ptr</b>.</p>
Distributed under the Boost Software License, Version 1.0. See accompanying <h2><a name="References">References</a></h2>
file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or copy at <p>[<a name="D&amp;F-14">D&amp;F-14</a>] Peter Dimov &amp; Glen Fernandes, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3870.html">
<A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p> Extending make_shared to Support Arrays, Revision 1</a>, C++ committee document N3870,
</body> January, 2014.</p>
<p>[<a name="Col-94">Col-94</a>] Gregory Colvin, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1994/N0555.pdf">
Exception Safe Smart Pointers</a>, C++ committee document 94-168/N0555,
July, 1994.</p>
<p>[<a name="E&amp;D-94">E&amp;D-94</a>] John R. Ellis &amp; David L. Detlefs, <a href="http://www.usenix.org/publications/library/proceedings/c++94/full_papers/ellis.a">
Safe, Efficient Garbage Collection for C++</a>, Usenix Proceedings,
February, 1994. This paper includes an extensive discussion of weak pointers
and an extensive bibliography.</p>
<hr>
<p>$Date$</p>
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
Distributed under the Boost Software License, Version 1.0. See accompanying
file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or copy at
<A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html> </html>

View File

@@ -7,9 +7,9 @@
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> </head>
<body bgcolor="#FFFFFF"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" WIDTH="277" HEIGHT="86">Smart Pointer Timings</h1> <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle" border="0">Smart Pointer Timings</h1>
<p>In late January 2000, Mark Borgerding put forward a suggestion to boost for <p>In late January 2000, Mark Borgerding put forward a suggestion to boost for
a new design of smart pointer whereby an intrusive doubly linked list is used a new design of smart pointer whereby an intrusive doubly linked list is used
@@ -533,9 +533,8 @@ Gavin Collings,
spreads its information as in the case of linked pointer.</li> spreads its information as in the case of linked pointer.</li>
</ul> </ul>
<hr> <hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->19 August 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" --> <p>$Date$</p>
</p> <p>&copy; Copyright Gavin Collings 2000. Permission to copy, use, modify, sell
<p><EFBFBD> Copyright Gavin Collings 2000. Permission to copy, use, modify, sell
and distribute this document is granted provided this copyright notice appears in all and distribute this document is granted provided this copyright notice appears in all
copies. This document is provided &quot;as is&quot; without express or implied warranty, copies. This document is provided &quot;as is&quot; without express or implied warranty,
and with no claim as to its suitability for any purpose.</p> and with no claim as to its suitability for any purpose.</p>

View File

@@ -1,67 +1,67 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>Smart Pointer Programming Techniques</title> <title>Smart Pointer Programming Techniques</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> </head>
<body text="#000000" bgColor="#ffffff"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle" <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
border="0"></A>Smart Pointer Programming Techniques</h1> width="277" align="middle" border="0">Smart Pointer Programming Techniques</h1>
<p><A href="#incomplete">Using incomplete classes for implementation hiding</A><br> <p><A href="#incomplete">Using incomplete classes for implementation hiding</A><br>
<A href="#pimpl">The "Pimpl" idiom</A><br> <A href="#pimpl">The "Pimpl" idiom</A><br>
<A href="#abstract">Using abstract classes for implementation hiding</A><br> <A href="#abstract">Using abstract classes for implementation hiding</A><br>
<A href="#preventing_delete">Preventing <code>delete px.get()</code></A><br> <A href="#preventing_delete">Preventing <code>delete px.get()</code></A><br>
<A href="#array">Using a <code>shared_ptr</code> to hold a pointer to an array</A><br> <A href="#array">Using a <code>shared_ptr</code> to hold a pointer to an array</A><br>
<A href="#encapsulation">Encapsulating allocation details, wrapping factory <A href="#encapsulation">Encapsulating allocation details, wrapping factory
functions</A><br> functions</A><br>
<A href="#static">Using a <code>shared_ptr</code> to hold a pointer to a statically <A href="#static">Using a <code>shared_ptr</code> to hold a pointer to a statically
allocated object</A><br> allocated object</A><br>
<A href="#com">Using a <code>shared_ptr</code> to hold a pointer to a COM object</A><br> <A href="#com">Using a <code>shared_ptr</code> to hold a pointer to a COM object</A><br>
<A href="#intrusive">Using a <code>shared_ptr</code> to hold a pointer to an object <A href="#intrusive">Using a <code>shared_ptr</code> to hold a pointer to an object
with an embedded reference count</A><br> with an embedded reference count</A><br>
<A href="#another_sp">Using a <code>shared_ptr</code> to hold another shared <A href="#another_sp">Using a <code>shared_ptr</code> to hold another shared
ownership smart pointer</A><br> ownership smart pointer</A><br>
<A href="#from_raw">Obtaining a <code>shared_ptr</code> from a raw pointer</A><br> <A href="#from_raw">Obtaining a <code>shared_ptr</code> from a raw pointer</A><br>
<A href="#in_constructor">Obtaining a <code>shared_ptr</code> (<code>weak_ptr</code>) <A href="#in_constructor">Obtaining a <code>shared_ptr</code> (<code>weak_ptr</code>)
to <code>this</code> in a constructor</A><br> to <code>this</code> in a constructor</A><br>
<A href="#from_this">Obtaining a <code>shared_ptr</code> to <code>this</code></A><br> <A href="#from_this">Obtaining a <code>shared_ptr</code> to <code>this</code></A><br>
<A href="#handle">Using <code>shared_ptr</code> as a smart counted handle</A><br> <A href="#handle">Using <code>shared_ptr</code> as a smart counted handle</A><br>
<A href="#on_block_exit">Using <code>shared_ptr</code> to execute code on block <A href="#on_block_exit">Using <code>shared_ptr</code> to execute code on block
exit</A><br> exit</A><br>
<A href="#pvoid">Using <code>shared_ptr&lt;void&gt;</code> to hold an arbitrary <A href="#pvoid">Using <code>shared_ptr&lt;void&gt;</code> to hold an arbitrary
object</A><br> object</A><br>
<A href="#extra_data">Associating arbitrary data with heterogeneous <code>shared_ptr</code> <A href="#extra_data">Associating arbitrary data with heterogeneous <code>shared_ptr</code>
instances</A><br> instances</A><br>
<A href="#as_lock">Using <code>shared_ptr</code> as a CopyConstructible mutex lock</A><br> <A href="#as_lock">Using <code>shared_ptr</code> as a CopyConstructible mutex lock</A><br>
<A href="#wrapper">Using <code>shared_ptr</code> to wrap member function calls</A><br> <A href="#wrapper">Using <code>shared_ptr</code> to wrap member function calls</A><br>
<A href="#delayed">Delayed deallocation</A><br> <A href="#delayed">Delayed deallocation</A><br>
<A href="#weak_without_shared">Weak pointers to objects not managed by a <code>shared_ptr</code></A><br> <A href="#weak_without_shared">Weak pointers to objects not managed by a <code>shared_ptr</code></A><br>
</p> </p>
<h2><A name="incomplete">Using incomplete classes for implementation hiding</A></h2> <h2><A name="incomplete">Using incomplete classes for implementation hiding</A></h2>
<p>A proven technique (that works in C, too) for separating interface from <p>A proven technique (that works in C, too) for separating interface from
implementation is to use a pointer to an incomplete class as an opaque handle:</p> implementation is to use a pointer to an incomplete class as an opaque handle:</p>
<pre>class FILE; <pre>class FILE;
FILE * fopen(char const * name, char const * mode); FILE * fopen(char const * name, char const * mode);
void fread(FILE * f, void * data, size_t size); void fread(FILE * f, void * data, size_t size);
void fclose(FILE * f); void fclose(FILE * f);
</pre> </pre>
<p>It is possible to express the above interface using <code>shared_ptr</code>, <p>It is possible to express the above interface using <code>shared_ptr</code>,
eliminating the need to manually call <code>fclose</code>:</p> eliminating the need to manually call <code>fclose</code>:</p>
<pre>class FILE; <pre>class FILE;
shared_ptr&lt;FILE&gt; fopen(char const * name, char const * mode); shared_ptr&lt;FILE&gt; fopen(char const * name, char const * mode);
void fread(shared_ptr&lt;FILE&gt; f, void * data, size_t size); void fread(shared_ptr&lt;FILE&gt; f, void * data, size_t size);
</pre> </pre>
<p>This technique relies on <code>shared_ptr</code>'s ability to execute a custom <p>This technique relies on <code>shared_ptr</code>'s ability to execute a custom
deleter, eliminating the explicit call to <code>fclose</code>, and on the fact deleter, eliminating the explicit call to <code>fclose</code>, and on the fact
that <code>shared_ptr&lt;X&gt;</code> can be copied and destroyed when <code>X</code> that <code>shared_ptr&lt;X&gt;</code> can be copied and destroyed when <code>X</code>
is incomplete.</p> is incomplete.</p>
<h2><A name="pimpl">The "Pimpl" idiom</A></h2> <h2><A name="pimpl">The "Pimpl" idiom</A></h2>
<p>A C++ specific variation of the incomplete class pattern is the "Pimpl" idiom. <p>A C++ specific variation of the incomplete class pattern is the "Pimpl" idiom.
The incomplete class is not exposed to the user; it is hidden behind a The incomplete class is not exposed to the user; it is hidden behind a
forwarding facade. <code>shared_ptr</code> can be used to implement a "Pimpl":</p> forwarding facade. <code>shared_ptr</code> can be used to implement a "Pimpl":</p>
<pre>// file.hpp: <pre>// file.hpp:
class file class file
{ {
@@ -79,7 +79,7 @@ public:
void read(void * data, size_t size); void read(void * data, size_t size);
}; };
</pre> </pre>
<pre>// file.cpp: <pre>// file.cpp:
#include "file.hpp" #include "file.hpp"
@@ -108,17 +108,17 @@ void file::read(void * data, size_t size)
pimpl_-&gt;read(data, size); pimpl_-&gt;read(data, size);
} }
</pre> </pre>
<p>The key thing to note here is that the compiler-generated copy constructor, <p>The key thing to note here is that the compiler-generated copy constructor,
assignment operator, and destructor all have a sensible meaning. As a result, <code> assignment operator, and destructor all have a sensible meaning. As a result, <code>
file</code> is <code>CopyConstructible</code> and <code>Assignable</code>, file</code> is <code>CopyConstructible</code> and <code>Assignable</code>,
allowing its use in standard containers.</p> allowing its use in standard containers.</p>
<h2><A name="abstract">Using abstract classes for implementation hiding</A></h2> <h2><A name="abstract">Using abstract classes for implementation hiding</A></h2>
<p>Another widely used C++ idiom for separating inteface and implementation is to <p>Another widely used C++ idiom for separating inteface and implementation is to
use abstract base classes and factory functions. The abstract classes are use abstract base classes and factory functions. The abstract classes are
sometimes called "interfaces" and the pattern is known as "interface-based sometimes called "interfaces" and the pattern is known as "interface-based
programming". Again, <code>shared_ptr</code> can be used as the return type of programming". Again, <code>shared_ptr</code> can be used as the return type of
the factory functions:</p> the factory functions:</p>
<pre>// X.hpp: <pre>// X.hpp:
class X class X
{ {
@@ -134,7 +134,7 @@ protected:
shared_ptr&lt;X&gt; createX(); shared_ptr&lt;X&gt; createX();
</pre> </pre>
<pre>-- X.cpp: <pre>-- X.cpp:
class X_impl: public X class X_impl: public X
{ {
@@ -162,18 +162,18 @@ shared_ptr&lt;X&gt; createX()
return px; return px;
} }
</pre> </pre>
<p>A key property of shared_ptr is that the allocation, construction, deallocation, <p>A key property of shared_ptr is that the allocation, construction, deallocation,
and destruction details are captured at the point of construction, inside the and destruction details are captured at the point of construction, inside the
factory function. Note the protected and nonvirtual destructor in the example factory function. Note the protected and nonvirtual destructor in the example
above. The client code cannot, and does not need to, delete a pointer to <code>X</code>; above. The client code cannot, and does not need to, delete a pointer to <code>X</code>;
the <code>shared_ptr&lt;X&gt;</code> instance returned from <code>createX</code> the <code>shared_ptr&lt;X&gt;</code> instance returned from <code>createX</code>
will correctly call <code>~X_impl</code>.</p> will correctly call <code>~X_impl</code>.</p>
<h2><A name="preventing_delete">Preventing <code>delete px.get()</code></A></h2> <h2><A name="preventing_delete">Preventing <code>delete px.get()</code></A></h2>
<p>It is often desirable to prevent client code from deleting a pointer that is <p>It is often desirable to prevent client code from deleting a pointer that is
being managed by <code>shared_ptr</code>. The previous technique showed one being managed by <code>shared_ptr</code>. The previous technique showed one
possible approach, using a protected destructor. Another alternative is to use possible approach, using a protected destructor. Another alternative is to use
a private deleter:</p> a private deleter:</p>
<pre>class X <pre>class X
{ {
private: private:
@@ -198,48 +198,48 @@ public:
} }
}; };
</pre> </pre>
<h2><A name="array">Using a <code>shared_ptr</code> to hold a pointer to an array</A></h2> <h2><A name="array">Using a <code>shared_ptr</code> to hold a pointer to an array</A></h2>
<p>A <code>shared_ptr</code> can be used to hold a pointer to an array allocated <p>A <code>shared_ptr</code> can be used to hold a pointer to an array allocated
with <code>new[]</code>:</p> with <code>new[]</code>:</p>
<pre>shared_ptr&lt;X&gt; px(new X[1], <A href="../utility/checked_delete.html" >checked_array_deleter</A>&lt;X&gt;()); <pre>shared_ptr&lt;X&gt; px(new X[1], <A href="../utility/checked_delete.html" >checked_array_deleter</A>&lt;X&gt;());
</pre> </pre>
<p>Note, however, that <code><A href="shared_array.htm">shared_array</A></code> is <p>Note, however, that <code><A href="shared_array.htm">shared_array</A></code> is
often preferable, if this is an option. It has an array-specific interface, often preferable, if this is an option. It has an array-specific interface,
without <code>operator*</code> and <code>operator-&gt;</code>, and does not without <code>operator*</code> and <code>operator-&gt;</code>, and does not
allow pointer conversions.</p> allow pointer conversions.</p>
<h2><A name="encapsulation">Encapsulating allocation details, wrapping factory <h2><A name="encapsulation">Encapsulating allocation details, wrapping factory
functions</A></h2> functions</A></h2>
<p><code>shared_ptr</code> can be used in creating C++ wrappers over existing C <p><code>shared_ptr</code> can be used in creating C++ wrappers over existing C
style library interfaces that return raw pointers from their factory functions style library interfaces that return raw pointers from their factory functions
to encapsulate allocation details. As an example, consider this interface, to encapsulate allocation details. As an example, consider this interface,
where <code>CreateX</code> might allocate <code>X</code> from its own private where <code>CreateX</code> might allocate <code>X</code> from its own private
heap, <code>~X</code> may be inaccessible, or <code>X</code> may be incomplete:</p> heap, <code>~X</code> may be inaccessible, or <code>X</code> may be incomplete:</p>
<pre>X * CreateX(); <pre>X * CreateX();
void DestroyX(X *); void DestroyX(X *);
</pre> </pre>
<p>The only way to reliably destroy a pointer returned by <code>CreateX</code> is <p>The only way to reliably destroy a pointer returned by <code>CreateX</code> is
to call <code>DestroyX</code>.</p> to call <code>DestroyX</code>.</p>
<P>Here is how a <code>shared_ptr</code>-based wrapper may look like:</P> <P>Here is how a <code>shared_ptr</code>-based wrapper may look like:</P>
<pre>shared_ptr&lt;X&gt; createX() <pre>shared_ptr&lt;X&gt; createX()
{ {
shared_ptr&lt;X&gt; px(CreateX(), DestroyX); shared_ptr&lt;X&gt; px(CreateX(), DestroyX);
return px; return px;
} }
</pre> </pre>
<p>Client code that calls <code>createX</code> still does not need to know how the <p>Client code that calls <code>createX</code> still does not need to know how the
object has been allocated, but now the destruction is automatic.</p> object has been allocated, but now the destruction is automatic.</p>
<h2><A name="static">Using a <code>shared_ptr</code> to hold a pointer to a statically <h2><A name="static">Using a <code>shared_ptr</code> to hold a pointer to a statically
allocated object</A></h2> allocated object</A></h2>
<p>Sometimes it is desirable to create a <code>shared_ptr</code> to an already <p>Sometimes it is desirable to create a <code>shared_ptr</code> to an already
existing object, so that the <code>shared_ptr</code> does not attempt to existing object, so that the <code>shared_ptr</code> does not attempt to
destroy the object when there are no more references left. As an example, the destroy the object when there are no more references left. As an example, the
factory function:</p> factory function:</p>
<pre>shared_ptr&lt;X&gt; createX(); <pre>shared_ptr&lt;X&gt; createX();
</pre> </pre>
<p>in certain situations may need to return a pointer to a statically allocated <code>X</code> <p>in certain situations may need to return a pointer to a statically allocated <code>X</code>
instance.</p> instance.</p>
<P>The solution is to use a custom deleter that does nothing:</P> <P>The solution is to use a custom deleter that does nothing:</P>
<pre>struct null_deleter <pre>struct null_deleter
{ {
void operator()(void const *) const void operator()(void const *) const
{ {
@@ -254,33 +254,33 @@ shared_ptr&lt;X&gt; createX()
return px; return px;
} }
</pre> </pre>
<p>The same technique works for any object known to outlive the pointer.</p> <p>The same technique works for any object known to outlive the pointer.</p>
<h2><A name="com">Using a <code>shared_ptr</code> to hold a pointer to a COM Object</A></h2> <h2><A name="com">Using a <code>shared_ptr</code> to hold a pointer to a COM Object</A></h2>
<p>Background: COM objects have an embedded reference count and two member <p>Background: COM objects have an embedded reference count and two member
functions that manipulate it. <code>AddRef()</code> increments the count. <code>Release()</code> functions that manipulate it. <code>AddRef()</code> increments the count. <code>Release()</code>
decrements the count and destroys itself when the count drops to zero.</p> decrements the count and destroys itself when the count drops to zero.</p>
<P>It is possible to hold a pointer to a COM object in a <code>shared_ptr</code>:</P> <P>It is possible to hold a pointer to a COM object in a <code>shared_ptr</code>:</P>
<pre>shared_ptr&lt;IWhatever&gt; make_shared_from_COM(IWhatever * p) <pre>shared_ptr&lt;IWhatever&gt; make_shared_from_COM(IWhatever * p)
{ {
p-&gt;AddRef(); p-&gt;AddRef();
shared_ptr&lt;IWhatever&gt; pw(p, <A href="../bind/mem_fn.html" >mem_fn</A>(&amp;IWhatever::Release)); shared_ptr&lt;IWhatever&gt; pw(p, <A href="../bind/mem_fn.html" >mem_fn</A>(&amp;IWhatever::Release));
return pw; return pw;
} }
</pre> </pre>
<p>Note, however, that <code>shared_ptr</code> copies created from <code>pw</code> will <p>Note, however, that <code>shared_ptr</code> copies created from <code>pw</code> will
not "register" in the embedded count of the COM object; they will share the not "register" in the embedded count of the COM object; they will share the
single reference created in <code>make_shared_from_COM</code>. Weak pointers single reference created in <code>make_shared_from_COM</code>. Weak pointers
created from <code>pw</code> will be invalidated when the last <code>shared_ptr</code> created from <code>pw</code> will be invalidated when the last <code>shared_ptr</code>
is destroyed, regardless of whether the COM object itself is still alive.</p> is destroyed, regardless of whether the COM object itself is still alive.</p>
<P>As <A href="../bind/mem_fn.html#Q3">explained</A> in the <code>mem_fn</code> documentation, <P>As <A href="../bind/mem_fn.html#Q3">explained</A> in the <code>mem_fn</code> documentation,
you need to <A href="../bind/mem_fn.html#stdcall">#define you need to <A href="../bind/mem_fn.html#stdcall">#define
BOOST_MEM_FN_ENABLE_STDCALL</A> first.</P> BOOST_MEM_FN_ENABLE_STDCALL</A> first.</P>
<h2><A name="intrusive">Using a <code>shared_ptr</code> to hold a pointer to an object <h2><A name="intrusive">Using a <code>shared_ptr</code> to hold a pointer to an object
with an embedded reference count</A></h2> with an embedded reference count</A></h2>
<p>This is a generalization of the above technique. The example assumes that the <p>This is a generalization of the above technique. The example assumes that the
object implements the two functions required by <code><A href="intrusive_ptr.html">intrusive_ptr</A></code>, object implements the two functions required by <code><A href="intrusive_ptr.html">intrusive_ptr</A></code>,
<code>intrusive_ptr_add_ref</code> and <code>intrusive_ptr_release</code>:</p> <code>intrusive_ptr_add_ref</code> and <code>intrusive_ptr_release</code>:</p>
<pre>template&lt;class T&gt; struct intrusive_deleter <pre>template&lt;class T&gt; struct intrusive_deleter
{ {
void operator()(T * p) void operator()(T * p)
{ {
@@ -295,15 +295,15 @@ shared_ptr&lt;X&gt; make_shared_from_intrusive(X * p)
return px; return px;
} }
</pre> </pre>
<h2><A name="another_sp">Using a <code>shared_ptr</code> to hold another shared <h2><A name="another_sp">Using a <code>shared_ptr</code> to hold another shared
ownership smart pointer</A></h2> ownership smart pointer</A></h2>
<p>One of the design goals of <code>shared_ptr</code> is to be used in library <p>One of the design goals of <code>shared_ptr</code> is to be used in library
interfaces. It is possible to encounter a situation where a library takes a <code>shared_ptr</code> interfaces. It is possible to encounter a situation where a library takes a <code>shared_ptr</code>
argument, but the object at hand is being managed by a different reference argument, but the object at hand is being managed by a different reference
counted or linked smart pointer.</p> counted or linked smart pointer.</p>
<P>It is possible to exploit <code>shared_ptr</code>'s custom deleter feature to <P>It is possible to exploit <code>shared_ptr</code>'s custom deleter feature to
wrap this existing smart pointer behind a <code>shared_ptr</code> facade:</P> wrap this existing smart pointer behind a <code>shared_ptr</code> facade:</P>
<pre>template&lt;class P&gt; struct smart_pointer_deleter <pre>template&lt;class P&gt; struct smart_pointer_deleter
{ {
private: private:
@@ -332,17 +332,17 @@ shared_ptr&lt;X&gt; make_shared_from_another(another_ptr&lt;X&gt; qx)
return px; return px;
} }
</pre> </pre>
<p>One subtle point is that deleters are not allowed to throw exceptions, and the <p>One subtle point is that deleters are not allowed to throw exceptions, and the
above example as written assumes that <code>p_.reset()</code> doesn't throw. If above example as written assumes that <code>p_.reset()</code> doesn't throw. If
this is not the case, <code>p_.reset()</code> should be wrapped in a <code>try {} this is not the case, <code>p_.reset()</code> should be wrapped in a <code>try {}
catch(...) {}</code> block that ignores exceptions. In the (usually catch(...) {}</code> block that ignores exceptions. In the (usually
unlikely) event when an exception is thrown and ignored, <code>p_</code> will unlikely) event when an exception is thrown and ignored, <code>p_</code> will
be released when the lifetime of the deleter ends. This happens when all be released when the lifetime of the deleter ends. This happens when all
references, including weak pointers, are destroyed or reset.</p> references, including weak pointers, are destroyed or reset.</p>
<P>Another twist is that it is possible, given the above <code>shared_ptr</code> instance, <P>Another twist is that it is possible, given the above <code>shared_ptr</code> instance,
to recover the original smart pointer, using <code><A href="shared_ptr.htm#get_deleter"> to recover the original smart pointer, using <code><A href="shared_ptr.htm#get_deleter">
get_deleter</A></code>:</P> get_deleter</A></code>:</P>
<pre>void extract_another_from_shared(shared_ptr&lt;X&gt; px) <pre>void extract_another_from_shared(shared_ptr&lt;X&gt; px)
{ {
typedef smart_pointer_deleter&lt; another_ptr&lt;X&gt; &gt; deleter; typedef smart_pointer_deleter&lt; another_ptr&lt;X&gt; &gt; deleter;
@@ -356,37 +356,37 @@ shared_ptr&lt;X&gt; make_shared_from_another(another_ptr&lt;X&gt; qx)
} }
} }
</pre> </pre>
<h2><A name="from_raw">Obtaining a <code>shared_ptr</code> from a raw pointer</A></h2> <h2><A name="from_raw">Obtaining a <code>shared_ptr</code> from a raw pointer</A></h2>
<p>Sometimes it is necessary to obtain a <code>shared_ptr</code> given a raw <p>Sometimes it is necessary to obtain a <code>shared_ptr</code> given a raw
pointer to an object that is already managed by another <code>shared_ptr</code> pointer to an object that is already managed by another <code>shared_ptr</code>
instance. Example:</p> instance. Example:</p>
<pre>void f(X * p) <pre>void f(X * p)
{ {
shared_ptr&lt;X&gt; px(<i>???</i>); shared_ptr&lt;X&gt; px(<i>???</i>);
} }
</pre> </pre>
<p>Inside <code>f</code>, we'd like to create a <code>shared_ptr</code> to <code>*p</code>.</p> <p>Inside <code>f</code>, we'd like to create a <code>shared_ptr</code> to <code>*p</code>.</p>
<P>In the general case, this problem has no solution. One approach is to modify <code>f</code> <P>In the general case, this problem has no solution. One approach is to modify <code>f</code>
to take a <code>shared_ptr</code>, if possible:</P> to take a <code>shared_ptr</code>, if possible:</P>
<pre>void f(shared_ptr&lt;X&gt; px); <pre>void f(shared_ptr&lt;X&gt; px);
</pre> </pre>
<p>The same transformation can be used for nonvirtual member functions, to convert <p>The same transformation can be used for nonvirtual member functions, to convert
the implicit <code>this</code>:</p> the implicit <code>this</code>:</p>
<pre>void X::f(int m); <pre>void X::f(int m);
</pre> </pre>
<p>would become a free function with a <code>shared_ptr</code> first argument:</p> <p>would become a free function with a <code>shared_ptr</code> first argument:</p>
<pre>void f(shared_ptr&lt;X&gt; this_, int m); <pre>void f(shared_ptr&lt;X&gt; this_, int m);
</pre> </pre>
<p>If <code>f</code> cannot be changed, but <code>X</code> uses intrusive counting, <p>If <code>f</code> cannot be changed, but <code>X</code> uses intrusive counting,
use <code><A href="#intrusive">make_shared_from_intrusive</A></code> described use <code><A href="#intrusive">make_shared_from_intrusive</A></code> described
above. Or, if it's known that the <code>shared_ptr</code> created in <code>f</code> above. Or, if it's known that the <code>shared_ptr</code> created in <code>f</code>
will never outlive the object, use <A href="#static">a null deleter</A>.</p> will never outlive the object, use <A href="#static">a null deleter</A>.</p>
<h2><A name="in_constructor">Obtaining a <code>shared_ptr</code> (<code>weak_ptr</code>) <h2><A name="in_constructor">Obtaining a <code>shared_ptr</code> (<code>weak_ptr</code>)
to <code>this</code> in a constructor</A></h2> to <code>this</code> in a constructor</A></h2>
<p>Some designs require objects to register themselves on construction with a <p>Some designs require objects to register themselves on construction with a
central authority. When the registration routines take a shared_ptr, this leads central authority. When the registration routines take a shared_ptr, this leads
to the question how could a constructor obtain a shared_ptr to this:</p> to the question how could a constructor obtain a shared_ptr to this:</p>
<pre>class X <pre>class X
{ {
public: public:
@@ -396,19 +396,19 @@ public:
} }
}; };
</pre> </pre>
<p>In the general case, the problem cannot be solved. The <code>X</code> instance <p>In the general case, the problem cannot be solved. The <code>X</code> instance
being constructed can be an automatic variable or a static variable; it can be being constructed can be an automatic variable or a static variable; it can be
created on the heap:</p> created on the heap:</p>
<pre>shared_ptr&lt;X&gt; px(new X);</pre> <pre>shared_ptr&lt;X&gt; px(new X);</pre>
<P>but at construction time, <code>px</code> does not exist yet, and it is <P>but at construction time, <code>px</code> does not exist yet, and it is
impossible to create another <code>shared_ptr</code> instance that shares impossible to create another <code>shared_ptr</code> instance that shares
ownership with it.</P> ownership with it.</P>
<P>Depending on context, if the inner <code>shared_ptr</code> <code>this_</code> doesn't <P>Depending on context, if the inner <code>shared_ptr</code> <code>this_</code> doesn't
need to keep the object alive, use a <code>null_deleter</code> as explained <A href="#static"> need to keep the object alive, use a <code>null_deleter</code> as explained <A href="#static">
here</A> and <A href="#weak_without_shared">here</A>. If <code>X</code> is here</A> and <A href="#weak_without_shared">here</A>. If <code>X</code> is
supposed to always live on the heap, and be managed by a <code>shared_ptr</code>, supposed to always live on the heap, and be managed by a <code>shared_ptr</code>,
use a static factory function:</P> use a static factory function:</P>
<pre>class X <pre>class X
{ {
private: private:
@@ -424,13 +424,13 @@ public:
} }
}; };
</pre> </pre>
<h2><A name="from_this">Obtaining a <code>shared_ptr</code> to <code>this</code></A></h2> <h2><A name="from_this">Obtaining a <code>shared_ptr</code> to <code>this</code></A></h2>
<p>Sometimes it is needed to obtain a <code>shared_ptr</code> from <code>this</code> <p>Sometimes it is needed to obtain a <code>shared_ptr</code> from <code>this</code>
in a virtual member function under the assumption that <code>this</code> is in a virtual member function under the assumption that <code>this</code> is
already managed by a <code>shared_ptr</code>. The transformations <A href="#from_raw"> already managed by a <code>shared_ptr</code>. The transformations <A href="#from_raw">
described in the previous technique</A> cannot be applied.</p> described in the previous technique</A> cannot be applied.</p>
<P>A typical example:</P> <P>A typical example:</P>
<pre>class X <pre>class X
{ {
public: public:
@@ -469,8 +469,8 @@ public:
} }
}; };
</pre> </pre>
<p>The solution is to keep a weak pointer to <code>this</code> as a member in <code>impl</code>:</p> <p>The solution is to keep a weak pointer to <code>this</code> as a member in <code>impl</code>:</p>
<pre>class impl: public X, public Y <pre>class impl: public X, public Y
{ {
private: private:
@@ -499,10 +499,10 @@ public:
} }
}; };
</pre> </pre>
<p>The library now includes a helper class template <code><A href="enable_shared_from_this.html"> <p>The library now includes a helper class template <code><A href="enable_shared_from_this.html">
enable_shared_from_this</A></code> that can be used to encapsulate the enable_shared_from_this</A></code> that can be used to encapsulate the
solution:</p> solution:</p>
<pre>class impl: public X, public Y, public enable_shared_from_this&lt;impl&gt; <pre>class impl: public X, public Y, public enable_shared_from_this&lt;impl&gt;
{ {
public: public:
@@ -519,19 +519,19 @@ public:
} }
} }
</pre> </pre>
<p>Note that you no longer need to manually initialize the <code>weak_ptr</code> member <p>Note that you no longer need to manually initialize the <code>weak_ptr</code> member
in <code><A href="enable_shared_from_this.html">enable_shared_from_this</A></code>. in <code><A href="enable_shared_from_this.html">enable_shared_from_this</A></code>.
Constructing a <code>shared_ptr</code> to <code>impl</code> takes care of that.</p> Constructing a <code>shared_ptr</code> to <code>impl</code> takes care of that.</p>
<h2><A name="handle">Using <code>shared_ptr</code> as a smart counted handle</A></h2> <h2><A name="handle">Using <code>shared_ptr</code> as a smart counted handle</A></h2>
<p>Some library interfaces use opaque handles, a variation of the <A href="#incomplete"> <p>Some library interfaces use opaque handles, a variation of the <A href="#incomplete">
incomplete class technique</A> described above. An example:</p> incomplete class technique</A> described above. An example:</p>
<pre>typedef void * HANDLE; <pre>typedef void * HANDLE;
HANDLE CreateProcess(); HANDLE CreateProcess();
void CloseHandle(HANDLE); void CloseHandle(HANDLE);
</pre> </pre>
<p>Instead of a raw pointer, it is possible to use <code>shared_ptr</code> as the <p>Instead of a raw pointer, it is possible to use <code>shared_ptr</code> as the
handle and get reference counting and automatic resource management for free:</p> handle and get reference counting and automatic resource management for free:</p>
<pre>typedef shared_ptr&lt;void&gt; handle; <pre>typedef shared_ptr&lt;void&gt; handle;
handle createProcess() handle createProcess()
{ {
@@ -539,42 +539,42 @@ handle createProcess()
return pv; return pv;
} }
</pre> </pre>
<h2><A name="on_block_exit">Using <code>shared_ptr</code> to execute code on block exit</A></h2> <h2><A name="on_block_exit">Using <code>shared_ptr</code> to execute code on block exit</A></h2>
<p><code>shared_ptr&lt;void&gt;</code> can automatically execute cleanup code when <p><code>shared_ptr&lt;void&gt;</code> can automatically execute cleanup code when
control leaves a scope.</p> control leaves a scope.</p>
<UL> <UL>
<LI> <LI>
Executing <code>f(p)</code>, where <code>p</code> is a pointer:</LI></UL> Executing <code>f(p)</code>, where <code>p</code> is a pointer:</LI></UL>
<pre> shared_ptr&lt;void&gt; guard(p, f); <pre> shared_ptr&lt;void&gt; guard(p, f);
</pre> </pre>
<UL> <UL>
<LI> <LI>
Executing arbitrary code: <code>f(x, y)</code>:</LI></UL> Executing arbitrary code: <code>f(x, y)</code>:</LI></UL>
<pre> shared_ptr&lt;void&gt; guard(static_cast&lt;void*&gt;(0), <A href="../bind/bind.html" >bind</A>(f, x, y)); <pre> shared_ptr&lt;void&gt; guard(static_cast&lt;void*&gt;(0), <A href="../bind/bind.html" >bind</A>(f, x, y));
</pre> </pre>
<P>For a more thorough treatment, see the article "Simplify Your Exception-Safe <P>For a more thorough treatment, see the article "Simplify Your Exception-Safe
Code" by Andrei Alexandrescu and Petru Marginean, available online at <A href="http://www.cuj.com/experts/1812/alexandr.htm?topic=experts"> Code" by Andrei Alexandrescu and Petru Marginean, available online at <A href="http://www.cuj.com/experts/1812/alexandr.htm?topic=experts">
http://www.cuj.com/experts/1812/alexandr.htm?topic=experts</A>.</P> http://www.cuj.com/experts/1812/alexandr.htm?topic=experts</A>.</P>
<h2><A name="pvoid">Using <code>shared_ptr&lt;void&gt;</code> to hold an arbitrary <h2><A name="pvoid">Using <code>shared_ptr&lt;void&gt;</code> to hold an arbitrary
object</A></h2> object</A></h2>
<p><code>shared_ptr&lt;void&gt;</code> can act as a generic object pointer similar <p><code>shared_ptr&lt;void&gt;</code> can act as a generic object pointer similar
to <code>void*</code>. When a <code>shared_ptr&lt;void&gt;</code> instance to <code>void*</code>. When a <code>shared_ptr&lt;void&gt;</code> instance
constructed as:</p> constructed as:</p>
<pre> shared_ptr&lt;void&gt; pv(new X); <pre> shared_ptr&lt;void&gt; pv(new X);
</pre> </pre>
<p>is destroyed, it will correctly dispose of the <code>X</code> object by <p>is destroyed, it will correctly dispose of the <code>X</code> object by
executing <code>~X</code>.</p> executing <code>~X</code>.</p>
<p>This propery can be used in much the same manner as a raw <code>void*</code> is <p>This propery can be used in much the same manner as a raw <code>void*</code> is
used to temporarily strip type information from an object pointer. A <code>shared_ptr&lt;void&gt;</code> used to temporarily strip type information from an object pointer. A <code>shared_ptr&lt;void&gt;</code>
can later be cast back to the correct type by using <code><A href="shared_ptr.htm#static_pointer_cast"> can later be cast back to the correct type by using <code><A href="shared_ptr.htm#static_pointer_cast">
static_pointer_cast</A></code>.</p> static_pointer_cast</A></code>.</p>
<h2><A name="extra_data">Associating arbitrary data with heterogeneous <code>shared_ptr</code> <h2><A name="extra_data">Associating arbitrary data with heterogeneous <code>shared_ptr</code>
instances</A></h2> instances</A></h2>
<p><code>shared_ptr</code> and <code>weak_ptr</code> support <code>operator&lt;</code> <p><code>shared_ptr</code> and <code>weak_ptr</code> support <code>operator&lt;</code>
comparisons required by standard associative containers such as <code>std::map</code>. comparisons required by standard associative containers such as <code>std::map</code>.
This can be used to non-intrusively associate arbitrary data with objects This can be used to non-intrusively associate arbitrary data with objects
managed by <code>shared_ptr</code>:</p> managed by <code>shared_ptr</code>:</p>
<pre>typedef int Data; <pre>typedef int Data;
std::map&lt; shared_ptr&lt;void&gt;, Data &gt; userData; std::map&lt; shared_ptr&lt;void&gt;, Data &gt; userData;
// or std::map&lt; weak_ptr&lt;void&gt;, Data &gt; userData; to not affect the lifetime // or std::map&lt; weak_ptr&lt;void&gt;, Data &gt; userData; to not affect the lifetime
@@ -585,11 +585,11 @@ shared_ptr&lt;int&gt; pi(new int(3));
userData[px] = 42; userData[px] = 42;
userData[pi] = 91; userData[pi] = 91;
</pre> </pre>
<h2><A name="as_lock">Using <code>shared_ptr</code> as a CopyConstructible mutex lock</A></h2> <h2><A name="as_lock">Using <code>shared_ptr</code> as a CopyConstructible mutex lock</A></h2>
<p>Sometimes it's necessary to return a mutex lock from a function, and a <p>Sometimes it's necessary to return a mutex lock from a function, and a
noncopyable lock cannot be returned by value. It is possible to use <code>shared_ptr</code> noncopyable lock cannot be returned by value. It is possible to use <code>shared_ptr</code>
as a mutex lock:</p> as a mutex lock:</p>
<pre>class mutex <pre>class mutex
{ {
public: public:
@@ -603,9 +603,9 @@ shared_ptr&lt;mutex&gt; lock(mutex &amp; m)
return shared_ptr&lt;mutex&gt;(&amp;m, mem_fn(&amp;mutex::unlock)); return shared_ptr&lt;mutex&gt;(&amp;m, mem_fn(&amp;mutex::unlock));
} }
</pre> </pre>
<p>Better yet, the <code>shared_ptr</code> instance acting as a lock can be <p>Better yet, the <code>shared_ptr</code> instance acting as a lock can be
encapsulated in a dedicated <code>shared_lock</code> class:</p> encapsulated in a dedicated <code>shared_lock</code> class:</p>
<pre>class shared_lock <pre>class shared_lock
{ {
private: private:
@@ -616,17 +616,17 @@ public:
template&lt;class Mutex&gt; explicit shared_lock(Mutex &amp; m): pv((m.lock(), &amp;m), mem_fn(&amp;Mutex::unlock)) {} template&lt;class Mutex&gt; explicit shared_lock(Mutex &amp; m): pv((m.lock(), &amp;m), mem_fn(&amp;Mutex::unlock)) {}
}; };
</pre> </pre>
<p><code>shared_lock</code> can now be used as:</p> <p><code>shared_lock</code> can now be used as:</p>
<pre> shared_lock lock(m); <pre> shared_lock lock(m);
</pre> </pre>
<p>Note that <code>shared_lock</code> is not templated on the mutex type, thanks to <code> <p>Note that <code>shared_lock</code> is not templated on the mutex type, thanks to <code>
shared_ptr&lt;void&gt;</code>'s ability to hide type information.</p> shared_ptr&lt;void&gt;</code>'s ability to hide type information.</p>
<h2><A name="wrapper">Using <code>shared_ptr</code> to wrap member function calls</A></h2> <h2><A name="wrapper">Using <code>shared_ptr</code> to wrap member function calls</A></h2>
<p><code>shared_ptr</code> implements the ownership semantics required from the <code>Wrap</code>/<code>CallProxy</code> <p><code>shared_ptr</code> implements the ownership semantics required from the <code>Wrap</code>/<code>CallProxy</code>
scheme described in Bjarne Stroustrup's article "Wrapping C++ Member Function scheme described in Bjarne Stroustrup's article "Wrapping C++ Member Function
Calls" (available online at <A href="http://www.stroustrup.com/wrapper.pdf">http://www.stroustrup.com/wrapper.pdf</A>). Calls" (available online at <A href="http://www.stroustrup.com/wrapper.pdf">http://www.stroustrup.com/wrapper.pdf</A>).
An implementation is given below:</p> An implementation is given below:</p>
<pre>template&lt;class T&gt; class pointer <pre>template&lt;class T&gt; class pointer
{ {
private: private:
@@ -669,10 +669,10 @@ int main()
px-&gt;g(); px-&gt;g();
} }
</pre> </pre>
<h2><A name="delayed">Delayed deallocation</A></h2> <h2><A name="delayed">Delayed deallocation</A></h2>
<p>In some situations, a single <code>px.reset()</code> can trigger an expensive <p>In some situations, a single <code>px.reset()</code> can trigger an expensive
deallocation in a performance-critical region:</p> deallocation in a performance-critical region:</p>
<pre>class X; // ~X is expensive <pre>class X; // ~X is expensive
class Y class Y
{ {
@@ -686,10 +686,10 @@ public:
} }
}; };
</pre> </pre>
<p>The solution is to postpone the potential deallocation by moving <code>px</code> <p>The solution is to postpone the potential deallocation by moving <code>px</code>
to a dedicated free list that can be periodically emptied when performance and to a dedicated free list that can be periodically emptied when performance and
response times are not an issue:</p> response times are not an issue:</p>
<pre>vector&lt; shared_ptr&lt;void&gt; &gt; free_list; <pre>vector&lt; shared_ptr&lt;void&gt; &gt; free_list;
class Y class Y
{ {
@@ -706,9 +706,9 @@ public:
// periodically invoke free_list.clear() when convenient // periodically invoke free_list.clear() when convenient
</pre> </pre>
<p>Another variation is to move the free list logic to the construction point by <p>Another variation is to move the free list logic to the construction point by
using a delayed deleter:</p> using a delayed deleter:</p>
<pre>struct delayed_deleter <pre>struct delayed_deleter
{ {
template&lt;class T&gt; void operator()(T * p) template&lt;class T&gt; void operator()(T * p)
{ {
@@ -723,9 +723,9 @@ public:
} }
}; };
</pre> </pre>
<h2><A name="weak_without_shared">Weak pointers to objects not managed by a <code>shared_ptr</code></A></h2> <h2><A name="weak_without_shared">Weak pointers to objects not managed by a <code>shared_ptr</code></A></h2>
<p>Make the object hold a <code>shared_ptr</code> to itself, using a <code>null_deleter</code>:</p> <p>Make the object hold a <code>shared_ptr</code> to itself, using a <code>null_deleter</code>:</p>
<pre>class X <pre>class X
{ {
private: private:
@@ -748,18 +748,18 @@ public:
X &amp; operator=(X const &amp; rhs) X &amp; operator=(X const &amp; rhs)
{ {
i_ = rhs.i_; i_ = rhs.i_;
} }
weak_ptr&lt;X&gt; get_weak_ptr() const { return this_; } weak_ptr&lt;X&gt; get_weak_ptr() const { return this_; }
}; };
</pre> </pre>
<p>When the object's lifetime ends, <code>X::this_</code> will be destroyed, and <p>When the object's lifetime ends, <code>X::this_</code> will be destroyed, and
all weak pointers will automatically expire.</p> all weak pointers will automatically expire.</p>
<hr> <hr>
<p>$Date$</p> <p>$Date$</p>
<p><small>Copyright <EFBFBD> 2003 Peter Dimov. Distributed under the Boost Software License, Version <p><small>Copyright &copy; 2003 Peter Dimov. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p> copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body> </body>
</html> </html>

View File

@@ -1,6 +1,6 @@
# Boost.SmartPtr Library test Jamfile # Boost.SmartPtr Library test Jamfile
# #
# Copyright (c) 2003-2007 Peter Dimov # Copyright (c) 2003-2013 Peter Dimov
# Copyright (c) 2003 Dave Abrahams # Copyright (c) 2003 Dave Abrahams
# #
# Distributed under the Boost Software License, Version 1.0. (See # Distributed under the Boost Software License, Version 1.0. (See
@@ -78,6 +78,11 @@ import testing ;
[ run sp_array_cast_test.cpp ] [ run sp_array_cast_test.cpp ]
[ run sp_zero_compare_test.cpp ] [ run sp_zero_compare_test.cpp ]
[ run sp_nullptr_test.cpp ] [ run sp_nullptr_test.cpp ]
[ run sa_nullptr_test.cpp ]
[ run shared_ptr_alloc3_test.cpp ]
[ run shared_ptr_alloc11_test.cpp ]
[ run allocate_shared_alloc11_test.cpp ]
[ run allocate_shared_construct11_test.cpp ]
[ compile-fail array_fail_spa_sp_c.cpp ] [ compile-fail array_fail_spa_sp_c.cpp ]
[ compile-fail array_fail_sp_spa_c.cpp ] [ compile-fail array_fail_sp_spa_c.cpp ]
@@ -136,22 +141,26 @@ import testing ;
[ compile-fail array_fail_array_access.cpp ] [ compile-fail array_fail_array_access.cpp ]
[ run make_shared_array_test.cpp ] [ run make_shared_array_test.cpp ]
[ run make_shared_arrays_test.cpp ] [ run make_shared_arrays_test.cpp : : : <toolset>gcc-4.6.3_0x:<cxxflags>-fno-deduce-init-list ]
[ run make_shared_array_create_test.cpp ]
[ run make_shared_array_init_test.cpp : : : <toolset>gcc-4.6.3_0x:<cxxflags>-fno-deduce-init-list ]
[ run make_shared_arrays_create_test.cpp : : : <toolset>gcc-4.6.3_0x:<cxxflags>-fno-deduce-init-list ]
[ run make_shared_arrays_init_test.cpp : : : <toolset>gcc-4.6.3_0x:<cxxflags>-fno-deduce-init-list ]
[ run make_shared_array_throws_test.cpp ] [ run make_shared_array_throws_test.cpp ]
[ run make_shared_array_esft_test.cpp ] [ run make_shared_array_esft_test.cpp ]
[ run make_shared_array_args_test.cpp ] [ run make_shared_array_noinit_test.cpp ]
[ run make_shared_array_value_test.cpp ]
[ run allocate_shared_array_test.cpp ] [ run allocate_shared_array_test.cpp ]
[ run allocate_shared_arrays_test.cpp ] [ run allocate_shared_arrays_test.cpp : : : <toolset>gcc-4.6.3_0x:<cxxflags>-fno-deduce-init-list ]
[ run allocate_shared_array_create_test.cpp ]
[ run allocate_shared_array_init_test.cpp : : : <toolset>gcc-4.6.3_0x:<cxxflags>-fno-deduce-init-list ]
[ run allocate_shared_arrays_create_test.cpp : : : <toolset>gcc-4.6.3_0x:<cxxflags>-fno-deduce-init-list ]
[ run allocate_shared_arrays_init_test.cpp : : : <toolset>gcc-4.6.3_0x:<cxxflags>-fno-deduce-init-list ]
[ run allocate_shared_array_throws_test.cpp ] [ run allocate_shared_array_throws_test.cpp ]
[ run allocate_shared_array_esft_test.cpp ] [ run allocate_shared_array_esft_test.cpp ]
[ run allocate_shared_array_args_test.cpp ] [ run allocate_shared_array_noinit_test.cpp ]
[ run allocate_shared_array_value_test.cpp ]
[ run allocate_shared_array_construct_test.cpp ]
[ run make_unique_test.cpp ]
[ run make_unique_args_test.cpp ]
[ run make_unique_value_test.cpp ]
[ run make_unique_noinit_test.cpp ]
[ run make_unique_throws_test.cpp ]
[ run make_unique_array_test.cpp ]
[ run make_unique_array_noinit_test.cpp ]
[ run make_unique_array_throws_test.cpp ]
; ;
} }

View File

@@ -0,0 +1,241 @@
// allocate_shared_alloc11_test.cpp
//
// allocate_shared with a minimal C++11 allocator
//
// Copyright 2007-2009, 2014 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/lightweight_test.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/config.hpp>
#include <cstddef>
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
template< class T > class cxx11_allocator
{
public:
typedef T value_type;
cxx11_allocator()
{
}
template< class Y > cxx11_allocator( cxx11_allocator<Y> const & )
{
}
T * allocate( std::size_t n )
{
return static_cast< T* >( ::operator new( n * sizeof( T ) ) );
}
void deallocate( T * p, std::size_t n )
{
::operator delete( p );
}
};
class X
{
private:
X( X const & );
X & operator=( X const & );
void * operator new( std::size_t n )
{
BOOST_ERROR( "private X::new called" );
return ::operator new( n );
}
void operator delete( void * p )
{
BOOST_ERROR( "private X::delete called" );
::operator delete( p );
}
public:
static int instances;
int v;
explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
{
++instances;
}
~X()
{
--instances;
}
};
int X::instances = 0;
int main()
{
{
boost::shared_ptr< int > pi = boost::allocate_shared< int >( cxx11_allocator<int>() );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( *pi == 0 );
}
{
boost::shared_ptr< int > pi = boost::allocate_shared< int >( cxx11_allocator<int>(), 5 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( *pi == 5 );
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>() );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 0 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
return boost::report_errors();
}
#else // !defined( BOOST_NO_CXX11_ALLOCATOR )
int main()
{
return 0;
}
#endif

View File

@@ -1,173 +0,0 @@
// allocate_shared_array_args_test.cpp
//
// Copyright 2007-2009, 2012 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/lightweight_test.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <memory>
#include <cstddef>
class X
{
private:
X( X const & );
X & operator=( X const & );
void * operator new[]( std::size_t n );
void operator delete[]( void * 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_TEST( X::instances == 0 );
{
boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator<X>(), 2 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 0 );
BOOST_TEST( px[1].v == 0 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
{
boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator<X>(), 2, 1 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1 );
BOOST_TEST( px[1].v == 1 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator<X>(), 2, 1, 2 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2 );
BOOST_TEST( px[1].v == 1+2 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator<X>(), 2, 1, 2, 3 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2+3 );
BOOST_TEST( px[1].v == 1+2+3 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator<X>(), 2, 1, 2, 3, 4 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2+3+4 );
BOOST_TEST( px[1].v == 1+2+3+4 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator<X>(), 2, 1, 2, 3, 4, 5 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2+3+4+5 );
BOOST_TEST( px[1].v == 1+2+3+4+5 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator<X>(), 2, 1, 2, 3, 4, 5, 6 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2+3+4+5+6 );
BOOST_TEST( px[1].v == 1+2+3+4+5+6 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator<X>(), 2, 1, 2, 3, 4, 5, 6, 7 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2+3+4+5+6+7 );
BOOST_TEST( px[1].v == 1+2+3+4+5+6+7 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator<X>(), 2, 1, 2, 3, 4, 5, 6, 7, 8 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2+3+4+5+6+7+8 );
BOOST_TEST( px[1].v == 1+2+3+4+5+6+7+8 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator<X>(), 2, 1, 2, 3, 4, 5, 6, 7, 8, 9 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2+3+4+5+6+7+8+9 );
BOOST_TEST( px[1].v == 1+2+3+4+5+6+7+8+9 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,167 @@
/*
* Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/detail/lightweight_test.hpp>
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
#include <boost/smart_ptr/allocate_shared_array.hpp>
template<typename T>
class creator {
public:
typedef T value_type;
#if defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template<typename U>
struct rebind {
typedef creator<U> other;
};
#endif
creator() {
}
template<typename U>
creator(const creator<U>&) {
}
T* allocate(std::size_t size) {
void* p1 = ::operator new(size * sizeof(T));
return static_cast<T*>(p1);
}
void deallocate(T* memory, std::size_t) {
void* p1 = memory;
::operator delete(p1);
}
template<typename U>
void construct(U* memory) {
void* p1 = memory;
::new(p1) U();
}
template<typename U>
void destroy(U* memory) {
memory->~U();
}
};
class type {
friend class creator<type>;
public:
static unsigned int instances;
static const type object;
protected:
explicit type() {
instances++;
}
type(const type&) {
instances++;
}
~type() {
instances--;
}
};
unsigned int type::instances;
const type type::object;
int main() {
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<type[]> a1 = boost::allocate_shared<type[]>(creator<void>(), 3);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 1);
}
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<type[3]> a1 = boost::allocate_shared<type[3]>(creator<void>());
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 1);
}
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<type[][2]> a1 = boost::allocate_shared<type[][2]>(creator<void>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 5);
a1.reset();
BOOST_TEST(type::instances == 1);
}
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<type[2][2]> a1 = boost::allocate_shared<type[2][2]>(creator<void>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 5);
a1.reset();
BOOST_TEST(type::instances == 1);
}
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<const type[]> a1 = boost::allocate_shared<const type[]>(creator<void>(), 3);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 1);
}
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<const type[3]> a1 = boost::allocate_shared<const type[3]>(creator<void>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 1);
}
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<const type[][2]> a1 = boost::allocate_shared<const type[][2]>(creator<void>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 5);
a1.reset();
BOOST_TEST(type::instances == 1);
}
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<const type[2][2]> a1 = boost::allocate_shared<const type[2][2]>(creator<void>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 5);
a1.reset();
BOOST_TEST(type::instances == 1);
}
return boost::report_errors();
}
#else
int main() {
return 0;
}
#endif

View File

@@ -1,114 +0,0 @@
/*
* Copyright (c) 2012 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_shared_array.hpp>
class type {
public:
static int instances;
explicit type(int a=0, int b=0, int c=0, int d=0, int e=0, int f=0, int g=0, int h=0, int i=0)
: a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h), i(i) {
instances++;
}
~type() {
instances--;
}
const int a;
const int b;
const int c;
const int d;
const int e;
const int f;
const int g;
const int h;
const int i;
private:
type(const type&);
type& operator=(const type&);
};
int type::instances = 0;
int main() {
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[]> a1 = boost::allocate_shared<type[]>(std::allocator<type>(), 2, 1, 2, 3, 4, 5, 6, 7, 8, 9);
BOOST_TEST(type::instances == 2);
BOOST_TEST(a1[0].a == 1);
BOOST_TEST(a1[0].d == 4);
BOOST_TEST(a1[1].f == 6);
BOOST_TEST(a1[1].i == 9);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2]> a1 = boost::allocate_shared<type[2]>(std::allocator<type>(), 1, 2, 3, 4, 5, 6, 7, 8, 9);
BOOST_TEST(type::instances == 2);
BOOST_TEST(a1[0].a == 1);
BOOST_TEST(a1[0].d == 4);
BOOST_TEST(a1[1].f == 6);
BOOST_TEST(a1[1].i == 9);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[][2]> a1 = boost::allocate_shared<type[][2]>(std::allocator<type>(), 2, 1, 2, 3, 4, 5, 6, 7);
BOOST_TEST(type::instances == 4);
BOOST_TEST(a1[0][0].a == 1);
BOOST_TEST(a1[0][1].d == 4);
BOOST_TEST(a1[1][0].f == 6);
BOOST_TEST(a1[1][1].i == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2][2]> a1 = boost::allocate_shared<type[2][2]>(std::allocator<type>(), 1, 2, 3, 4, 5, 6, 7);
BOOST_TEST(type::instances == 4);
BOOST_TEST(a1[0][0].a == 1);
BOOST_TEST(a1[0][1].d == 4);
BOOST_TEST(a1[1][0].f == 6);
BOOST_TEST(a1[1][1].i == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[][2][2]> a1 = boost::allocate_shared<type[][2][2]>(std::allocator<type>(), 2, 1, 2, 3, 4, 5);
BOOST_TEST(type::instances == 8);
BOOST_TEST(a1[0][0][0].a == 1);
BOOST_TEST(a1[0][1][0].c == 3);
BOOST_TEST(a1[1][0][1].e == 5);
BOOST_TEST(a1[1][1][1].i == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2][2][2]> a1 = boost::allocate_shared<type[2][2][2]>(std::allocator<type>(), 1, 2, 3, 4, 5);
BOOST_TEST(type::instances == 8);
BOOST_TEST(a1[0][0][0].a == 1);
BOOST_TEST(a1[0][1][0].c == 3);
BOOST_TEST(a1[1][0][1].e == 5);
BOOST_TEST(a1[1][1][1].i == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[][2][2][2]> a1 = boost::allocate_shared<type[][2][2][2]>(std::allocator<type>(), 2, 1, 2, 3);
BOOST_TEST(type::instances == 16);
BOOST_TEST(a1[0][0][0][1].a == 1);
BOOST_TEST(a1[0][0][1][0].c == 3);
BOOST_TEST(a1[0][1][0][0].f == 0);
BOOST_TEST(a1[1][0][0][0].i == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2][2][2][2]> a1 = boost::allocate_shared<type[2][2][2][2]>(std::allocator<type>(), 1, 2, 3);
BOOST_TEST(type::instances == 16);
BOOST_TEST(a1[0][0][0][1].a == 1);
BOOST_TEST(a1[0][0][1][0].c == 3);
BOOST_TEST(a1[0][1][0][0].f == 0);
BOOST_TEST(a1[1][0][0][0].i == 0);
}
#endif
return boost::report_errors();
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Glen Joseph Fernandes * Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com * glenfe at live dot com
* *
* Distributed under the Boost Software License, * Distributed under the Boost Software License,
@@ -14,12 +14,15 @@ class type
: public boost::enable_shared_from_this<type> { : public boost::enable_shared_from_this<type> {
public: public:
static unsigned int instances; static unsigned int instances;
explicit type() { explicit type() {
instances++; instances++;
} }
~type() { ~type() {
instances--; instances--;
} }
private: private:
type(const type&); type(const type&);
type& operator=(const type&); type& operator=(const type&);
@@ -38,6 +41,7 @@ int main() {
BOOST_TEST(type::instances == 3); BOOST_TEST(type::instances == 3);
} }
} }
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<type[]> a1 = boost::allocate_shared_noinit<type[]>(std::allocator<type>(), 3); boost::shared_ptr<type[]> a1 = boost::allocate_shared_noinit<type[]>(std::allocator<type>(), 3);
@@ -48,5 +52,6 @@ int main() {
BOOST_TEST(type::instances == 3); BOOST_TEST(type::instances == 3);
} }
} }
return boost::report_errors(); return boost::report_errors();
} }

View File

@@ -1,84 +0,0 @@
/*
* Copyright (c) 2012 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_shared_array.hpp>
class type {
public:
type(int value)
: value(value) {
}
const int value;
private:
type& operator=(const type&);
};
int main() {
#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
{
boost::shared_ptr<int[4]> a1 = boost::allocate_shared<int[4]>(std::allocator<int>(), { 0, 1, 2, 3 });
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 2);
BOOST_TEST(a1[3] == 3);
}
{
boost::shared_ptr<const int[4]> a1 = boost::allocate_shared<const int[4]>(std::allocator<int>(), { 0, 1, 2, 3 });
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 2);
BOOST_TEST(a1[3] == 3);
}
{
boost::shared_ptr<type[4]> a1 = boost::allocate_shared<type[4]>(std::allocator<type>(), { 0, 1, 2, 3 });
BOOST_TEST(a1[0].value == 0);
BOOST_TEST(a1[1].value == 1);
BOOST_TEST(a1[2].value == 2);
BOOST_TEST(a1[3].value == 3);
}
{
boost::shared_ptr<const type[4]> a1 = boost::allocate_shared<const type[4]>(std::allocator<type>(), { 0, 1, 2, 3 });
BOOST_TEST(a1[0].value == 0);
BOOST_TEST(a1[1].value == 1);
BOOST_TEST(a1[2].value == 2);
BOOST_TEST(a1[3].value == 3);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
{
boost::shared_ptr<int[]> a1 = boost::allocate_shared<int[]>(std::allocator<int>(), { 0, 1, 2, 3 });
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 2);
BOOST_TEST(a1[3] == 3);
}
{
boost::shared_ptr<const int[]> a1 = boost::allocate_shared<const int[]>(std::allocator<int>(), { 0, 1, 2, 3 });
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 2);
BOOST_TEST(a1[3] == 3);
}
{
boost::shared_ptr<type[]> a1 = boost::allocate_shared<type[]>(std::allocator<type>(), { 0, 1, 2, 3 });
BOOST_TEST(a1[0].value == 0);
BOOST_TEST(a1[1].value == 1);
BOOST_TEST(a1[2].value == 2);
BOOST_TEST(a1[3].value == 3);
}
{
boost::shared_ptr<const type[]> a1 = boost::allocate_shared<const type[]>(std::allocator<type>(), { 0, 1, 2, 3 });
BOOST_TEST(a1[0].value == 0);
BOOST_TEST(a1[1].value == 1);
BOOST_TEST(a1[2].value == 2);
BOOST_TEST(a1[3].value == 3);
}
#endif
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,181 @@
/*
* Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_shared_array.hpp>
#include <boost/smart_ptr/weak_ptr.hpp>
#include <boost/type_traits/alignment_of.hpp>
class type {
public:
static unsigned int instances;
explicit type() {
instances++;
}
~type() {
instances--;
}
private:
type(const type&);
type& operator=(const type&);
};
unsigned int type::instances = 0;
int main() {
{
boost::shared_ptr<int[]> a1 = boost::allocate_shared_noinit<int[]>(std::allocator<int>(), 3);
int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
{
boost::shared_ptr<int[3]> a1 = boost::allocate_shared_noinit<int[3]>(std::allocator<int>());
int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
{
boost::shared_ptr<int[][2]> a1 = boost::allocate_shared_noinit<int[][2]>(std::allocator<int>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
{
boost::shared_ptr<int[2][2]> a1 = boost::allocate_shared_noinit<int[2][2]>(std::allocator<int>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
{
boost::shared_ptr<const int[]> a1 = boost::allocate_shared_noinit<const int[]>(std::allocator<int>(), 3);
const int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
{
boost::shared_ptr<const int[3]> a1 = boost::allocate_shared_noinit<const int[3]>(std::allocator<int>());
const int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
{
boost::shared_ptr<const int[][2]> a1 = boost::allocate_shared_noinit<const int[][2]>(std::allocator<int>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
{
boost::shared_ptr<const int[2][2]> a1 = boost::allocate_shared_noinit<const int[2][2]>(std::allocator<int>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[]> a1 = boost::allocate_shared_noinit<type[]>(std::allocator<type>(), 3);
type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
boost::weak_ptr<type[]> w1 = a1;
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[3]> a1 = boost::allocate_shared_noinit<type[3]>(std::allocator<type>());
type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
boost::weak_ptr<type[3]> w1 = a1;
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[][2]> a1 = boost::allocate_shared_noinit<type[][2]>(std::allocator<type>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2][2]> a1 = boost::allocate_shared_noinit<type[2][2]>(std::allocator<type>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[]> a1 = boost::allocate_shared_noinit<const type[]>(std::allocator<type>(), 3);
const type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[3]> a1 = boost::allocate_shared_noinit<const type[3]>(std::allocator<type>());
const type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[][2]> a1 = boost::allocate_shared_noinit<const type[][2]>(std::allocator<type>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[2][2]> a1 = boost::allocate_shared_noinit<const type[2][2]>(std::allocator<type>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}

View File

@@ -1,9 +1,9 @@
/* /*
* Copyright (c) 2012 Glen Joseph Fernandes * Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com * glenfe at live dot com
* *
* Distributed under the Boost Software License, * Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt * Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt) * or copy at http://boost.org/LICENSE_1_0.txt)
*/ */
#include <boost/detail/lightweight_test.hpp> #include <boost/detail/lightweight_test.hpp>
@@ -14,17 +14,18 @@
class type { class type {
public: public:
static unsigned int instances; static unsigned int instances;
explicit type(int = 0, int = 0)
: member() { explicit type() {
instances++; instances++;
} }
~type() { ~type() {
instances--; instances--;
} }
private: private:
type(const type&); type(const type&);
type& operator=(const type&); type& operator=(const type&);
double member;
}; };
unsigned int type::instances = 0; unsigned int type::instances = 0;
@@ -40,6 +41,38 @@ int main() {
BOOST_TEST(a1[1] == 0); BOOST_TEST(a1[1] == 0);
BOOST_TEST(a1[2] == 0); BOOST_TEST(a1[2] == 0);
} }
{
boost::shared_ptr<int[3]> a1 = boost::allocate_shared<int[3]>(std::allocator<int>());
int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 0);
BOOST_TEST(a1[2] == 0);
}
{
boost::shared_ptr<int[][2]> a1 = boost::allocate_shared<int[][2]>(std::allocator<int>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 0);
BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[1][1] == 0);
}
{
boost::shared_ptr<int[2][2]> a1 = boost::allocate_shared<int[2][2]>(std::allocator<int>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 0);
BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[1][1] == 0);
}
{ {
boost::shared_ptr<const int[]> a1 = boost::allocate_shared<const int[]>(std::allocator<int>(), 3); boost::shared_ptr<const int[]> a1 = boost::allocate_shared<const int[]>(std::allocator<int>(), 3);
const int* a2 = a1.get(); const int* a2 = a1.get();
@@ -50,6 +83,38 @@ int main() {
BOOST_TEST(a1[1] == 0); BOOST_TEST(a1[1] == 0);
BOOST_TEST(a1[2] == 0); BOOST_TEST(a1[2] == 0);
} }
{
boost::shared_ptr<const int[3]> a1 = boost::allocate_shared<const int[3]>(std::allocator<int>());
const int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 0);
BOOST_TEST(a1[2] == 0);
}
{
boost::shared_ptr<const int[][2]> a1 = boost::allocate_shared<const int[][2]>(std::allocator<int>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 0);
BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[1][1] == 0);
}
{
boost::shared_ptr<const int[2][2]> a1 = boost::allocate_shared<const int[2][2]>(std::allocator<int>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 0);
BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[1][1] == 0);
}
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<type[]> a1 = boost::allocate_shared<type[]>(std::allocator<type>(), 3); boost::shared_ptr<type[]> a1 = boost::allocate_shared<type[]>(std::allocator<type>(), 3);
@@ -62,6 +127,40 @@ int main() {
a1.reset(); a1.reset();
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[3]> a1 = boost::allocate_shared<type[3]>(std::allocator<type>());
type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
boost::weak_ptr<type[3]> w1 = a1;
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[][2]> a1 = boost::allocate_shared<type[][2]>(std::allocator<type>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2][2]> a1 = boost::allocate_shared<type[2][2]>(std::allocator<type>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<const type[]> a1 = boost::allocate_shared<const type[]>(std::allocator<type>(), 3); boost::shared_ptr<const type[]> a1 = boost::allocate_shared<const type[]>(std::allocator<type>(), 3);
@@ -73,109 +172,10 @@ int main() {
a1.reset(); a1.reset();
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<type[]> a1 = boost::allocate_shared<type[]>(std::allocator<type>(), 3, 1, 5); boost::shared_ptr<const type[3]> a1 = boost::allocate_shared<const type[3]>(std::allocator<type>());
type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
boost::weak_ptr<type[]> w1 = a1;
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[3]> a1 = boost::allocate_shared<type[3]>(std::allocator<type>(), 1, 5);
type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
boost::weak_ptr<type[3]> w1 = a1;
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[]> a1 = boost::allocate_shared<const type[]>(std::allocator<type>(), 3, 1, 5);
const type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[3]> a1 = boost::allocate_shared<const type[3]>(std::allocator<type>(), 1, 5);
const type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
a1.reset();
BOOST_TEST(type::instances == 0);
}
#endif
{
boost::shared_ptr<int[]> a1 = boost::allocate_shared_noinit<int[]>(std::allocator<int>(), 3);
int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
{
boost::shared_ptr<int[3]> a1 = boost::allocate_shared_noinit<int[3]>(std::allocator<int>());
int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
{
boost::shared_ptr<const int[]> a1 = boost::allocate_shared_noinit<const int[]>(std::allocator<int>(), 3);
const int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
{
boost::shared_ptr<const int[3]> a1 = boost::allocate_shared_noinit<const int[3]>(std::allocator<int>());
const int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[]> a1 = boost::allocate_shared_noinit<type[]>(std::allocator<type>(), 3);
type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
boost::weak_ptr<type[]> w1 = a1;
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[3]> a1 = boost::allocate_shared_noinit<type[3]>(std::allocator<type>());
type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
boost::weak_ptr<type[3]> w1 = a1;
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[]> a1 = boost::allocate_shared_noinit<const type[]>(std::allocator<type>(), 3);
const type* a2 = a1.get(); const type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0); BOOST_TEST(a2 != 0);
@@ -184,16 +184,26 @@ int main() {
a1.reset(); a1.reset();
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<const type[3]> a1 = boost::allocate_shared_noinit<const type[3]>(std::allocator<type>()); boost::shared_ptr<const type[][2]> a1 = boost::allocate_shared<const type[][2]>(std::allocator<type>(), 2);
const type* a2 = a1.get(); BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0); BOOST_TEST(type::instances == 4);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
a1.reset(); a1.reset();
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[2][2]> a1 = boost::allocate_shared<const type[2][2]>(std::allocator<type>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors(); return boost::report_errors();
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Glen Joseph Fernandes * Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com * glenfe at live dot com
* *
* Distributed under the Boost Software License, * Distributed under the Boost Software License,
@@ -12,15 +12,18 @@
class type { class type {
public: public:
static unsigned int instances; static unsigned int instances;
explicit type() { explicit type() {
if (instances == 5) { if (instances == 5) {
throw true; throw true;
} }
instances++; instances++;
} }
~type() { ~type() {
instances--; instances--;
} }
private: private:
type(const type&); type(const type&);
type& operator=(const type&); type& operator=(const type&);
@@ -36,6 +39,7 @@ int main() {
} catch (...) { } catch (...) {
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
try { try {
boost::allocate_shared<type[][2]>(std::allocator<type>(), 3); boost::allocate_shared<type[][2]>(std::allocator<type>(), 3);
@@ -43,7 +47,7 @@ int main() {
} catch (...) { } catch (...) {
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
try { try {
boost::allocate_shared<type[6]>(std::allocator<type>()); boost::allocate_shared<type[6]>(std::allocator<type>());
@@ -51,6 +55,7 @@ int main() {
} catch (...) { } catch (...) {
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
try { try {
boost::allocate_shared<type[3][2]>(std::allocator<type>()); boost::allocate_shared<type[3][2]>(std::allocator<type>());
@@ -58,7 +63,7 @@ int main() {
} catch (...) { } catch (...) {
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
#endif
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
try { try {
boost::allocate_shared_noinit<type[]>(std::allocator<type>(), 6); boost::allocate_shared_noinit<type[]>(std::allocator<type>(), 6);
@@ -66,6 +71,7 @@ int main() {
} catch (...) { } catch (...) {
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
try { try {
boost::allocate_shared_noinit<type[][2]>(std::allocator<type>(), 3); boost::allocate_shared_noinit<type[][2]>(std::allocator<type>(), 3);
@@ -73,5 +79,22 @@ int main() {
} catch (...) { } catch (...) {
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0);
try {
boost::allocate_shared_noinit<type[6]>(std::allocator<type>());
BOOST_ERROR("allocate_shared_noinit did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
try {
boost::allocate_shared_noinit<type[3][2]>(std::allocator<type>());
BOOST_ERROR("allocate_shared_noinit did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
return boost::report_errors(); return boost::report_errors();
} }

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_shared_array.hpp>
int main() {
{
boost::shared_ptr<int[]> a1 = boost::allocate_shared<int[]>(std::allocator<int>(), 4, 1);
BOOST_TEST(a1[0] == 1);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 1);
BOOST_TEST(a1[3] == 1);
}
{
boost::shared_ptr<int[4]> a1 = boost::allocate_shared<int[4]>(std::allocator<int>(), 1);
BOOST_TEST(a1[0] == 1);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 1);
BOOST_TEST(a1[3] == 1);
}
{
boost::shared_ptr<const int[]> a1 = boost::allocate_shared<const int[]>(std::allocator<int>(), 4, 1);
BOOST_TEST(a1[0] == 1);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 1);
BOOST_TEST(a1[3] == 1);
}
{
boost::shared_ptr<const int[4]> a1 = boost::allocate_shared<const int[4]>(std::allocator<int>(), 1);
BOOST_TEST(a1[0] == 1);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 1);
BOOST_TEST(a1[3] == 1);
}
return boost::report_errors();
}

View File

@@ -1,94 +0,0 @@
/*
* Copyright (c) 2012 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_shared_array.hpp>
class type {
public:
type(int x, int y)
: x(x), y(y) {
}
const int x;
const int y;
private:
type& operator=(const type&);
};
int main() {
#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
{
boost::shared_ptr<int[4]> a1 = boost::allocate_shared<int[4]>(std::allocator<int>(), {0, 1, 2, 3});
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 2);
BOOST_TEST(a1[3] == 3);
}
{
boost::shared_ptr<int[2][2]> a1 = boost::allocate_shared<int[2][2]>(std::allocator<int>(), { {0, 1}, {2, 3} });
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(a1[1][0] == 2);
BOOST_TEST(a1[1][1] == 3);
}
{
boost::shared_ptr<int[][2]> a1 = boost::allocate_shared<int[][2]>(std::allocator<int>(), 2, {0, 1});
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[1][1] == 1);
}
{
boost::shared_ptr<int[][2][2]> a1 = boost::allocate_shared<int[][2][2]>(std::allocator<int>(), 2, { {0, 1}, {2, 3} });
BOOST_TEST(a1[0][0][0] == 0);
BOOST_TEST(a1[0][0][1] == 1);
BOOST_TEST(a1[1][1][0] == 2);
BOOST_TEST(a1[1][1][1] == 3);
}
{
boost::shared_ptr<int[2][2]> a1 = boost::allocate_shared<int[2][2]>(std::allocator<int>(), {0, 1});
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[1][1] == 1);
}
{
boost::shared_ptr<int[2][2][2]> a1 = boost::allocate_shared<int[2][2][2]>(std::allocator<int>(), { {0, 1}, {2, 3} });
BOOST_TEST(a1[0][0][0] == 0);
BOOST_TEST(a1[0][0][1] == 1);
BOOST_TEST(a1[1][1][0] == 2);
BOOST_TEST(a1[1][1][1] == 3);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
{
boost::shared_ptr<int[]> a1 = boost::allocate_shared<int[]>(std::allocator<int>(), {0, 1, 2, 3});
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 2);
BOOST_TEST(a1[3] == 3);
}
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
{
boost::shared_ptr<type[]> a1 = boost::allocate_shared<type[]>(std::allocator<type>(), 4, {1, 2});
BOOST_TEST(a1[0].x == 1);
BOOST_TEST(a1[1].y == 2);
BOOST_TEST(a1[2].x == 1);
BOOST_TEST(a1[3].y == 2);
}
{
boost::shared_ptr<type[4]> a1 = boost::allocate_shared<type[4]>(std::allocator<type>(), {1, 2});
BOOST_TEST(a1[0].x == 1);
BOOST_TEST(a1[1].y == 2);
BOOST_TEST(a1[2].x == 1);
BOOST_TEST(a1[3].y == 2);
}
#endif
#endif
return boost::report_errors();
}

View File

@@ -1,23 +0,0 @@
/*
* Copyright (c) 2012 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_shared_array.hpp>
int main() {
#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
{
boost::shared_ptr<int[][2]> a1 = boost::allocate_shared<int[][2]>(std::allocator<int>(), { {0, 1}, {2, 3} });
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(a1[1][0] == 2);
BOOST_TEST(a1[1][1] == 3);
}
#endif
return boost::report_errors();
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Glen Joseph Fernandes * Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com * glenfe at live dot com
* *
* Distributed under the Boost Software License, * Distributed under the Boost Software License,
@@ -9,152 +9,40 @@
#include <boost/detail/lightweight_test.hpp> #include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_shared_array.hpp> #include <boost/smart_ptr/allocate_shared_array.hpp>
class type {
public:
static unsigned int instances;
explicit type(int = 0, int = 0)
: member() {
instances++;
}
~type() {
instances--;
}
private:
type(const type&);
type& operator=(const type&);
double member;
};
unsigned int type::instances = 0;
int main() { int main() {
#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
{ {
boost::shared_ptr<int[][2][2]> a1 = boost::allocate_shared<int[][2][2]>(std::allocator<int>(), 2); boost::shared_ptr<int[][2]> a1 = boost::allocate_shared<int[][2]>(std::allocator<int>(), 2, {0, 1});
BOOST_TEST(a1.get() != 0); BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(a1[0][0][1] == 0); BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[0][1][0] == 0); BOOST_TEST(a1[1][1] == 1);
BOOST_TEST(a1[1][0][0] == 0);
} }
{ {
boost::shared_ptr<const int[][2][2]> a1 = boost::allocate_shared<const int[][2][2]>(std::allocator<int>(), 2); boost::shared_ptr<int[2][2]> a1 = boost::allocate_shared<int[2][2]>(std::allocator<int>(), { 0, 1 });
BOOST_TEST(a1.get() != 0); BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(a1[0][0][1] == 0); BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[0][1][0] == 0); BOOST_TEST(a1[1][1] == 1);
BOOST_TEST(a1[1][0][0] == 0);
} }
BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<type[][2][2]> a1 = boost::allocate_shared<type[][2][2]>(std::allocator<type>(), 2); boost::shared_ptr<const int[][2]> a1 = boost::allocate_shared<const int[][2]>(std::allocator<int>(), 2, { 0, 1 });
BOOST_TEST(a1.get() != 0); BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(type::instances == 8); BOOST_TEST(a1[1][0] == 0);
a1.reset(); BOOST_TEST(a1[1][1] == 1);
BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<const type[][2][2]> a1 = boost::allocate_shared<const type[][2][2]>(std::allocator<type>(), 2); boost::shared_ptr<const int[2][2]> a1 = boost::allocate_shared<const int[2][2]>(std::allocator<int>(), { 0, 1 });
BOOST_TEST(a1.get() != 0); BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(type::instances == 8); BOOST_TEST(a1[1][0] == 0);
a1.reset(); BOOST_TEST(a1[1][1] == 1);
BOOST_TEST(type::instances == 0);
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[][2][2]> a1 = boost::allocate_shared<type[][2][2]>(std::allocator<type>(), 2, 1, 5);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2][2][2]> a1 = boost::allocate_shared<type[2][2][2]>(std::allocator<type>(), 1, 5);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[][2][2]> a1 = boost::allocate_shared<const type[][2][2]>(std::allocator<type>(), 2, 1, 5);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[2][2][2]> a1 = boost::allocate_shared<const type[2][2][2]>(std::allocator<type>(), 1, 5);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
} }
#endif #endif
{
boost::shared_ptr<int[][2][2]> a1 = boost::allocate_shared_noinit<int[][2][2]>(std::allocator<int>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
{
boost::shared_ptr<int[2][2][2]> a1 = boost::allocate_shared_noinit<int[2][2][2]>(std::allocator<int>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
{
boost::shared_ptr<const int[][2][2]> a1 = boost::allocate_shared_noinit<const int[][2][2]>(std::allocator<int>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
{
boost::shared_ptr<const int[2][2][2]> a1 = boost::allocate_shared_noinit<const int[2][2][2]>(std::allocator<int>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[][2][2]> a1 = boost::allocate_shared_noinit<type[][2][2]>(std::allocator<type>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2][2][2]> a1 = boost::allocate_shared_noinit<type[2][2][2]>(std::allocator<type>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[][2][2]> a1 = boost::allocate_shared_noinit<const type[][2][2]>(std::allocator<type>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[2][2][2]> a1 = boost::allocate_shared_noinit<const type[2][2][2]>(std::allocator<type>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors(); return boost::report_errors();
} }

View File

@@ -0,0 +1,240 @@
// allocate_shared_construct11_test.cpp
//
// Test whether allocate_shared uses construct/destroy in C++11
//
// Copyright 2007-2009, 2014 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/lightweight_test.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <cstddef>
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
template< class T > class cxx11_allocator
{
public:
typedef T value_type;
cxx11_allocator()
{
}
template< class Y > cxx11_allocator( cxx11_allocator<Y> const & )
{
}
T * allocate( std::size_t n )
{
return static_cast< T* >( ::operator new( n * sizeof( T ) ) );
}
void deallocate( T * p, std::size_t n )
{
::operator delete( p );
}
template<class... Args> void construct( T * p, Args&&... args )
{
::new( static_cast< void* >( p ) ) T( std::forward<Args>( args )... );
}
void destroy( T * p )
{
p->~T();
}
};
class X
{
private:
X( X const & );
X & operator=( X const & );
void * operator new( std::size_t n )
{
BOOST_ERROR( "private X::new called" );
return ::operator new( n );
}
void operator delete( void * p )
{
BOOST_ERROR( "private X::delete called" );
::operator delete( p );
}
public:
static int instances;
int v;
protected:
explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
{
++instances;
}
~X()
{
--instances;
}
friend class cxx11_allocator<X>;
};
int X::instances = 0;
int main()
{
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>() );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 0 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
return boost::report_errors();
}
#else // !defined( BOOST_NO_CXX11_ALLOCATOR )
int main()
{
return 0;
}
#endif

View File

@@ -51,14 +51,18 @@ protected:
base(): use_count_(0) base(): use_count_(0)
{ {
++instances;
} }
virtual ~base() virtual ~base()
{ {
--instances;
} }
public: public:
static long instances;
long use_count() const long use_count() const
{ {
return use_count_; return use_count_;
@@ -91,6 +95,8 @@ public:
#endif #endif
}; };
long base::instances = 0;
} // namespace N } // namespace N
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
@@ -161,19 +167,27 @@ void pointer_constructor()
BOOST_TEST(px.get() == 0); BOOST_TEST(px.get() == 0);
} }
BOOST_TEST( N::base::instances == 0 );
{ {
X * p = new X; X * p = new X;
BOOST_TEST(p->use_count() == 0); BOOST_TEST(p->use_count() == 0);
BOOST_TEST( N::base::instances == 1 );
boost::intrusive_ptr<X> px(p); boost::intrusive_ptr<X> px(p);
BOOST_TEST(px.get() == p); BOOST_TEST(px.get() == p);
BOOST_TEST(px->use_count() == 1); BOOST_TEST(px->use_count() == 1);
} }
BOOST_TEST( N::base::instances == 0 );
{ {
X * p = new X; X * p = new X;
BOOST_TEST(p->use_count() == 0); BOOST_TEST(p->use_count() == 0);
BOOST_TEST( N::base::instances == 1 );
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
using boost::intrusive_ptr_add_ref; using boost::intrusive_ptr_add_ref;
#endif #endif
@@ -184,6 +198,8 @@ void pointer_constructor()
BOOST_TEST(px.get() == p); BOOST_TEST(px.get() == p);
BOOST_TEST(px->use_count() == 1); BOOST_TEST(px->use_count() == 1);
} }
BOOST_TEST( N::base::instances == 0 );
} }
void copy_constructor() void copy_constructor()
@@ -224,17 +240,27 @@ void copy_constructor()
BOOST_TEST(px.get() == py.get()); BOOST_TEST(px.get() == py.get());
} }
BOOST_TEST( N::base::instances == 0 );
{ {
boost::intrusive_ptr<X> px(new X); boost::intrusive_ptr<X> px(new X);
boost::intrusive_ptr<X> px2(px); boost::intrusive_ptr<X> px2(px);
BOOST_TEST(px2.get() == px.get()); BOOST_TEST( px2.get() == px.get() );
BOOST_TEST( N::base::instances == 1 );
} }
BOOST_TEST( N::base::instances == 0 );
{ {
boost::intrusive_ptr<Y> py(new Y); boost::intrusive_ptr<Y> py(new Y);
boost::intrusive_ptr<X> px(py); boost::intrusive_ptr<X> px(py);
BOOST_TEST(px.get() == py.get()); BOOST_TEST( px.get() == py.get() );
BOOST_TEST( N::base::instances == 1 );
} }
BOOST_TEST( N::base::instances == 0 );
} }
void test() void test()
@@ -251,15 +277,23 @@ namespace n_destructor
void test() void test()
{ {
boost::intrusive_ptr<X> px(new X); BOOST_TEST( N::base::instances == 0 );
BOOST_TEST(px->use_count() == 1);
{ {
boost::intrusive_ptr<X> px2(px); boost::intrusive_ptr<X> px(new X);
BOOST_TEST(px->use_count() == 2); BOOST_TEST(px->use_count() == 1);
BOOST_TEST( N::base::instances == 1 );
{
boost::intrusive_ptr<X> px2(px);
BOOST_TEST(px->use_count() == 2);
}
BOOST_TEST(px->use_count() == 1);
} }
BOOST_TEST(px->use_count() == 1); BOOST_TEST( N::base::instances == 0 );
} }
} // namespace n_destructor } // namespace n_destructor
@@ -288,6 +322,174 @@ void test()
} // namespace n_assignment } // namespace n_assignment
namespace n_reset
{
void test()
{
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px;
BOOST_TEST( px.get() == 0 );
px.reset();
BOOST_TEST( px.get() == 0 );
X * p = new X;
BOOST_TEST( p->use_count() == 0 );
BOOST_TEST( N::base::instances == 1 );
px.reset( p );
BOOST_TEST( px.get() == p );
BOOST_TEST( px->use_count() == 1 );
px.reset();
BOOST_TEST( px.get() == 0 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new X );
BOOST_TEST( N::base::instances == 1 );
px.reset( 0 );
BOOST_TEST( px.get() == 0 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new X );
BOOST_TEST( N::base::instances == 1 );
px.reset( 0, false );
BOOST_TEST( px.get() == 0 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new X );
BOOST_TEST( N::base::instances == 1 );
px.reset( 0, true );
BOOST_TEST( px.get() == 0 );
}
BOOST_TEST( N::base::instances == 0 );
{
X * p = new X;
BOOST_TEST( p->use_count() == 0 );
BOOST_TEST( N::base::instances == 1 );
boost::intrusive_ptr<X> px;
BOOST_TEST( px.get() == 0 );
px.reset( p, true );
BOOST_TEST( px.get() == p );
BOOST_TEST( px->use_count() == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
X * p = new X;
BOOST_TEST( p->use_count() == 0 );
BOOST_TEST( N::base::instances == 1 );
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
using boost::intrusive_ptr_add_ref;
#endif
intrusive_ptr_add_ref( p );
BOOST_TEST( p->use_count() == 1 );
boost::intrusive_ptr<X> px;
BOOST_TEST( px.get() == 0 );
px.reset( p, false );
BOOST_TEST( px.get() == p );
BOOST_TEST( px->use_count() == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new X );
BOOST_TEST( px.get() != 0 );
BOOST_TEST( px->use_count() == 1 );
BOOST_TEST( N::base::instances == 1 );
X * p = new X;
BOOST_TEST( p->use_count() == 0 );
BOOST_TEST( N::base::instances == 2 );
px.reset( p );
BOOST_TEST( px.get() == p );
BOOST_TEST( px->use_count() == 1 );
BOOST_TEST( N::base::instances == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new X );
BOOST_TEST( px.get() != 0 );
BOOST_TEST( px->use_count() == 1 );
BOOST_TEST( N::base::instances == 1 );
X * p = new X;
BOOST_TEST( p->use_count() == 0 );
BOOST_TEST( N::base::instances == 2 );
px.reset( p, true );
BOOST_TEST( px.get() == p );
BOOST_TEST( px->use_count() == 1 );
BOOST_TEST( N::base::instances == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new X );
BOOST_TEST( px.get() != 0 );
BOOST_TEST( px->use_count() == 1 );
BOOST_TEST( N::base::instances == 1 );
X * p = new X;
BOOST_TEST( p->use_count() == 0 );
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
using boost::intrusive_ptr_add_ref;
#endif
intrusive_ptr_add_ref( p );
BOOST_TEST( p->use_count() == 1 );
BOOST_TEST( N::base::instances == 2 );
px.reset( p, false );
BOOST_TEST( px.get() == p );
BOOST_TEST( px->use_count() == 1 );
BOOST_TEST( N::base::instances == 1 );
}
BOOST_TEST( N::base::instances == 0 );
}
} // namespace n_reset
namespace n_access namespace n_access
{ {
@@ -330,6 +532,30 @@ void test()
BOOST_TEST(get_pointer(px) == px.get()); BOOST_TEST(get_pointer(px) == px.get());
} }
{
boost::intrusive_ptr<X> px;
X* detached = px.detach();
BOOST_TEST( px.get() == 0 );
BOOST_TEST( detached == 0 );
}
{
X * p = new X;
BOOST_TEST( p->use_count() == 0 );
boost::intrusive_ptr<X> px( p );
BOOST_TEST( px.get() == p );
BOOST_TEST( px->use_count() == 1 );
X * detached = px.detach();
BOOST_TEST( px.get() == 0 );
BOOST_TEST( detached == p );
BOOST_TEST( detached->use_count() == 1 );
delete detached;
}
} }
} // namespace n_access } // namespace n_access
@@ -548,6 +774,7 @@ int main()
n_constructors::test(); n_constructors::test();
n_destructor::test(); n_destructor::test();
n_assignment::test(); n_assignment::test();
n_reset::test();
n_access::test(); n_access::test();
n_swap::test(); n_swap::test();
n_comparison::test(); n_comparison::test();

View File

@@ -1,172 +0,0 @@
// make_shared_array_args_test.cpp
//
// Copyright 2007-2009, 2012 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/lightweight_test.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <cstddef>
class X
{
private:
X( X const & );
X & operator=( X const & );
void * operator new[]( std::size_t n );
void operator delete[]( void * 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_TEST( X::instances == 0 );
{
boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 0 );
BOOST_TEST( px[1].v == 0 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
{
boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1 );
BOOST_TEST( px[1].v == 1 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2 );
BOOST_TEST( px[1].v == 1+2 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2+3 );
BOOST_TEST( px[1].v == 1+2+3 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2+3+4 );
BOOST_TEST( px[1].v == 1+2+3+4 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2+3+4+5 );
BOOST_TEST( px[1].v == 1+2+3+4+5 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5, 6 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2+3+4+5+6 );
BOOST_TEST( px[1].v == 1+2+3+4+5+6 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5, 6, 7 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2+3+4+5+6+7 );
BOOST_TEST( px[1].v == 1+2+3+4+5+6+7 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5, 6, 7, 8 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2+3+4+5+6+7+8 );
BOOST_TEST( px[1].v == 1+2+3+4+5+6+7+8 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5, 6, 7, 8, 9 );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( px[0].v == 1+2+3+4+5+6+7+8+9 );
BOOST_TEST( px[1].v == 1+2+3+4+5+6+7+8+9 );
px.reset();
BOOST_TEST( X::instances == 0 );
}
#endif
return boost::report_errors();
}

View File

@@ -1,114 +0,0 @@
/*
* Copyright (c) 2012 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_shared_array.hpp>
class type {
public:
static int instances;
explicit type(int a=0, int b=0, int c=0, int d=0, int e=0, int f=0, int g=0, int h=0, int i=0)
: a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h), i(i) {
instances++;
}
~type() {
instances--;
}
const int a;
const int b;
const int c;
const int d;
const int e;
const int f;
const int g;
const int h;
const int i;
private:
type(const type&);
type& operator=(const type&);
};
int type::instances = 0;
int main() {
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[]> a1 = boost::make_shared<type[]>(2, 1, 2, 3, 4, 5, 6, 7, 8, 9);
BOOST_TEST(type::instances == 2);
BOOST_TEST(a1[0].a == 1);
BOOST_TEST(a1[0].d == 4);
BOOST_TEST(a1[1].f == 6);
BOOST_TEST(a1[1].i == 9);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2]> a1 = boost::make_shared<type[2]>(1, 2, 3, 4, 5, 6, 7, 8, 9);
BOOST_TEST(type::instances == 2);
BOOST_TEST(a1[0].a == 1);
BOOST_TEST(a1[0].d == 4);
BOOST_TEST(a1[1].f == 6);
BOOST_TEST(a1[1].i == 9);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[][2]> a1 = boost::make_shared<type[][2]>(2, 1, 2, 3, 4, 5, 6, 7);
BOOST_TEST(type::instances == 4);
BOOST_TEST(a1[0][0].a == 1);
BOOST_TEST(a1[0][1].d == 4);
BOOST_TEST(a1[1][0].f == 6);
BOOST_TEST(a1[1][1].i == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2][2]> a1 = boost::make_shared<type[2][2]>(1, 2, 3, 4, 5, 6, 7);
BOOST_TEST(type::instances == 4);
BOOST_TEST(a1[0][0].a == 1);
BOOST_TEST(a1[0][1].d == 4);
BOOST_TEST(a1[1][0].f == 6);
BOOST_TEST(a1[1][1].i == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[][2][2]> a1 = boost::make_shared<type[][2][2]>(2, 1, 2, 3, 4, 5);
BOOST_TEST(type::instances == 8);
BOOST_TEST(a1[0][0][0].a == 1);
BOOST_TEST(a1[0][1][0].c == 3);
BOOST_TEST(a1[1][0][1].e == 5);
BOOST_TEST(a1[1][1][1].i == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2][2][2]> a1 = boost::make_shared<type[2][2][2]>(1, 2, 3, 4, 5);
BOOST_TEST(type::instances == 8);
BOOST_TEST(a1[0][0][0].a == 1);
BOOST_TEST(a1[0][1][0].c == 3);
BOOST_TEST(a1[1][0][1].e == 5);
BOOST_TEST(a1[1][1][1].i == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[][2][2][2]> a1 = boost::make_shared<type[][2][2][2]>(2, 1, 2, 3);
BOOST_TEST(type::instances == 16);
BOOST_TEST(a1[0][0][0][1].a == 1);
BOOST_TEST(a1[0][0][1][0].c == 3);
BOOST_TEST(a1[0][1][0][0].f == 0);
BOOST_TEST(a1[1][0][0][0].i == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2][2][2][2]> a1 = boost::make_shared<type[2][2][2][2]>(1, 2, 3);
BOOST_TEST(type::instances == 16);
BOOST_TEST(a1[0][0][0][1].a == 1);
BOOST_TEST(a1[0][0][1][0].c == 3);
BOOST_TEST(a1[0][1][0][0].f == 0);
BOOST_TEST(a1[1][0][0][0].i == 0);
}
#endif
return boost::report_errors();
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Glen Joseph Fernandes * Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com * glenfe at live dot com
* *
* Distributed under the Boost Software License, * Distributed under the Boost Software License,
@@ -14,12 +14,15 @@ class type
: public boost::enable_shared_from_this<type> { : public boost::enable_shared_from_this<type> {
public: public:
static unsigned int instances; static unsigned int instances;
explicit type() { explicit type() {
instances++; instances++;
} }
~type() { ~type() {
instances--; instances--;
} }
private: private:
type(const type&); type(const type&);
type& operator=(const type&); type& operator=(const type&);
@@ -38,6 +41,7 @@ int main() {
BOOST_TEST(type::instances == 3); BOOST_TEST(type::instances == 3);
} }
} }
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<type[]> a1 = boost::make_shared_noinit<type[]>(3); boost::shared_ptr<type[]> a1 = boost::make_shared_noinit<type[]>(3);
@@ -48,5 +52,6 @@ int main() {
BOOST_TEST(type::instances == 3); BOOST_TEST(type::instances == 3);
} }
} }
return boost::report_errors(); return boost::report_errors();
} }

View File

@@ -1,84 +0,0 @@
/*
* Copyright (c) 2012 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_shared_array.hpp>
class type {
public:
type(int value)
: value(value) {
}
const int value;
private:
type& operator=(const type&);
};
int main() {
#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
{
boost::shared_ptr<int[4]> a1 = boost::make_shared<int[4]>({ 0, 1, 2, 3 });
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 2);
BOOST_TEST(a1[3] == 3);
}
{
boost::shared_ptr<const int[4]> a1 = boost::make_shared<const int[4]>({ 0, 1, 2, 3 });
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 2);
BOOST_TEST(a1[3] == 3);
}
{
boost::shared_ptr<type[4]> a1 = boost::make_shared<type[4]>({ 0, 1, 2, 3 });
BOOST_TEST(a1[0].value == 0);
BOOST_TEST(a1[1].value == 1);
BOOST_TEST(a1[2].value == 2);
BOOST_TEST(a1[3].value == 3);
}
{
boost::shared_ptr<const type[4]> a1 = boost::make_shared<const type[4]>({ 0, 1, 2, 3 });
BOOST_TEST(a1[0].value == 0);
BOOST_TEST(a1[1].value == 1);
BOOST_TEST(a1[2].value == 2);
BOOST_TEST(a1[3].value == 3);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
{
boost::shared_ptr<int[]> a1 = boost::make_shared<int[]>({ 0, 1, 2, 3 });
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 2);
BOOST_TEST(a1[3] == 3);
}
{
boost::shared_ptr<const int[]> a1 = boost::make_shared<const int[]>({ 0, 1, 2, 3 });
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 2);
BOOST_TEST(a1[3] == 3);
}
{
boost::shared_ptr<type[]> a1 = boost::make_shared<type[]>({ 0, 1, 2, 3 });
BOOST_TEST(a1[0].value == 0);
BOOST_TEST(a1[1].value == 1);
BOOST_TEST(a1[2].value == 2);
BOOST_TEST(a1[3].value == 3);
}
{
boost::shared_ptr<const type[]> a1 = boost::make_shared<const type[]>({ 0, 1, 2, 3 });
BOOST_TEST(a1[0].value == 0);
BOOST_TEST(a1[1].value == 1);
BOOST_TEST(a1[2].value == 2);
BOOST_TEST(a1[3].value == 3);
}
#endif
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,181 @@
/*
* Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_shared_array.hpp>
#include <boost/smart_ptr/weak_ptr.hpp>
#include <boost/type_traits/alignment_of.hpp>
class type {
public:
static unsigned int instances;
explicit type() {
instances++;
}
~type() {
instances--;
}
private:
type(const type&);
type& operator=(const type&);
};
unsigned int type::instances = 0;
int main() {
{
boost::shared_ptr<int[]> a1 = boost::make_shared_noinit<int[]>(3);
int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
{
boost::shared_ptr<int[3]> a1 = boost::make_shared_noinit<int[3]>();
int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
{
boost::shared_ptr<int[][2]> a1 = boost::make_shared_noinit<int[][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
{
boost::shared_ptr<int[2][2]> a1 = boost::make_shared_noinit<int[2][2]>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
{
boost::shared_ptr<const int[]> a1 = boost::make_shared_noinit<const int[]>(3);
const int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
{
boost::shared_ptr<const int[3]> a1 = boost::make_shared_noinit<const int[3]>();
const int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
{
boost::shared_ptr<const int[][2]> a1 = boost::make_shared_noinit<const int[][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
{
boost::shared_ptr<const int[2][2]> a1 = boost::make_shared_noinit<const int[2][2]>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[]> a1 = boost::make_shared_noinit<type[]>(3);
type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
boost::weak_ptr<type[]> w1 = a1;
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[3]> a1 = boost::make_shared_noinit<type[3]>();
type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
boost::weak_ptr<type[3]> w1 = a1;
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[][2]> a1 = boost::make_shared_noinit<type[][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2][2]> a1 = boost::make_shared_noinit<type[2][2]>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[]> a1 = boost::make_shared_noinit<const type[]>(3);
const type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[3]> a1 = boost::make_shared_noinit<const type[3]>();
const type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[][2]> a1 = boost::make_shared_noinit<const type[][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[2][2]> a1 = boost::make_shared_noinit<const type[2][2]>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Glen Joseph Fernandes * Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com * glenfe at live dot com
* *
* Distributed under the Boost Software License, * Distributed under the Boost Software License,
@@ -14,17 +14,18 @@
class type { class type {
public: public:
static unsigned int instances; static unsigned int instances;
explicit type(int = 0, int = 0)
: member() { explicit type() {
instances++; instances++;
} }
~type() { ~type() {
instances--; instances--;
} }
private: private:
type(const type&); type(const type&);
type& operator=(const type&); type& operator=(const type&);
double member;
}; };
unsigned int type::instances = 0; unsigned int type::instances = 0;
@@ -40,6 +41,38 @@ int main() {
BOOST_TEST(a1[1] == 0); BOOST_TEST(a1[1] == 0);
BOOST_TEST(a1[2] == 0); BOOST_TEST(a1[2] == 0);
} }
{
boost::shared_ptr<int[3]> a1 = boost::make_shared<int[3]>();
int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 0);
BOOST_TEST(a1[2] == 0);
}
{
boost::shared_ptr<int[][2]> a1 = boost::make_shared<int[][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 0);
BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[1][1] == 0);
}
{
boost::shared_ptr<int[2][2]> a1 = boost::make_shared<int[2][2]>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 0);
BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[1][1] == 0);
}
{ {
boost::shared_ptr<const int[]> a1 = boost::make_shared<const int[]>(3); boost::shared_ptr<const int[]> a1 = boost::make_shared<const int[]>(3);
const int* a2 = a1.get(); const int* a2 = a1.get();
@@ -50,6 +83,38 @@ int main() {
BOOST_TEST(a1[1] == 0); BOOST_TEST(a1[1] == 0);
BOOST_TEST(a1[2] == 0); BOOST_TEST(a1[2] == 0);
} }
{
boost::shared_ptr<const int[3]> a1 = boost::make_shared<const int[3]>();
const int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 0);
BOOST_TEST(a1[2] == 0);
}
{
boost::shared_ptr<const int[][2]> a1 = boost::make_shared<const int[][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 0);
BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[1][1] == 0);
}
{
boost::shared_ptr<const int[2][2]> a1 = boost::make_shared<const int[2][2]>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 0);
BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[1][1] == 0);
}
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<type[]> a1 = boost::make_shared<type[]>(3); boost::shared_ptr<type[]> a1 = boost::make_shared<type[]>(3);
@@ -62,6 +127,40 @@ int main() {
a1.reset(); a1.reset();
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[3]> a1 = boost::make_shared<type[3]>();
type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
boost::weak_ptr<type[3]> w1 = a1;
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[][2]> a1 = boost::make_shared<type[][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2][2]> a1 = boost::make_shared<type[2][2]>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<const type[]> a1 = boost::make_shared<const type[]>(3); boost::shared_ptr<const type[]> a1 = boost::make_shared<const type[]>(3);
@@ -73,109 +172,10 @@ int main() {
a1.reset(); a1.reset();
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<type[]> a1 = boost::make_shared<type[]>(3, 1, 5); boost::shared_ptr<const type[3]> a1 = boost::make_shared<const type[3]>();
type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
boost::weak_ptr<type[]> w1 = a1;
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[3]> a1 = boost::make_shared<type[3]>(1, 5);
type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
boost::weak_ptr<type[3]> w1 = a1;
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[]> a1 = boost::make_shared<const type[]>(3, 1, 5);
const type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[3]> a1 = boost::make_shared<const type[3]>(1, 5);
const type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
a1.reset();
BOOST_TEST(type::instances == 0);
}
#endif
{
boost::shared_ptr<int[]> a1 = boost::make_shared_noinit<int[]>(3);
int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
{
boost::shared_ptr<int[3]> a1 = boost::make_shared_noinit<int[3]>();
int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
{
boost::shared_ptr<const int[]> a1 = boost::make_shared_noinit<const int[]>(3);
const int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
{
boost::shared_ptr<const int[3]> a1 = boost::make_shared_noinit<const int[3]>();
const int* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<int>::value == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[]> a1 = boost::make_shared_noinit<type[]>(3);
type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
boost::weak_ptr<type[]> w1 = a1;
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[3]> a1 = boost::make_shared_noinit<type[3]>();
type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
boost::weak_ptr<type[3]> w1 = a1;
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[]> a1 = boost::make_shared_noinit<const type[]>(3);
const type* a2 = a1.get(); const type* a2 = a1.get();
BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0); BOOST_TEST(a2 != 0);
@@ -184,16 +184,26 @@ int main() {
a1.reset(); a1.reset();
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<const type[3]> a1 = boost::make_shared_noinit<const type[3]>(); boost::shared_ptr<const type[][2]> a1 = boost::make_shared<const type[][2]>(2);
const type* a2 = a1.get(); BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a2 != 0); BOOST_TEST(type::instances == 4);
BOOST_TEST(size_t(a2) % boost::alignment_of<type>::value == 0);
BOOST_TEST(type::instances == 3);
a1.reset(); a1.reset();
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[2][2]> a1 = boost::make_shared<const type[2][2]>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors(); return boost::report_errors();
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Glen Joseph Fernandes * Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com * glenfe at live dot com
* *
* Distributed under the Boost Software License, * Distributed under the Boost Software License,
@@ -12,15 +12,18 @@
class type { class type {
public: public:
static unsigned int instances; static unsigned int instances;
explicit type() { explicit type() {
if (instances == 5) { if (instances == 5) {
throw true; throw true;
} }
instances++; instances++;
} }
~type() { ~type() {
instances--; instances--;
} }
private: private:
type(const type&); type(const type&);
type& operator=(const type&); type& operator=(const type&);
@@ -36,6 +39,7 @@ int main() {
} catch (...) { } catch (...) {
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
try { try {
boost::make_shared<type[][2]>(3); boost::make_shared<type[][2]>(3);
@@ -43,7 +47,7 @@ int main() {
} catch (...) { } catch (...) {
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
try { try {
boost::make_shared<type[6]>(); boost::make_shared<type[6]>();
@@ -51,6 +55,7 @@ int main() {
} catch (...) { } catch (...) {
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
try { try {
boost::make_shared<type[3][2]>(); boost::make_shared<type[3][2]>();
@@ -58,7 +63,7 @@ int main() {
} catch (...) { } catch (...) {
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
#endif
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
try { try {
boost::make_shared_noinit<type[]>(6); boost::make_shared_noinit<type[]>(6);
@@ -66,6 +71,7 @@ int main() {
} catch (...) { } catch (...) {
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
try { try {
boost::make_shared_noinit<type[][2]>(3); boost::make_shared_noinit<type[][2]>(3);
@@ -73,5 +79,22 @@ int main() {
} catch (...) { } catch (...) {
BOOST_TEST(type::instances == 0); BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0);
try {
boost::make_shared_noinit<type[6]>();
BOOST_ERROR("make_shared_noinit did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
try {
boost::make_shared_noinit<type[3][2]>();
BOOST_ERROR("make_shared_noinit did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
return boost::report_errors(); return boost::report_errors();
} }

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_shared_array.hpp>
int main() {
{
boost::shared_ptr<int[]> a1 = boost::make_shared<int[]>(4, 1);
BOOST_TEST(a1[0] == 1);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 1);
BOOST_TEST(a1[3] == 1);
}
{
boost::shared_ptr<int[4]> a1 = boost::make_shared<int[4]>(1);
BOOST_TEST(a1[0] == 1);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 1);
BOOST_TEST(a1[3] == 1);
}
{
boost::shared_ptr<const int[]> a1 = boost::make_shared<const int[]>(4, 1);
BOOST_TEST(a1[0] == 1);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 1);
BOOST_TEST(a1[3] == 1);
}
{
boost::shared_ptr<const int[4]> a1 = boost::make_shared<const int[4]>(1);
BOOST_TEST(a1[0] == 1);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 1);
BOOST_TEST(a1[3] == 1);
}
return boost::report_errors();
}

View File

@@ -1,94 +0,0 @@
/*
* Copyright (c) 2012 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_shared_array.hpp>
class type {
public:
type(int x, int y)
: x(x), y(y) {
}
const int x;
const int y;
private:
type& operator=(const type&);
};
int main() {
#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
{
boost::shared_ptr<int[4]> a1 = boost::make_shared<int[4]>({0, 1, 2, 3});
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 2);
BOOST_TEST(a1[3] == 3);
}
{
boost::shared_ptr<int[2][2]> a1 = boost::make_shared<int[2][2]>({ {0, 1}, {2, 3} });
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(a1[1][0] == 2);
BOOST_TEST(a1[1][1] == 3);
}
{
boost::shared_ptr<int[][2]> a1 = boost::make_shared<int[][2]>(2, {0, 1});
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[1][1] == 1);
}
{
boost::shared_ptr<int[][2][2]> a1 = boost::make_shared<int[][2][2]>(2, { {0, 1}, {2, 3} });
BOOST_TEST(a1[0][0][0] == 0);
BOOST_TEST(a1[0][0][1] == 1);
BOOST_TEST(a1[1][1][0] == 2);
BOOST_TEST(a1[1][1][1] == 3);
}
{
boost::shared_ptr<int[2][2]> a1 = boost::make_shared<int[2][2]>({ 0, 1 });
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[1][1] == 1);
}
{
boost::shared_ptr<int[2][2][2]> a1 = boost::make_shared<int[2][2][2]>({ {0, 1}, {2, 3} });
BOOST_TEST(a1[0][0][0] == 0);
BOOST_TEST(a1[0][0][1] == 1);
BOOST_TEST(a1[1][1][0] == 2);
BOOST_TEST(a1[1][1][1] == 3);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
{
boost::shared_ptr<int[]> a1 = boost::make_shared<int[]>({0, 1, 2, 3});
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 1);
BOOST_TEST(a1[2] == 2);
BOOST_TEST(a1[3] == 3);
}
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
{
boost::shared_ptr<type[]> a1 = boost::make_shared<type[]>(4, {1, 2});
BOOST_TEST(a1[0].x == 1);
BOOST_TEST(a1[1].y == 2);
BOOST_TEST(a1[2].x == 1);
BOOST_TEST(a1[3].y == 2);
}
{
boost::shared_ptr<type[4]> a1 = boost::make_shared<type[4]>({1, 2});
BOOST_TEST(a1[0].x == 1);
BOOST_TEST(a1[1].y == 2);
BOOST_TEST(a1[2].x == 1);
BOOST_TEST(a1[3].y == 2);
}
#endif
#endif
return boost::report_errors();
}

View File

@@ -1,23 +0,0 @@
/*
* Copyright (c) 2012 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_shared_array.hpp>
int main() {
#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
{
boost::shared_ptr<int[][2]> a1 = boost::make_shared<int[][2]>({ {0, 1}, {2, 3} });
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(a1[1][0] == 2);
BOOST_TEST(a1[1][1] == 3);
}
#endif
return boost::report_errors();
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012 Glen Joseph Fernandes * Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com * glenfe at live dot com
* *
* Distributed under the Boost Software License, * Distributed under the Boost Software License,
@@ -9,152 +9,40 @@
#include <boost/detail/lightweight_test.hpp> #include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_shared_array.hpp> #include <boost/smart_ptr/make_shared_array.hpp>
class type {
public:
static unsigned int instances;
explicit type(int = 0, int = 0)
: member() {
instances++;
}
~type() {
instances--;
}
private:
type(const type&);
type& operator=(const type&);
double member;
};
unsigned int type::instances = 0;
int main() { int main() {
#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
{ {
boost::shared_ptr<int[][2][2]> a1 = boost::make_shared<int[][2][2]>(2); boost::shared_ptr<int[][2]> a1 = boost::make_shared<int[][2]>(2, {0, 1});
BOOST_TEST(a1.get() != 0); BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(a1[0][0][1] == 0); BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[0][1][0] == 0); BOOST_TEST(a1[1][1] == 1);
BOOST_TEST(a1[1][0][0] == 0);
}
{
boost::shared_ptr<const int[][2][2]> a1 = boost::make_shared<const int[][2][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a1[0][0][1] == 0);
BOOST_TEST(a1[0][1][0] == 0);
BOOST_TEST(a1[1][0][0] == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[][2][2]> a1 = boost::make_shared<type[][2][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[][2][2]> a1 = boost::make_shared<const type[][2][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
} }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<type[][2][2]> a1 = boost::make_shared<type[][2][2]>(2, 1, 5); boost::shared_ptr<int[2][2]> a1 = boost::make_shared<int[2][2]>({ 0, 1 });
BOOST_TEST(a1.get() != 0); BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(type::instances == 8); BOOST_TEST(a1[1][0] == 0);
a1.reset(); BOOST_TEST(a1[1][1] == 1);
BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<type[2][2][2]> a1 = boost::make_shared<type[2][2][2]>(1, 5); boost::shared_ptr<const int[][2]> a1 = boost::make_shared<const int[][2]>(2, { 0, 1 });
BOOST_TEST(a1.get() != 0); BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(type::instances == 8); BOOST_TEST(a1[1][0] == 0);
a1.reset(); BOOST_TEST(a1[1][1] == 1);
BOOST_TEST(type::instances == 0);
} }
BOOST_TEST(type::instances == 0);
{ {
boost::shared_ptr<const type[][2][2]> a1 = boost::make_shared<const type[][2][2]>(2, 1, 5); boost::shared_ptr<const int[2][2]> a1 = boost::make_shared<const int[2][2]>({ 0, 1 });
BOOST_TEST(a1.get() != 0); BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1[0][1] == 1);
BOOST_TEST(type::instances == 8); BOOST_TEST(a1[1][0] == 0);
a1.reset(); BOOST_TEST(a1[1][1] == 1);
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[2][2][2]> a1 = boost::make_shared<const type[2][2][2]>(1, 5);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
} }
#endif #endif
{
boost::shared_ptr<int[][2][2]> a1 = boost::make_shared_noinit<int[][2][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
{
boost::shared_ptr<int[2][2][2]> a1 = boost::make_shared_noinit<int[2][2][2]>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
{
boost::shared_ptr<const int[][2][2]> a1 = boost::make_shared_noinit<const int[][2][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
{
boost::shared_ptr<const int[2][2][2]> a1 = boost::make_shared_noinit<const int[2][2][2]>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[][2][2]> a1 = boost::make_shared_noinit<type[][2][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<type[2][2][2]> a1 = boost::make_shared_noinit<type[2][2][2]>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[][2][2]> a1 = boost::make_shared_noinit<const type[][2][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
boost::shared_ptr<const type[2][2][2]> a1 = boost::make_shared_noinit<const type[2][2][2]>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 8);
a1.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors(); return boost::report_errors();
} }

View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_unique_object.hpp>
class type {
public:
static unsigned int instances;
explicit type(int v1 = 0,
int v2 = 0,
int v3 = 0,
int v4 = 0,
int v5 = 0,
int v6 = 0,
int v7 = 0,
int v8 = 0,
int v9 = 0)
: sum(v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9) {
instances++;
}
~type() {
instances--;
}
const int sum;
private:
type(const type&);
type& operator=(const type&);
};
unsigned int type::instances = 0;
int main() {
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<type> a1 = boost::make_unique<type>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 1);
BOOST_TEST(a1->sum == 0);
a1.reset();
BOOST_TEST(type::instances == 0);
}
#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES )
{
std::unique_ptr<type> a1 = boost::make_unique<type>(1);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 1);
BOOST_TEST(a1->sum == 1);
a1.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type> a1 = boost::make_unique<type>(1, 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 1);
BOOST_TEST(a1->sum == 1 + 2);
a1.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type> a1 = boost::make_unique<type>(1, 2, 3);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 1);
BOOST_TEST(a1->sum == 1 + 2 + 3);
a1.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type> a1 = boost::make_unique<type>(1, 2, 3, 4);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 1);
BOOST_TEST(a1->sum == 1 + 2 + 3 + 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type> a1 = boost::make_unique<type>(1, 2, 3, 4, 5);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 1);
BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5);
a1.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type> a1 = boost::make_unique<type>(1, 2, 3, 4, 5, 6);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 1);
BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5 + 6);
a1.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type> a1 = boost::make_unique<type>(1, 2, 3, 4, 5, 6, 7);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 1);
BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5 + 6 + 7);
a1.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type> a1 = boost::make_unique<type>(1, 2, 3, 4, 5, 6, 7, 8);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 1);
BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8);
a1.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type> a1 = boost::make_unique<type>(1, 2, 3, 4, 5, 6, 7, 8, 9);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 1);
BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9);
a1.reset();
BOOST_TEST(type::instances == 0);
}
#endif
return boost::report_errors();
}
#else
int main() {
return 0;
}
#endif

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_unique_array.hpp>
class type {
public:
static unsigned int instances;
explicit type() {
instances++;
}
~type() {
instances--;
}
private:
type(const type&);
type& operator=(const type&);
};
unsigned int type::instances = 0;
int main() {
{
std::unique_ptr<int[]> a1 = boost::make_unique_noinit<int[]>(3);
BOOST_TEST(a1.get() != 0);
}
{
std::unique_ptr<int[][2]> a1 = boost::make_unique_noinit<int[][2]>(2);
BOOST_TEST(a1.get() != 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<type[]> a1 = boost::make_unique_noinit<type[]>(3);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 3);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<type[][2]> a1 = boost::make_unique_noinit<type[][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<const type[]> a1 = boost::make_unique_noinit<const type[]>(3);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 3);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<const type[][2]> a1 = boost::make_unique_noinit<const type[][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main() {
return 0;
}
#endif

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_unique_array.hpp>
class type {
public:
static unsigned int instances;
explicit type() {
instances++;
}
~type() {
instances--;
}
private:
type(const type&);
type& operator=(const type&);
};
unsigned int type::instances = 0;
int main() {
{
std::unique_ptr<int[]> a1 = boost::make_unique<int[]>(3);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 0);
BOOST_TEST(a1[2] == 0);
}
{
std::unique_ptr<int[][2]> a1 = boost::make_unique<int[][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 0);
BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[1][1] == 0);
}
{
std::unique_ptr<const int[]> a1 = boost::make_unique<const int[]>(3);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1[0] == 0);
BOOST_TEST(a1[1] == 0);
BOOST_TEST(a1[2] == 0);
}
{
std::unique_ptr<const int[][2]> a1 = boost::make_unique<const int[][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1[0][0] == 0);
BOOST_TEST(a1[0][1] == 0);
BOOST_TEST(a1[1][0] == 0);
BOOST_TEST(a1[1][1] == 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<type[]> a1 = boost::make_unique<type[]>(3);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 3);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<type[][2]> a1 = boost::make_unique<type[][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<const type[]> a1 = boost::make_unique<const type[]>(3);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 3);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<const type[][2]> a1 = boost::make_unique<const type[][2]>(2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main() {
return 0;
}
#endif

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_unique_array.hpp>
class type {
public:
static unsigned int instances;
explicit type() {
if (instances == 5) {
throw true;
}
instances++;
}
~type() {
instances--;
}
private:
type(const type&);
type& operator=(const type&);
};
unsigned int type::instances = 0;
int main() {
BOOST_TEST(type::instances == 0);
try {
boost::make_unique<type[]>(6);
BOOST_ERROR("make_unique did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
try {
boost::make_unique<type[][2]>(3);
BOOST_ERROR("make_unique did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
try {
boost::make_unique_noinit<type[]>(6);
BOOST_ERROR("make_unique_noinit did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
try {
boost::make_unique_noinit<type[][2]>(3);
BOOST_ERROR("make_unique_noinit did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main() {
return 0;
}
#endif

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_unique_object.hpp>
class type {
public:
static unsigned int instances;
explicit type() {
instances++;
}
~type() {
instances--;
}
private:
type(const type&);
type& operator=(const type&);
};
unsigned int type::instances = 0;
int main() {
{
std::unique_ptr<int> a1 = boost::make_unique_noinit<int>();
BOOST_TEST(a1.get() != 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<type> a1 = boost::make_unique_noinit<type>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 1);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<const type> a1 = boost::make_unique_noinit<const type>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 1);
a1.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main() {
return 0;
}
#endif

72
test/make_unique_test.cpp Normal file
View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_unique_object.hpp>
class type {
public:
static unsigned int instances;
explicit type() {
instances++;
}
~type() {
instances--;
}
private:
type(const type&);
type& operator=(const type&);
};
unsigned int type::instances = 0;
int main() {
{
std::unique_ptr<int> a1 = boost::make_unique<int>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(*a1 == 0);
}
{
std::unique_ptr<const int> a1 = boost::make_unique<const int>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(*a1 == 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<type> a1 = boost::make_unique<type>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 1);
a1.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<const type> a1 = boost::make_unique<const type>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 1);
a1.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main() {
return 0;
}
#endif

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_unique_object.hpp>
class type {
public:
static unsigned int instances;
explicit type() {
if (instances == 0) {
throw true;
}
instances++;
}
~type() {
instances--;
}
private:
type(const type&);
type& operator=(const type&);
};
unsigned int type::instances = 0;
int main() {
BOOST_TEST(type::instances == 0);
try {
boost::make_unique<type>();
BOOST_ERROR("make_unique did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main() {
return 0;
}
#endif

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/detail/lightweight_test.hpp>
#include <boost/smart_ptr/make_unique_object.hpp>
struct type {
int x;
int y;
};
int main() {
{
std::unique_ptr<type> a1 = boost::make_unique<type>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1->x == 0);
BOOST_TEST(a1->y == 0);
}
{
std::unique_ptr<const type> a1 = boost::make_unique<const type>();
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1->x == 0);
BOOST_TEST(a1->y == 0);
}
#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
{
std::unique_ptr<type> a1 = boost::make_unique<type>({ 1, 2 });
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1->x == 1);
BOOST_TEST(a1->y == 2);
}
{
std::unique_ptr<const type> a1 = boost::make_unique<const type>({ 1, 2 });
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1->x == 1);
BOOST_TEST(a1->y == 2);
}
#endif
return boost::report_errors();
}
#else
int main() {
return 0;
}
#endif

112
test/sa_nullptr_test.cpp Normal file
View File

@@ -0,0 +1,112 @@
//
// shared_array nullptr test
//
// Copyright 2012, 2013 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/shared_array.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <cstddef>
#include <memory>
#if !defined( BOOST_NO_CXX11_NULLPTR )
struct X
{
static int instances;
X()
{
++instances;
}
~X()
{
--instances;
}
private:
X( X const & );
X & operator=( X const & );
};
int X::instances = 0;
int main()
{
{
boost::shared_array<int> p( nullptr );
BOOST_TEST( p.get() == 0 );
BOOST_TEST( p.use_count() == 0 );
BOOST_TEST( p == nullptr );
BOOST_TEST( nullptr == p );
BOOST_TEST( !( p != nullptr ) );
BOOST_TEST( !( nullptr != p ) );
}
{
boost::shared_array<int> p( new int[ 1 ] );
BOOST_TEST( p.get() != 0 );
BOOST_TEST( p.use_count() == 1 );
BOOST_TEST( p != nullptr );
BOOST_TEST( nullptr != p );
BOOST_TEST( !( p == nullptr ) );
BOOST_TEST( !( nullptr == p ) );
p = nullptr;
BOOST_TEST( p.get() == 0 );
BOOST_TEST( p.use_count() == 0 );
BOOST_TEST( p == nullptr );
BOOST_TEST( nullptr == p );
BOOST_TEST( !( p != nullptr ) );
BOOST_TEST( !( nullptr != p ) );
}
{
BOOST_TEST( X::instances == 0 );
boost::shared_array<X> p( new X[ 2 ] );
BOOST_TEST( X::instances == 2 );
BOOST_TEST( p.get() != 0 );
BOOST_TEST( p.use_count() == 1 );
BOOST_TEST( p != nullptr );
BOOST_TEST( nullptr != p );
BOOST_TEST( !( p == nullptr ) );
BOOST_TEST( !( nullptr == p ) );
p = nullptr;
BOOST_TEST( X::instances == 0 );
BOOST_TEST( p.get() == 0 );
BOOST_TEST( p.use_count() == 0 );
BOOST_TEST( p == nullptr );
BOOST_TEST( nullptr == p );
BOOST_TEST( !( p != nullptr ) );
BOOST_TEST( !( nullptr != p ) );
}
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif

View File

@@ -0,0 +1,116 @@
#include <boost/config.hpp>
// shared_ptr_alloc11_test.cpp
//
// Test the allocator constructor with a C++11 minimal allocator
//
// Copyright (c) 2005, 2014 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/lightweight_test.hpp>
#include <boost/shared_ptr.hpp>
#include <memory>
#include <cstddef>
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
template< class T > class cxx11_allocator
{
public:
typedef T value_type;
cxx11_allocator()
{
}
template< class Y > cxx11_allocator( cxx11_allocator<Y> const & )
{
}
T * allocate( std::size_t n )
{
return static_cast< T* >( ::operator new( n * sizeof( T ) ) );
}
void deallocate( T * p, std::size_t n )
{
::operator delete( p );
}
};
//
struct D;
struct X
{
static int instances;
X(): deleted_( false )
{
++instances;
}
~X()
{
BOOST_TEST( deleted_ );
--instances;
}
private:
friend struct D;
bool deleted_;
X( X const & );
X & operator=( X const & );
};
int X::instances = 0;
struct D
{
void operator()( X * px ) const
{
px->deleted_ = true;
delete px;
}
};
int main()
{
BOOST_TEST( X::instances == 0 );
boost::shared_ptr<void> pv( new X, D(), cxx11_allocator<X>() );
BOOST_TEST( X::instances == 1 );
pv.reset();
BOOST_TEST( X::instances == 0 );
pv.reset( new X, D(), cxx11_allocator<void>() );
BOOST_TEST( X::instances == 1 );
pv.reset();
BOOST_TEST( X::instances == 0 );
return boost::report_errors();
}
#else // !defined( BOOST_NO_CXX11_ALLOCATOR )
int main()
{
return 0;
}
#endif

View File

@@ -91,7 +91,7 @@ public:
::operator delete( p ); ::operator delete( p );
} }
pointer allocate( size_type n, void const * ) pointer allocate( size_type n, void const * = 0 )
{ {
T * p = static_cast< T* >( ::operator new( n * sizeof( T ) ) ); T * p = static_cast< T* >( ::operator new( n * sizeof( T ) ) );
@@ -107,7 +107,7 @@ public:
void construct( pointer p, T const & t ) void construct( pointer p, T const & t )
{ {
new( p ) T( t ); ::new( p ) T( t );
} }
void destroy( pointer p ) void destroy( pointer p )

View File

@@ -0,0 +1,78 @@
#include <boost/config.hpp>
// shared_ptr_alloc3_test.cpp
//
// Copyright (c) 2005, 2014 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/lightweight_test.hpp>
#include <boost/shared_ptr.hpp>
#include <memory>
#include <cstddef>
//
struct D;
struct X
{
static int instances;
X(): deleted_( false )
{
++instances;
}
~X()
{
BOOST_TEST( deleted_ );
--instances;
}
private:
friend struct D;
bool deleted_;
X( X const & );
X & operator=( X const & );
};
int X::instances = 0;
struct D
{
void operator()( X * px ) const
{
px->deleted_ = true;
delete px;
}
};
int main()
{
BOOST_TEST( X::instances == 0 );
boost::shared_ptr<void> pv( new X, D(), std::allocator<X>() );
BOOST_TEST( X::instances == 1 );
pv.reset();
BOOST_TEST( X::instances == 0 );
pv.reset( new X, D(), std::allocator<void>() );
BOOST_TEST( X::instances == 1 );
pv.reset();
BOOST_TEST( X::instances == 0 );
return boost::report_errors();
}

View File

@@ -1,42 +1,42 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>weak_ptr</title> <title>weak_ptr</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head> </head>
<body text="#000000" bgColor="#ffffff"> <body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle" <h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
border="0"></A>weak_ptr class template</h1> width="277" align="middle" border="0">weak_ptr class template</h1>
<p><A href="#Introduction">Introduction</A><br> <p><A href="#Introduction">Introduction</A><br>
<A href="#Synopsis">Synopsis</A><br> <A href="#Synopsis">Synopsis</A><br>
<A href="#Members">Members</A><br> <A href="#Members">Members</A><br>
<A href="#functions">Free Functions</A><br> <A href="#functions">Free Functions</A><br>
<A href="#FAQ">Frequently Asked Questions</A> <A href="#FAQ">Frequently Asked Questions</A>
</p> </p>
<h2><a name="Introduction">Introduction</a></h2> <h2><a name="Introduction">Introduction</a></h2>
<p>The <b>weak_ptr</b> class template stores a "weak reference" to an object that's <p>The <b>weak_ptr</b> class template stores a "weak reference" to an object that's
already managed by a <b>shared_ptr</b>. To access the object, a <STRONG>weak_ptr</STRONG> already managed by a <b>shared_ptr</b>. To access the object, a <STRONG>weak_ptr</STRONG>
can be converted to a <STRONG>shared_ptr</STRONG> using <A href="shared_ptr.htm#constructors"> can be converted to a <STRONG>shared_ptr</STRONG> using <A href="shared_ptr.htm#constructors">
the <STRONG>shared_ptr</STRONG> constructor</A> or the member function <STRONG><A href="#lock"> the <STRONG>shared_ptr</STRONG> constructor</A> or the member function <STRONG><A href="#lock">
lock</A></STRONG>. When the last <b>shared_ptr</b> to the object goes lock</A></STRONG>. When the last <b>shared_ptr</b> to the object goes
away and the object is deleted, the attempt to obtain a <STRONG>shared_ptr</STRONG> away and the object is deleted, the attempt to obtain a <STRONG>shared_ptr</STRONG>
from the <b>weak_ptr</b> instances that refer to the deleted object will fail: from the <b>weak_ptr</b> instances that refer to the deleted object will fail:
the constructor will throw an exception of type <STRONG>boost::bad_weak_ptr</STRONG>, the constructor will throw an exception of type <STRONG>boost::bad_weak_ptr</STRONG>,
and <STRONG>weak_ptr::lock</STRONG> will return an <EM>empty</EM> <STRONG>shared_ptr</STRONG>.</p> and <STRONG>weak_ptr::lock</STRONG> will return an <EM>empty</EM> <STRONG>shared_ptr</STRONG>.</p>
<p>Every <b>weak_ptr</b> meets the <b>CopyConstructible</b> and <b>Assignable</b> requirements <p>Every <b>weak_ptr</b> meets the <b>CopyConstructible</b> and <b>Assignable</b> requirements
of the C++ Standard Library, and so can be used in standard library containers. of the C++ Standard Library, and so can be used in standard library containers.
Comparison operators are supplied so that <b>weak_ptr</b> works with the Comparison operators are supplied so that <b>weak_ptr</b> works with the
standard library's associative containers.</p> standard library's associative containers.</p>
<P><STRONG>weak_ptr</STRONG> operations never throw&nbsp;exceptions.</P> <P><STRONG>weak_ptr</STRONG> operations never throw&nbsp;exceptions.</P>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed <p>The class template is parameterized on <b>T</b>, the type of the object pointed
to.</p> to.</p>
<P>Compared to <STRONG>shared_ptr</STRONG>, <STRONG>weak_ptr</STRONG> provides a <P>Compared to <STRONG>shared_ptr</STRONG>, <STRONG>weak_ptr</STRONG> provides a
very limited subset of operations since accessing its stored pointer is often very limited subset of operations since accessing its stored pointer is often
dangerous in multithreaded programs, and sometimes unsafe even within a single dangerous in multithreaded programs, and sometimes unsafe even within a single
thread (that is, it may invoke undefined behavior.) Pretend for a moment that <b>weak_ptr</b> thread (that is, it may invoke undefined behavior.) Pretend for a moment that <b>weak_ptr</b>
has a <b>get</b> member function that returns a raw pointer, and consider this has a <b>get</b> member function that returns a raw pointer, and consider this
innocent piece of code:</P> innocent piece of code:</P>
<pre>shared_ptr&lt;int&gt; p(new int(5)); <pre>shared_ptr&lt;int&gt; p(new int(5));
weak_ptr&lt;int&gt; q(p); weak_ptr&lt;int&gt; q(p);
// some time later // some time later
@@ -46,12 +46,12 @@ if(int * r = q.get())
// use *r // use *r
} }
</pre> </pre>
<P>Imagine that after the <STRONG>if</STRONG>, but immediately before <STRONG>r</STRONG> <P>Imagine that after the <STRONG>if</STRONG>, but immediately before <STRONG>r</STRONG>
is used, another thread executes the statement <code>p.reset()</code>. Now <STRONG>r</STRONG> is used, another thread executes the statement <code>p.reset()</code>. Now <STRONG>r</STRONG>
is a dangling pointer.</P> is a dangling pointer.</P>
<P>The solution to this problem is to create a temporary <STRONG>shared_ptr</STRONG> <P>The solution to this problem is to create a temporary <STRONG>shared_ptr</STRONG>
from <STRONG>q</STRONG>:</P> from <STRONG>q</STRONG>:</P>
<pre>shared_ptr&lt;int&gt; p(new int(5)); <pre>shared_ptr&lt;int&gt; p(new int(5));
weak_ptr&lt;int&gt; q(p); weak_ptr&lt;int&gt; q(p);
// some time later // some time later
@@ -61,13 +61,13 @@ if(shared_ptr&lt;int&gt; r = q.<A href="#lock" >lock</A>())
// use *r // use *r
} }
</pre> </pre>
<p>Now <STRONG>r</STRONG> holds a reference to the object that was pointed by <STRONG>q</STRONG>. <p>Now <STRONG>r</STRONG> holds a reference to the object that was pointed by <STRONG>q</STRONG>.
Even if <code>p.reset()</code> is executed in another thread, the object will Even if <code>p.reset()</code> is executed in another thread, the object will
stay alive until <STRONG>r</STRONG> goes out of scope or is reset. By obtaining stay alive until <STRONG>r</STRONG> goes out of scope or is reset. By obtaining
a <STRONG>shared_ptr</STRONG> to the object, we have effectively locked it a <STRONG>shared_ptr</STRONG> to the object, we have effectively locked it
against destruction.</p> against destruction.</p>
<h2><a name="Synopsis">Synopsis</a></h2> <h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost { <pre>namespace boost {
template&lt;class T&gt; class weak_ptr { template&lt;class T&gt; class weak_ptr {
@@ -101,119 +101,119 @@ if(shared_ptr&lt;int&gt; r = q.<A href="#lock" >lock</A>())
void <A href="#free-swap" >swap</A>(weak_ptr&lt;T&gt; &amp; a, weak_ptr&lt;T&gt; &amp; b); void <A href="#free-swap" >swap</A>(weak_ptr&lt;T&gt; &amp; a, weak_ptr&lt;T&gt; &amp; b);
} }
</pre> </pre>
<h2><a name="Members">Members</a></h2> <h2><a name="Members">Members</a></h2>
<h3><a name="element_type">element_type</a></h3> <h3><a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre> <pre>typedef T element_type;</pre>
<blockquote> <blockquote>
<p>Provides the type of the template parameter T.</p> <p>Provides the type of the template parameter T.</p>
</blockquote> </blockquote>
<h3><a name="default-constructor">constructors</a></h3> <h3><a name="constructors">constructors</a></h3>
<pre>weak_ptr();</pre> <pre><a name="default-constructor">weak_ptr();</a></pre>
<blockquote> <blockquote>
<p><b>Effects:</b> Constructs an <EM>empty</EM> <b>weak_ptr</b>.</p> <p><b>Effects:</b> Constructs an <EM>empty</EM> <b>weak_ptr</b>.</p>
<p><b>Postconditions:</b> <code>use_count() == 0</code>.</p> <p><b>Postconditions:</b> <code>use_count() == 0</code>.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
</blockquote><a name="constructors"></a> </blockquote>
<pre>template&lt;class Y&gt; weak_ptr</A>(shared_ptr&lt;Y&gt; const &amp; r); <pre>template&lt;class Y&gt; weak_ptr(shared_ptr&lt;Y&gt; const &amp; r);
weak_ptr(weak_ptr const &amp; r); weak_ptr(weak_ptr const &amp; r);
template&lt;class Y&gt; weak_ptr(weak_ptr&lt;Y&gt; const &amp; r);</pre> template&lt;class Y&gt; weak_ptr(weak_ptr&lt;Y&gt; const &amp; r);</pre>
<blockquote> <blockquote>
<p><b>Effects:</b> If <STRONG>r</STRONG> is <EM>empty</EM>, constructs an <EM>empty</EM> <p><b>Effects:</b> If <STRONG>r</STRONG> is <EM>empty</EM>, constructs an <EM>empty</EM>
<STRONG>weak_ptr</STRONG>; otherwise, constructs a <b>weak_ptr</b> that <EM>shares <STRONG>weak_ptr</STRONG>; otherwise, constructs a <b>weak_ptr</b> that <EM>shares
ownership</EM> with <STRONG>r</STRONG> as if by storing a copy of the ownership</EM> with <STRONG>r</STRONG> as if by storing a copy of the
pointer stored in <b>r</b>.</p> pointer stored in <b>r</b>.</p>
<p><b>Postconditions:</b> <code>use_count() == r.use_count()</code>.</p> <p><b>Postconditions:</b> <code>use_count() == r.use_count()</code>.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
</blockquote> </blockquote>
<h3><a name="destructor">destructor</a></h3> <h3><a name="destructor">destructor</a></h3>
<pre>~weak_ptr();</pre> <pre>~weak_ptr();</pre>
<BLOCKQUOTE> <BLOCKQUOTE>
<P><B>Effects:</B> Destroys this <b>weak_ptr</b> but has no effect on the object <P><B>Effects:</B> Destroys this <b>weak_ptr</b> but has no effect on the object
its stored pointer points to.</P> its stored pointer points to.</P>
<P><B>Throws:</B> nothing.</P> <P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE> </BLOCKQUOTE>
<h3><a name="assignment">assignment</a></h3> <h3><a name="assignment">assignment</a></h3>
<pre>weak_ptr &amp; operator=(weak_ptr const &amp; r); <pre>weak_ptr &amp; operator=(weak_ptr const &amp; r);
template&lt;class Y&gt; weak_ptr &amp; operator=(weak_ptr&lt;Y&gt; const &amp; r); template&lt;class Y&gt; weak_ptr &amp; operator=(weak_ptr&lt;Y&gt; const &amp; r);
template&lt;class Y&gt; weak_ptr &amp; operator=(shared_ptr&lt;Y&gt; const &amp; r);</pre> template&lt;class Y&gt; weak_ptr &amp; operator=(shared_ptr&lt;Y&gt; const &amp; r);</pre>
<BLOCKQUOTE> <BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>weak_ptr(r).swap(*this)</code>.</P> <P><B>Effects:</B> Equivalent to <code>weak_ptr(r).swap(*this)</code>.</P>
<P><B>Throws:</B> nothing.</P> <P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> The implementation is free to meet the effects (and the implied <P><B>Notes:</B> The implementation is free to meet the effects (and the implied
guarantees) via different means, without creating a temporary.</P> guarantees) via different means, without creating a temporary.</P>
</BLOCKQUOTE> </BLOCKQUOTE>
<h3><a name="use_count">use_count</a></h3> <h3><a name="use_count">use_count</a></h3>
<pre>long use_count() const;</pre> <pre>long use_count() const;</pre>
<blockquote> <blockquote>
<p><b>Returns:</b> 0 if <STRONG>*this</STRONG> is <EM>empty</EM>; otherwise, the <p><b>Returns:</b> 0 if <STRONG>*this</STRONG> is <EM>empty</EM>; otherwise, the
number of <b>shared_ptr</b> objects that <EM>share ownership</EM> with <STRONG>*this</STRONG>.</p> number of <b>shared_ptr</b> objects that <EM>share ownership</EM> with <STRONG>*this</STRONG>.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <code>use_count()</code> is not necessarily efficient. Use only <P><B>Notes:</B> <code>use_count()</code> is not necessarily efficient. Use only
for debugging and testing purposes, not for production code.</P> for debugging and testing purposes, not for production code.</P>
</blockquote> </blockquote>
<h3><a name="expired">expired</a></h3> <h3><a name="expired">expired</a></h3>
<pre>bool expired() const;</pre> <pre>bool expired() const;</pre>
<blockquote> <blockquote>
<p><b>Returns:</b> <code>use_count() == 0</code>.</p> <p><b>Returns:</b> <code>use_count() == 0</code>.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <code>expired()</code> may be faster than <code>use_count()</code>.</P> <P><B>Notes:</B> <code>expired()</code> may be faster than <code>use_count()</code>.</P>
</blockquote> </blockquote>
<h3><a name="lock">lock</a></h3> <h3><a name="lock">lock</a></h3>
<pre>shared_ptr&lt;T&gt; lock() const;</pre> <pre>shared_ptr&lt;T&gt; lock() const;</pre>
<BLOCKQUOTE> <BLOCKQUOTE>
<P><B>Returns:</B> <code>expired()? shared_ptr&lt;T&gt;(): shared_ptr&lt;T&gt;(*this)</code>.</P> <P><B>Returns:</B> <code>expired()? shared_ptr&lt;T&gt;(): shared_ptr&lt;T&gt;(*this)</code>.</P>
<P><B>Throws:</B> nothing.</P> <P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE> </BLOCKQUOTE>
<h3><a name="reset">reset</a></h3> <h3><a name="reset">reset</a></h3>
<pre>void reset();</pre> <pre>void reset();</pre>
<BLOCKQUOTE> <BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>weak_ptr().swap(*this)</code>.</P> <P><B>Effects:</B> Equivalent to <code>weak_ptr().swap(*this)</code>.</P>
</BLOCKQUOTE> </BLOCKQUOTE>
<h3><a name="swap">swap</a></h3> <h3><a name="swap">swap</a></h3>
<pre>void swap(weak_ptr &amp; b);</pre> <pre>void swap(weak_ptr &amp; b);</pre>
<blockquote> <blockquote>
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p> <p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
</blockquote> </blockquote>
<h2><a name="functions">Free Functions</a></h2> <h2><a name="functions">Free Functions</a></h2>
<h3><a name="comparison">comparison</a></h3> <h3><a name="comparison">comparison</a></h3>
<pre>template&lt;class T, class U&gt; <pre>template&lt;class T, class U&gt;
bool operator&lt;(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b);</pre> bool operator&lt;(weak_ptr&lt;T&gt; const &amp; a, weak_ptr&lt;U&gt; const &amp; b);</pre>
<blockquote> <blockquote>
<p><b>Returns:</b> an unspecified value such that</p> <p><b>Returns:</b> an unspecified value such that</p>
<UL> <UL>
<LI> <LI>
<b>operator&lt;</b> is a strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code> <b>operator&lt;</b> is a strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
of the C++ standard; of the C++ standard;
<LI> <LI>
under the equivalence relation defined by <STRONG>operator&lt;</STRONG>, <code>!(a under the equivalence relation defined by <STRONG>operator&lt;</STRONG>, <code>!(a
&lt; b) &amp;&amp; !(b &lt; a)</code>, two <STRONG>weak_ptr</STRONG> instances &lt; b) &amp;&amp; !(b &lt; a)</code>, two <STRONG>weak_ptr</STRONG> instances
are equivalent if and only if they <EM>share ownership</EM> or are both <EM>empty</EM>.</LI></UL> are equivalent if and only if they <EM>share ownership</EM> or are both <EM>empty</EM>.</LI></UL>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> Allows <STRONG>weak_ptr</STRONG> objects to be used as keys in <P><B>Notes:</B> Allows <STRONG>weak_ptr</STRONG> objects to be used as keys in
associative containers.</P> associative containers.</P>
</blockquote> </blockquote>
<h3><a name="free-swap">swap</a></h3> <h3><a name="free-swap">swap</a></h3>
<pre>template&lt;class T&gt; <pre>template&lt;class T&gt;
void swap(weak_ptr&lt;T&gt; &amp; a, weak_ptr&lt;T&gt; &amp; b)</pre> void swap(weak_ptr&lt;T&gt; &amp; a, weak_ptr&lt;T&gt; &amp; b)</pre>
<BLOCKQUOTE> <BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P> <P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
<P><B>Throws:</B> nothing.</P> <P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to <P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
generic programming.</P> generic programming.</P>
</BLOCKQUOTE> </BLOCKQUOTE>
<h2><a name="FAQ">Frequently Asked Questions</a></h2> <h2><a name="FAQ">Frequently Asked Questions</a></h2>
<P><B>Q.</B> Can an object create a <STRONG>weak_ptr</STRONG> to itself in its <P><B>Q.</B> Can an object create a <STRONG>weak_ptr</STRONG> to itself in its
constructor?</P> constructor?</P>
<P><b>A.</b> No. A <STRONG>weak_ptr</STRONG> can only be created from a <STRONG>shared_ptr</STRONG>, <P><b>A.</b> No. A <STRONG>weak_ptr</STRONG> can only be created from a <STRONG>shared_ptr</STRONG>,
and at object construction time no <STRONG>shared_ptr</STRONG> to the object and at object construction time no <STRONG>shared_ptr</STRONG> to the object
exists yet. Even if you could create a temporary <STRONG>shared_ptr</STRONG> to <STRONG> exists yet. Even if you could create a temporary <STRONG>shared_ptr</STRONG> to <STRONG>
this</STRONG>, it would go out of scope at the end of the constructor, and this</STRONG>, it would go out of scope at the end of the constructor, and
all <STRONG>weak_ptr</STRONG> instances would instantly expire.</P> all <STRONG>weak_ptr</STRONG> instances would instantly expire.</P>
<P>The solution is to make the constructor private, and supply a factory function <P>The solution is to make the constructor private, and supply a factory function
that returns a <STRONG>shared_ptr</STRONG>:<BR> that returns a <STRONG>shared_ptr</STRONG>:<BR>
</P> </P>
<pre> <pre>
class X class X
{ {
private: private:
@@ -230,13 +230,11 @@ public:
} }
}; };
</pre> </pre>
<p><br> <hr>
</p> <p>$Date$</p>
<hr> <p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
<p>$Date$</p> Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or </body>
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html> </html>