<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>

<meta http-equiv="Content-Type" content="text/html;charset=US-ASCII">

<style type="text/css">

body { color: #000000; background-color: #FFFFFF; }
del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
  border: 1px solid #E1E28E; }

p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

blockquote.std { color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5empadding-right: 0.5em; ; }

blockquote.stdins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3; padding: 0.5em; }

table { border: 1px solid black; border-spacing: 0px;
  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }
td { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }

</style>

<title>C++ Dynamic Arrays</title>
</head>
<body>
<h1>C++ Dynamic Arrays</h1>

<p>
ISO/IEC JTC1 SC22 WG21 N3532 - 2013-03-12
</p>

<address>
Lawrence Crowl, crowl@google.com, Lawrence@Crowl.org
<br>
Matt Austern, austern@google.com
</address>

<p>
<a href="#Problem">Problem</a><br>
<a href="#Solution">Solution</a><br>
<a href="#Builtin">Builtin Arrays of Runtime Bound</a><br>
<a href="#Presentation">Presentation</a><br>
<a href="#Proposal">Proposal</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#containers">Chapter 23 Containers library [containers]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#sequence.reqmts">23.2.3 Sequence containers [sequence.reqmts]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#sequences">23.3 Sequence containers [sequences]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#dynarray">23.3.8 Class template <code>dynarray</code> [dynarray]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#dynarray">23.3.8.1 Class template <code>dynarray</code> overview [dynarray.overview]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#dynarray.cons">23.2.8.2 <code>dynarray</code> constructor and destructor [dynarray.cons]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#dynarray.size">23.2.8.3 <code>dynarray::size</code> [dynarray.size]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#dynarray.data">23.2.8.4 <code>dynarray::data</code> [dynarray.data]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#dynarray.zero">23.2.8.5 Zero sized dynarrays [dynarray.zero]</a><br>
<a href="#Example">Example</a><br>
<a href="#Revision">Revision History</a><br>
</p>


<h2><a name="Problem">Problem</a></h2>


<p>
Programs can become more efficient
when they can bind aspects of their execution
earlier in program development.
As an example,
the <code>std::unordered_map</code> container
provides more functionality than <code>std::vector</code>,
but <code>std::vector</code>
provides better performance
when the programmer can bind indexes
to a dense, but extensible, range near zero.
Going further, built-in arrays
provide even better performance
by binding the range end at compilation time.
</p>

<p>
Unfortunately, for some applications,
the range end is known at container construction
but not at compilation time.
So, built-in arrays are not applicable.
On the other hand,
<code>std::vector</code> is more general than needed,
as it permits an extensibility that is not required.
Ideally, we would like to be able to specify a container
where the index end is bound at construction,
but does not change thereafter.
</p>

<p>
The C programming language has such a container
in the form of <dfn>variable-length arrays</dfn>.
They are not general in that
they are limited to automatic variables,
but given that restriction
they are nearly as efficient as normal arrays,
requiring only mark/release stack allocation
and maintenance of a frame pointer.
(Maintaining a frame pointer is a good idea anyway.)
Unfortunately the detailed type semantics of C variable-length arrays
are probably not acceptable to C++,
so we cannot simply adopt them.
</p>

<p>
The <code>std::valarray</code> container is intermediate
between built-in arrays and <code>std::vector</code>,
but as it supports a <code>resize</code> method,
it cannot hold its size fixed for the lifetime of the variable.
Furthermore, <code>std::valarray</code>
supports compound member assignment operators
that imply such operators in the parameter type.
Such implications are workable only for types with "full interfaces",
not for general types.
</p>


<h2><a name="Solution">Solution</a></h2>

<p>
Instead of adopting C variable-length arrays,
we propose to define a new facility for arrays
where the number of elements is bound at construction.
We call these dynamic arrays, <code>dynarray</code>.
In keeping with C++ practice,
we wish to make <code>dynarray</code>s
usable with more than just automatic variables.
But to take advantage of the efficiency stack allocation,
we wish to make <code>dynarray</code> optimizable
when used as an automatic variable.
</p>

