Improve documentation for make_shared for arrays

This commit is contained in:
Glen Fernandes
2014-02-03 16:42:57 -08:00
parent 63a05a3576
commit 2b033ce05d
2 changed files with 272 additions and 160 deletions
+176 -88
View File
@@ -8,13 +8,13 @@
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
width="277" align="middle" border="0">make_shared and allocate_shared
for arrays</h1>
<p><a href="#Introduction">Introduction</a><br>
<a href="#Synopsis">Synopsis</a><br>
<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="#example">Examples</a><br>
<a href="#history">History</a><br>
<a href="#references">References</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<h2><a name="introduction">Introduction</a></h2>
<p>Originally the Boost function templates <code>make_shared</code> and
<code>allocate_shared</code> were for efficient allocation of shared
objects only. There was a need to have efficient allocation of
@@ -28,24 +28,24 @@
<code>make_shared</code> uses the global operator <code>new</code> to
allocate memory, whereas <code>allocate_shared</code> uses an
user-supplied allocator, allowing finer control.</p>
<h2><a name="Synopsis">Synopsis</a></h2>
<h2><a name="synopsis">Synopsis</a></h2>
<pre>namespace boost {
template&lt;typename U&gt; // U is T[]
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(size_t size);
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);
template&lt;typename U&gt; // U is T[N]
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>();
template&lt;typename U, typename A&gt; // U is T[N]
shared_ptr&lt;U&gt; <a href="#functions">allocate_shared</a>(const A&amp; allocator);
template&lt;typename U&gt; // U is T[]
shared_ptr&lt;U&gt; <a href="#functions">make_shared</a>(size_t size, const T&amp; value);
template&lt;typename U, typename A&gt; // U is 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, const T&amp; value);
template&lt;typename U&gt; // U is T[N]
@@ -66,95 +66,183 @@
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);
}</pre>
<h2><a name="functions">Free Functions</a></h2>
<pre>template&lt;typename U&gt; // U is T[]
shared_ptr&lt;U&gt; make_shared(size_t size);
template&lt;typename U, typename A&gt; // U is T[]
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, size_t size);
template&lt;typename U&gt; // U is T[N]
shared_ptr&lt;U&gt; make_shared();
template&lt;typename U, typename A&gt; // U is T[N]
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator);</pre>
<h2><a name="common">Common Requirements</a></h2>
<pre>template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared(<em>args</em>);
template&lt;typename U, typename A&gt;
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, <em>args</em>);
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>
<p><b>Requires:</b> The expression
<code>new(pointer) T()</code>, where <code>pointer</code> is a
<code>void*</code> pointing to storage suitable to hold an object of
type <code>T</code>, shall be well-formed. <code>A</code> shall be an
<em>Allocator</em>, 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>
<p><b>Effects:</b> Allocates memory suitable for an array of type
<code>T</code> and size <code>size</code> and constructs an array of
objects in it via the placement new expression <code>new(pointer)
T()</code>. <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>Requires:</b> <code>U</code> is of the form <code>T[]</code> or
<code>T[N]</code>. <code>A</code> shall be an <em>Allocator</em>, as
described in section 17.6.3.5 [<strong>Allocator
requirements</strong>] of the C++ Standard. The copy constructor and
destructor of <code>A</code> shall not throw exceptions.</p>
<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><em>args</em></code>
as specified by the concrete overload). The object is initialized as
specified by the concrete overload. The templates
<code>allocate_shared</code> and <code>allocate_shared_noinit</code>
use a copy of <code>allocator</code> to allocate memory. If an
exception is thrown, the functions have no effect.</p>
<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>
and size <code>size</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> or the constructor of <code>T</code>.</p>
<p><b>Notes:</b> This implementation allocates the memory required for
the returned <code>shared_ptr</code> and an array of type
<code>T</code> of size <code>size</code> in a single allocation. This
provides efficiency to equivalent to an intrusive smart pointer.</p>
</blockquote>
<pre>template&lt;typename U&gt; // U is T[]
shared_ptr&lt;U&gt; make_shared(size_t size, const T&amp; value);
template&lt;typename U, typename A&gt; // U is T[]
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, size_t size, const T&amp; value);
template&lt;typename U&gt; // U is T[N]
shared_ptr&lt;U&gt; make_shared(const T&amp; value);
template&lt;typename U, typename A&gt; // U is T[N]
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, const T&amp; value);</pre>
<blockquote>
<p><b>Notes:</b> These overloads initialize array objects with the given
owns the address of the newly constructed object.</p>
<p><b>Postconditions:</b> <code>r.get() != 0 &amp;&amp;
r.use_count() == 1</code>, where <code>r</code> is the return
value.</p>
<p><b>Throws:</b> <code>bad_alloc</code>, an exception thrown from
<code>A::allocate</code>, or from the initialization of the
object.</p>
</blockquote>
<pre>template&lt;typename U&gt; // U is T[]
shared_ptr&lt;U&gt; make_shared_noinit(size_t size);
template&lt;typename U, typename A&gt; // U is T[]
shared_ptr&lt;U&gt; allocate_shared_noinit(const A&amp; allocator, size_t size);
template&lt;typename U&gt; // U is T[N]
shared_ptr&lt;U&gt; make_shared_noinit();
template&lt;typename U, typename A&gt; // U is T[N]
shared_ptr&lt;U&gt; allocate_shared_noinit(const A&amp; allocator);</pre>
<blockquote>
<p><b>Notes:</b> These overloads do not perform value initialization of
array objects.</p>
</blockquote>
<h2><a name="example">Examples</a></h2>
<p>The following examples value-initialize objects.</p>
<blockquote>
<pre>boost::shared_ptr&lt;int[]&gt; a1 = boost::make_shared&lt;int[]&gt;(size);
boost::shared_ptr&lt;int[8]&gt; a2 = boost::make_shared&lt;int[8]&gt;();
boost::shared_ptr&lt;int[][2]&gt; a3 = boost::make_shared&lt;int[][2]&gt;(size);
boost::shared_ptr&lt;int[4][2]&gt; a4 = boost::make_shared&lt;int[4][2]&gt;();</pre>
<p><b>Remarks:</b></p>
<blockquote>
<p>This implementation performs no more than one memory
allocation. This provides efficiency to equivalent to an intrusive
smart pointer.</p>
<p>When an object of an array type <code>T</code> is specified to be
initialized to a value of the same type <code>value</code>, this
shall be interpreted to mean that each array element of the object
is initialized to the corresponding element from
<code>value</code>.</p>
<p>When an object of an array type is specified to be
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>, or to
<code>T(list...)</code>, where <code>list...</code> is a list of
constructor arguments, <code>make_shared</code> shall perform this
initialization via the expression <code>::new(ptr) T(value)</code>
or <code>::new(ptr) T(list...)</code> respectively, 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>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 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>
</blockquote>
<p>The following examples initialize objects with a given value.</p>
<h2><a name="functions">Free Functions</a></h2>
<pre>template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared(size_t size);
template&lt;typename U, typename A&gt;
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, size_t size);</pre>
<blockquote>
<pre>boost::shared_ptr&lt;int[]&gt; a5 = boost::make_shared&lt;int[]&gt;(size, 1);
boost::shared_ptr&lt;int[8]&gt; a6 = boost::make_shared&lt;int[8]&gt;(1);
boost::shared_ptr&lt;int[][2]&gt; a7 = boost::make_shared&lt;int[][2]&gt;(size, {1, 2});
boost::shared_ptr&lt;int[4][2]&gt; a8 = boost::make_shared&lt;int[4][2]&gt;({1, 2});</pre>
<p><b>Returns:</b> A <code>shared_ptr</code> to a value-initialized
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>
</blockquote>
<p>The following examples default-initialize objects.</p>
<blockquote>
<pre>boost::shared_ptr&lt;int[]&gt; a9 = boost::make_shared_noinit&lt;int[]&gt;(size);
boost::shared_ptr&lt;int[8]&gt; a10 = boost::make_shared_noinit&lt;int[8]&gt;();
boost::shared_ptr&lt;int[][2]&gt; a11 = boost::make_shared_noinit&lt;int[][2]&gt;(size);
boost::shared_ptr&lt;int[4][2]&gt; a12 = boost::make_shared_noinit&lt;int[4][2]&gt;();</pre>
<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>
<pre>template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared();
template&lt;typename U, typename A&gt;
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator);</pre>
<blockquote>
<p><b>Returns:</b> A <code>shared_ptr</code> to a value-initialized
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>
</blockquote>
<blockquote>
<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>
<pre>template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared(size_t size, const T&amp; value);
template&lt;typename U, typename A&gt;
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, size_t size, const T&amp; value);</pre>
<blockquote>
<p><b>Returns:</b> A <code>shared_ptr</code> to an object of type
<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>
</blockquote>
<blockquote>
<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>
<pre>template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared(const T&amp; value);
template&lt;typename U, typename A&gt;
shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, const T&amp; value);</pre>
<blockquote>
<p><b>Returns:</b> A <code>shared_ptr</code> to an object of type
<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>
</blockquote>
<blockquote>
<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>
<pre>template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared_noinit(size_t size);
template&lt;typename U, typename A&gt;
shared_ptr&lt;U&gt; allocate_shared_noinit(const A&amp; allocator, size_t size);</pre>
<blockquote>
<p><b>Returns:</b> A <code>shared_ptr</code> to a default-initialized
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>
</blockquote>
<blockquote>
<p><b>Examples:</b></p>
<blockquote>
<pre>boost::shared_ptr&lt;int[]&gt; a1 = boost::make_shared_noinit&lt;int[]&gt;(size);
boost::shared_ptr&lt;int[][2]&gt; a2 = boost::make_shared_noinit&lt;int[][2]&gt;(size);</pre>
</blockquote>
</blockquote>
<pre>template&lt;typename U&gt;
shared_ptr&lt;U&gt; make_shared_noinit();
template&lt;typename U, typename A&gt;
shared_ptr&lt;U&gt; allocate_shared_noinit(const A&amp; allocator);</pre>
<blockquote>
<p><b>Returns:</b> A <code>shared_ptr</code> to a default-initialized
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>
</blockquote>
<blockquote>
<p><b>Examples:</b></p>
<blockquote>
<pre>boost::shared_ptr&lt;int[8]&gt; a1 = boost::make_shared_noinit&lt;int[8]&gt;();
boost::shared_ptr&lt;int[4][2]&gt; a2 = boost::make_shared_noinit&lt;int[4][2]&gt;();</pre>
</blockquote>
</blockquote>
<h2><a name="history">History</a></h2>
<p>January 2014. Glen Fernandes reduced the overloads of make_shared and