<p>
Therefore, we propose to define <code>dynarray</code>
so that compilers can recognize and implement
construction and destruction directly,
without appeal to any particular standard library implementation.
However, to minimize the necessary burden on compilers,
we propose that <code>dynarray</code> can be implemented as a pure library,
although with lost optimization opportunity.
</p>

<p>
We believe that the compilers can introduce the optimization
without impact on source or binary compatiblity.
There may be some change in code profiles and operator new calls
as a result of that optimization,
but such risks are common to compiler and library upgrades.
</p>

<p>
Syntactically, our proposal follows the lead of
<code>std::array</code> and <code>std::vector</code> containers.
Semantically, our proposal follows the lead of built-in arrays.
That is,
we do not require more out of <code>std::dynarray</code> element types
than we do of standard array element types.
</p>

<p>
The <code>dynarray</code> constructor has a parameter
indicating the number of elements in the container.
<code>Dynarray</code> requires an element type with a default constructor,
just as the built-in array requires.
Note that <code>dynarray</code> does not provide a default constructor,
because there is no reasonable default size,
and hence the <code>dynarray</code>
may not take a <code>dynarray</code> as an element.
</p>

<p>
<code>Dynarray</code> provides a copy constructor,
but use of the copy constructor requires that the element type
also have a copy constructor.
The presence of this constructor implies that
users cannot explicitly instantiate the <code>dynarray</code> template class
on a type that does not have a copy constructor.
This practice already exists in the standard library.
</p>

<p>
<code>Dynarray</code> provides random access iterators,
likely implemented as pointers.
The elements must be contiguously allocated,
to enable access via pointer arithmetic.
</p>

<p>
<code>Dynarray</code> also provides reverse iterators,
but these definitions imply that
the compiler implementation depends on the standard library implementation,
which is the reverse of the normal dependence.
</p>

<p>
<code>Dynarray</code> does not provide
any mechanism for determining whether heap or stack allocation was used.
</p>

<p>
<code>Dynarray</code> does not provide
a constructor from an <code>initializer_list</code>.
An initializer list necessarily has a static number of elements,
and an array or an <code>std::array</code> is likely more appropriate.
However, there is no technical reason against such a constructor.
</p>

<p>
<code>Dynarray</code> does not provide
a constructor from first and last forward iterators.
Such a constructor is possible, though,
as one can determine the size with <code>std::distance(first,last)</code>.
The technical consideration is that
determining the distance is only constant time for random access iterators.
</p>


<h2><a name="Builtin">Builtin Arrays of Runtime Bound</a></h2>

<p>
In <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3467.html">
N3497 Runtime-sized arrays with automatic storage duration</a>,
Jens Maurer proposes arrays with runtime bound.
These arrays are to <code>std::dynarray</code>
as normal fixed-size arrays are to <code>std::array</code>.
</p>

<p>
There are several similarities and differences.
</p>

<ul>

<li><p>
Both proposals permit allocation on the stack or on the heap,
at the discression of the implementation.
</p></li>

<li><p>
Arrays of runtime bound
can be used only for variables of automatic storage duration.
In contrast, <code>dynarray</code> can be used anywhere.
However, when <code>dynarray</code> is not used in a automatic variable,
use of the heap is necessarily required.
</p></li>

<li><p>
The types of arrays of runtime bound
are not inspectable (e.g. with <code>decltype</code>).
In contrast, <code>dynarray</code> has a normal template class type,
but the bound is not part of that type.
</p></li>

<li>
<p>
Arrays of runtime bound
throw <code>std::bad_array_length</code>
when the array size is unacceptable.
As currently defined,
<code>dynarray</code> also throws throw <code>std::bad_array_length</code>,
under the assumption that
migration between the two is easier if they throw the same exception.
The other choice would be to throw <code>std::length_error</code>
as does <code>std::vector::reserve()</code>.
Note, however, that the <code>std::vector::vector(size_type n)</code>
does not specify an exception.
The <code>operator new[]</code>
throws <code>std::bad_array_new_length</code>.
</p>

<p>
Because it may allocate memory,
<code>dynarray</code> may also throw <code>std::bad_alloc</code>.
</p>
</li>

<li><p>
Arrays of runtime bounds do no allow zero size;
<code>dynarray</code> does.
</p></li>

<li><p>
One can use initializer lists with arrays of runtime bound.
They are not currently supported with <code>dynarray</code>.
If <code>dynarray</code> were to support initializer lists,
it would derive its size from the initializer list.
This approach prevents a specification inconsistency
that is possible in arrays of runtime bound.
</p></li>

</ul>


<h2><a name="Presentation">Presentation</a></h2>

<p>
Within the proposal,
regular code font indicates normative code
and variable code font indicates an example implementation.
The example implementation is a pure library implementation,
and does not include the stack allocation optimization.
Thus, the example implementation is a minimal conforming implementation.
</p>

<p>
Within the example,
regular code font indicates example code.
There is no use of variable code font.
</p>

<p>
Within both the proposal and the example,
sample font is part of the commentary
and not part of either the proposal or the example.
This font is usually visually indistinguishable from code font,
but should be clear from context.
</p>

<p>
The code for the definition, implementation and subsequent example
can be extracted from the HTML source
with the following <code>sed</code> script.
</p>

<pre><code>
	1,/&lt;code class="extract"&gt;/		d
	/&lt;\/code&gt;/,/&lt;code class="extract"&gt;/	d
	s|&lt;var&gt;||g
	s|&lt;/var&gt;||g
	s|&amp;lt;|&lt;|g
	s|&amp;gt;|&gt;|g
	s|&amp;amp;|\&amp;|g
</code></pre>

<p>
First,
to enable a fully compilable implementation and example,
we include appropriate library headers
and exceptions introduced elsewhere.
</p>

<pre class="extract"><code class="extract"><var>
#include &lt;stddef.h&gt;
#include &lt;cstring&gt;
#include &lt;limits&gt;
#include &lt;algorithm&gt;
#include &lt;stdexcept&gt;
#include &lt;iostream&gt;
#include &lt;memory&gt;
namespace std { struct bad_array_length { }; }
</var></code></pre>


<h2><a name="Proposal">Proposal</a></h2>

<p>
The <code>dynarray</code> container definition is as follows.
The section, paragraph, and table references
are based on those of
<cite>
<a href="../2012/n3485.pdf">
N3485</a> Working Draft, Standard for Programming Language C++</cite>,
Stefanus Du Toit, November 2012.
</p>


<h3><a name="containers">Chapter 23 Containers library [containers]</a></h3>

<p>
Add <code>&lt;dynarray&gt;</code> to table 87:
</p>

<blockquote class="std">
<table>
<caption>Table 87: Containers library summary</caption>
<tbody>
<tr><th>Subclause</th><th>Header(s)</th></tr>
<tr><td valign=top>23.2 Requirements</td>
<td></td></tr>
<tr><td valign=top>23.3 Sequence containers</td>
<td><code>&lt;array&gt;<br>
&lt;deque&gt;<br>
<ins>&lt;dynarray&gt;</ins><br>
&lt;forward_list&gt;<br>
&lt;list&gt;<br>
&lt;vector&gt;</code></td></tr>
<tr><td valign=top>23.4 Associative containers</td>
<td><code>&lt;map&gt;<br>
&lt;set&gt;</code></td></tr>
<tr><td valign=top>23.5 Unordered associative containers</td>
<td><code>&lt;unordered_map&gt;<br>
&lt;unordered_set&gt;</code></td></tr>
<tr><td valign=top>23.6 Container adaptors</td>
<td>&lt;queue&gt;<br>
&lt;stack&gt;</td></tr>
</tbody>
</table>
</blockquote>


<h3><a name="sequence.reqmts">23.2.3 Sequence containers [sequence.reqmts]</a></h3>

<p>
In table 101, Optional sequence container operations,
add <code>dynarray</code> to the list of containers
for operations
<code>front</code>,
<code>back</code>,
<code>a[n]</code>, and
<code>at(n)</code>.
</p>


<h3><a name="sequences">23.3 Sequence containers [sequences]</a></h3>

<p>
Add a new synopsis:
</p>

<blockquote class="stdins">
<p>
<b>Header <code>&lt;dynarray&gt;</code> synopsis</b>
</p>

<pre class="extract"><code class="extract">
namespace std {
template&lt; class T &gt;
struct dynarray;
} // namespace std
</code></pre>
</blockquote>


<h3><a name="dynarray">23.3.8 Class template <code>dynarray</code> [dynarray]</a></h3>

<p>
Add a new section.
</p>


<h3><a name="dynarray">23.3.8.1 Class template <code>dynarray</code> overview [dynarray.overview]</a></h3>

<p>
Add a new section:
</p>

<blockquote class="stdins">

<p>
The header <code>&lt;dynarray&gt;</code>
defines a class template for storing sequences of objects
where the size is fixed at construction.
A <code>dynarray</code> supports random access iterators.
An instance of <code>dynarray&lt;T&gt;</code>
stores elements of type <code>T</code>.
The elements of a <code>dynarray</code> are stored contiguously,
meaning that if <code>d</code> is an <code>dynarray&lt;T&gt;</code>
then it obeys the identity
<code>&amp;a[n] == &amp;a[0] + n</code> for all <code>0 &lt;= n &lt; N</code>.
</p>

<p>
Unless otherwise specified,
all array operations are as described in 23.2.
Descriptions are provided here
only for operations on <code>dynarray</code>
that are not described in that clause
or for operations where there is additional semantic information.
</p>

<p>
All operations except construction and destruction
shall have constant-time complexity.
</p>

<pre class="extract"><code class="extract">
namespace std {
template&lt; class T &gt;
struct dynarray
{
    // types:
    typedef       T                               value_type;
    typedef       T&amp;                              reference;
    typedef const T&amp;                              const_reference;
    typedef       <var>T*</var>                              iterator;
    typedef <var>const T*</var>                              const_iterator;
    typedef std::reverse_iterator&lt;iterator&gt;       reverse_iterator;
    typedef std::reverse_iterator&lt;const_iterator&gt; const_reverse_iterator;
    typedef <var>size_t</var>                                size_type;
    typedef <var>ptrdiff_t</var>                             difference_type;

    // fields:
<var>private:</var>
    <var>T*        store;</var>
    <var>size_type count;</var>

    // helper functions:
    <var>void check(size_type n)
        { if ( n &gt;= count ) throw out_of_range("dynarray"); }</var>
    <var>T* alloc(size_type n)
        { if ( n > std::numeric_limits&lt;size_type&gt;::max()/sizeof(T) )
              throw std::bad_array_length();
          return reinterpret_cast&lt;T*&gt;( new char[ n*sizeof(T) ] ); }</var>

public:
    // construct and destruct:
    dynarray() = delete;
    const dynarray operator=(const dynarray&amp;) = delete;

    explicit dynarray(size_type <var>c</var>)
        <var>: store( alloc( c ) ), count( c )
        { size_type i;
          try {
              for ( size_type i = 0; i &lt; count; ++i )
                  new (store+i) T;
          } catch ( ... ) {
              for ( ; i > 0; --i )
                 (store+(i-1))->~T();
              throw;
          } }</var>

    dynarray(const dynarray&amp; <var>d</var>)
        <var>: store( alloc( d.count ) ), count( d.count )
        { try { uninitialized_copy( d.begin(), d.end(), begin() ); }
          catch ( ... ) { delete store; throw; } }</var>

    ~dynarray()
        <var>{ for ( size_type i = 0; i &lt; count; ++i )
              (store+i)->~T();
          delete[] store; }</var>

    // iterators:
    iterator       begin()        <var>{ return store; }</var>
    const_iterator begin()  const <var>{ return store; }</var>
    const_iterator cbegin() const <var>{ return store; }</var>
    iterator       end()          <var>{ return store + count; }</var>
    const_iterator end()    const <var>{ return store + count; }</var>
    const_iterator cend()   const <var>{ return store + count; }</var>

    reverse_iterator       rbegin()       
        <var>{ return reverse_iterator(end()); }</var>
    const_reverse_iterator rbegin()  const
        <var>{ return reverse_iterator(end()); }</var>
    reverse_iterator       rend()         
        <var>{ return reverse_iterator(begin()); }</var>
    const_reverse_iterator rend()    const
        <var>{ return reverse_iterator(begin()); }</var>

    // capacity:
    size_type size()     const <var>{ return count; }</var>
    size_type max_size() const <var>{ return count; }</var>
    bool      empty()    const <var>{ return count == 0; }</var>

    // element access:
    reference       operator[](size_type <var>n</var>)       <var>{ return store[n]; }</var>
    const_reference operator[](size_type <var>n</var>) const <var>{ return store[n]; }</var>

    reference       front()       <var>{ return store[0]; }</var>
    const_reference front() const <var>{ return store[0]; }</var>
    reference       back()        <var>{ return store[count-1]; }</var>
    const_reference back()  const <var>{ return store[count-1]; }</var>

    const_reference at(size_type <var>n</var>) const <var>{ check(n); return store[n]; }</var>
    reference       at(size_type <var>n</var>)       <var>{ check(n); return store[n]; }</var>

    // data access:
    T*       data()       <var>{ return store; }</var>
    const T* data() const <var>{ return store; }</var>
};

} // namespace std
</code></pre>

</blockquote>


<h3><a name="dynarray.cons">23.2.8.2 <code>dynarray</code> constructor and destructor [dynarray.cons]</a></h3>

<p>
Add a new section:
</p>

<blockquote class="stdins">

<p>
<code>dynarray(size_type <var>c</var>);</code>
</p>

<blockquote>
<p>
<i>Effects:</i>
May or may not invoke the global <code>operator new</code>.
</p>

<p>
<i>Throws:</i>
<code>std::bad_array_length</code>
when the size requested is larger than implementable.
<code>std::bad_alloc</code>
when there is insufficient memory.
</p>
</blockquote>

<p>
<code>dynarray(const dynarray&amp; <var>d</var>);</code>
</p>

<blockquote>
<p>
<i>Requires:</i>
T is Copy Constructible.
</p>

<p>
<i>Throws:</i>
<code>std::bad_alloc</code>
when there is insufficient memory.
</p>
</blockquote>

<blockquote>
<p>
<i>Effects:</i>
May or may not invoke the global <code>operator new</code>.
</p>
</blockquote>

<p>
<code>~dynarray();</code>
</p>

<blockquote>
<p>
<i>Effects:</i>
Invokes the global <code>operator delete</code>
if and only if
the constructor invoked the global <code>operator new</code>.
</p>
</blockquote>

</blockquote>


<h3><a name="dynarray.size">23.2.8.3 <code>dynarray::size</code> [dynarray.size]</a></h3>

<p>
Add a new section:
</p>

<blockquote class="stdins">

<p>
<code>size_type size() const;</code>
</p>

<blockquote>
<p>
<i>Returns:</i>
Returns the argument to the constructor of the object.
</p>
</blockquote>

<p>
<code>size_type max_size() const;</code>
</p>

<blockquote>
<p>
<i>Returns:</i>
Returns the argument to the constructor of the object.
</p>
</blockquote>

<p>
<code>bool empty() const;</code>
</p>

<blockquote>
<p>
<i>Returns:</i>
<code>size() == 0</code>.
</p>
</blockquote>

</blockquote>


<h3><a name="dynarray.data">23.2.8.4 <code>dynarray::data</code> [dynarray.data]</a></h3>

<p>
Add a new section:
</p>

<blockquote class="stdins">

<p>
<code>T* data();</code><br>
<code>T* data() const;</code>
</p>

<blockquote>
<p>
<i>Returns:</i>
A pointer to the contiguous storage containing the elements.
</p>
</blockquote>

</blockquote>


<h3><a name="dynarray.zero">23.2.8.5 Zero sized dynarrays [dynarray.zero]</a></h3>

<p>
Add a new section:
</p>

<blockquote class="stdins">

<p>
<code>dynarray</code> shall provide support
for the special case of construction with a size of zero.
In the case that the size is zero,
<code>begin() == end() ==</code> unique value.
The return value of <code>data()</code> is unspecified.
The effect of calling <code>front()</code> or <code>back()</code>
for a zero-sized <code>dynarray</code> is undefined.
</p>

</blockquote>


<h2><a name="Example">Example</a></h2>

<p>
Finally, we show a simple set of uses of the container.
</p>

<p>
Declaring a reference parameter.
Using a const iterator.
</p>

<pre class="extract"><code class="extract">
void dump( const std::dynarray&lt; int &gt; &amp; source )
{
    std::dynarray&lt; int &gt;::const_iterator src = source.begin();
    for ( ; src != source.end(); src++ )
        std::cout &lt;&lt; " " &lt;&lt; *src;
    std::cout &lt;&lt; std::endl;
}
</code></pre>

<p>
Declaring a local <code>dynarray</code> of computed size. 
Using 
<code>front</code>,
<code>back</code>,
and a non-const iterator.
</p>

<pre class="extract"><code class="extract">
void lowrap(       std::dynarray&lt; int &gt; &amp; target,
             const std::dynarray&lt; int &gt; &amp; source )
{
    dump( source );

    std::dynarray&lt; int &gt; sorted( source );
    dump( sorted );

    std::sort( sorted.begin(), sorted.end() );
    dump( sorted );

    const int* srt = &amp;sorted.front();
    std::dynarray&lt; int &gt;::iterator tgt( target.begin() );
    for ( ; tgt != target.end(); tgt++ ) {
        *tgt = *srt;
        if ( srt == &amp;sorted.back() )
            srt = &amp;sorted.front();
        else
            srt++;
    }
    dump( target );
}
</code></pre>

<p>
Declaring a local <code>dynarray</code> of fixed size.
Using
<code>size</code>,
<code>operator[]</code>,
<code>at</code>,
index iteration,
and pointer iteration.
</p>

<pre class="extract"><code class="extract">
int main() {
    std::dynarray&lt; int &gt; alpha(8);
    std::dynarray&lt; int &gt; gamma(3);
    for ( std::dynarray&lt; int &gt;::size_type i = 0; i &lt; gamma.size(); i++ )
	gamma[i] = 4 - i;
    lowrap( alpha, gamma );
    int sum = 0;
    for ( std::dynarray&lt; int &gt;::size_type i = 0; i &lt; alpha.size(); i++ )
	sum += alpha.at(i);
    
    return sum;
}
</code></pre>


<h2><a name="Revision">Revision History</a></h2>

<p>
This paper revises N2648 = 08-0158 - 2008-05-16 as follows.
</p>

<ul>

<li><p>
Add a section discussing of the relationship to
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3497.html">
N3497 Runtime-sized arrays with automatic storage duration</a>.
</p></li>

<li><p>
Support zero-length <code>dynarray</code>s.
Add corresponding specifications
for <code>max_size</code> and <code>empty</code>.
Update implementation.
</p></li>

<li><p>
Throw <code>std::bad_array_length</code>
when the size parameter is too large.
Throw <code>std::bad_alloc</code>
when memory allocation fails.
</p></li>

<li><p>
Clarify that there is no support for determing
whether heap or stack allocation was used.
</p></li>

<li><p>
Note that a constructor from <code>initializer_list</code>
is not provided but technically feasible.
</p></li>

<li><p>
Note that a constructor from two forward iterators
is not provided but technically feasible.
</p></li>

<li><p>
Update the form of the HTML,
which affects the script for extracting the code.
</p></li>

<li><p>
Add a 'Revision History' section.
</p></li>

</ul>


</body>
</html>
