123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680 |
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <!--
- == Copyright 2002 The Trustees of Indiana University.
- == Use, modification and distribution is subject to 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)
- == Boost.MultiArray Library
- == Authors: Ronald Garcia
- == Jeremy Siek
- == Andrew Lumsdaine
- == See http://www.boost.org/libs/multi_array for documentation.
- -->
- <head>
- <title>The Boost Multidimensional Array Library (Boost.MultiArray)</title>
- </head>
- <body>
- <h1>
- <img src="../../../boost.png" alt="boost logo"
- width="277" align="middle" height="86">
- <br>The Boost Multidimensional Array Library
- <br>(Boost.MultiArray)
- </h1>
- <h2>Synopsis</h2>
- <p>
- The Boost Multidimensional Array Library provides a class template for
- multidimensional arrays, as well as semantically equivalent
- adaptors for arrays of contiguous data. The classes in this library
- implement a common interface, formalized as a generic programming
- concept. The interface design is in line with the precedent set by the
- C++ Standard Library containers. Boost MultiArray is a more efficient
- and convenient way to express N-dimensional arrays than existing
- alternatives (especially the
- <tt>std::vector<std::vector<...>></tt> formulation
- of N-dimensional arrays). The arrays provided by the library may be
- accessed using the familiar syntax of native C++ arrays. Additional
- features, such as resizing, reshaping, and creating views are
- available (and described below).
- <h2>Table of Contents</h2>
- <ol>
- <li><a href="#sec_introduction">Introduction</a>
- <li><a href="#sec_example">Short Example</a>
- <li><a href="#sec_components">MultiArray Components</a>
- <li><a href="#sec_assignment">Construction and Assignment</a>
- <li><a href="#sec_generators">Array View and Subarray Type Generators</a>
- <li><a href="#sec_dimensions">Specifying Array Dimensions</a>
- <li><a href="#sec_access">Accessing Elements</a>
- <li><a href="#sec_views">Creating Views</a>
- <li><a href="#sec_storage">Storage Ordering</a>
- <li><a href="#sec_base">Setting the Array Base</a>
- <li><a href="#sec_reshape">Changing an Array's Shape</a>
- <li><a href="#sec_resize">Resizing an Array</a>
- <li><a href="#sec_concepts">MultiArray Concept</a>
- <li><a href="#sec_testcases">Test Cases</a>
- <li><a href="#sec_related">Related Work</a>
- <li><a href="#sec_credits">Credits</a>
- </ol>
- <a name="sec_introduction"></a>
- <h2>Introduction</h2>
- <p>
- The C++ standard library provides several generic containers, but it
- does not provide any multidimensional array types. The
- <tt>std::vector</tt> class template can be used to implement
- N-dimensional arrays, for example expressing a 2-dimensional array of
- <tt>double</tt> elements using the type
- <tt>std::vector<std::vector<double>></tt>, but the
- resulting interface is unwieldy and the memory overhead can be quite
- high. Native C++ arrays (i.e. <tt>int arr[2][2][2];</tt>) do not
- immediately interoperate well with the C++ Standard Library, and they
- also lose information at function call boundaries (specifically the
- extent of the last dimension). Finally, a dynamically allocated
- contiguous block of elements can be treated as an array, though this
- method requires manual bookkeeping that is error prone and obfuscates
- the intent of the programmer.
- </p>
- <p>
- The Boost MultiArray library enhances the C++ standard containers with
- versatile multi-dimensional array abstractions. It includes a general
- array class template and native array adaptors that support idiomatic
- array operations and interoperate with C++ Standard Library containers
- and algorithms. The arrays share a common interface, expressed as a
- generic programming in terms of which generic array algorithms can be
- implemented.
- </p>
- <p>
- This document is meant to provide an introductory tutorial and user's
- guide for the most basic and common usage patterns of MultiArray
- components. The <a href="./reference.html">reference manual</a>
- provides more complete and formal documentation of library features.
- </p>
- <a name="sec_example"></a>
- <h2>Short Example</h2>
- What follows is a brief example of the use of <tt>multi_array</tt>:
- <blockquote>
- <pre>
- #include "boost/multi_array.hpp"
- #include <cassert>
- int
- main () {
- // Create a 3D array that is 3 x 4 x 2
- typedef boost::multi_array<double, 3> array_type;
- typedef array_type::index index;
- array_type A(boost::extents[3][4][2]);
- // Assign values to the elements
- int values = 0;
- for(index i = 0; i != 3; ++i)
- for(index j = 0; j != 4; ++j)
- for(index k = 0; k != 2; ++k)
- A[i][j][k] = values++;
- // Verify values
- int verify = 0;
- for(index i = 0; i != 3; ++i)
- for(index j = 0; j != 4; ++j)
- for(index k = 0; k != 2; ++k)
- assert(A[i][j][k] == verify++);
- return 0;
- }
- </pre>
- </blockquote>
- <a name="sec_components"></a>
- <h2>MultiArray Components</h2>
- Boost.MultiArray's implementation (boost/multi_array.hpp) provides three user-level class templates:
- <ol>
- <li><a href="./reference.html#multi_array"><tt>multi_array</tt></a>,
- <li><a href="./reference.html#multi_array_ref"><tt>multi_array_ref</tt></a>, and
- <li><a href="./reference.html#const_multi_array_ref"><tt>const_multi_array_ref</tt></a>
- </ol>
- <tt>multi_array</tt> is a container template. When instantiated, it
- allocates space for the number of elements corresponding to the
- dimensions specified at construction time. A <tt>multi_array</tt> may
- also be default constructed and resized as needed.
- <p>
- <tt>multi_array_ref</tt> adapts an existing array of data to provide
- the <tt>multi_array</tt> interface. <tt>multi_array_ref</tt> does not own the
- data passed to it.
- <p>
- <tt>const_multi_array_ref</tt> is similar to <tt>multi_array_ref</tt>
- but guarantees that the contents of the array are immutable. It can
- thus wrap pointers of type <i>T const*</i>.
- <p>
- The three components exhibit very similar behavior. Aside from
- constructor parameters, <tt>multi_array</tt> and
- <tt>multi_array_ref</tt> export the same interface.
- <tt>const_multi_array_ref</tt> provides only the constness-preserving
- portions of the <tt>multi_array_ref</tt> interface.
- <a name="sec_assignment"></a>
- <h2>Construction and Assignment</h2>
- <p>Each of the array types -
- <a href="./reference.html#multi_array"><tt>multi_array</tt></a>,
- <a href="./reference.html#multi_array_ref"><tt>multi_array_ref</tt></a>, and
- <a href="./reference.html#const_multi_array_ref"><tt>const_multi_array_ref</tt></a> -
- provides a specialized set of constructors. For further information,
- consult their reference pages.
- <p>All of the non-const array types in this library provide assignment
- operators<tt>operator=()</tt>. Each of the array types <tt>multi_array</tt>,
- <tt>multi_array_ref</tt>, <tt>subarray</tt>, and
- <tt>array_view</tt> can be assigned from any
- of the others, so long as their shapes match. The
- const variants, <tt>const_multi_array_ref</tt>,
- <tt>const_subarray</tt>, and <tt>const_array_view</tt>, can be the
- source of a copy to an array with matching shape.
- Assignment results in a deep (element by element) copy of the data
- contained within an array.
- <a name="sec_generators"></a>
- <h2>Array View and Subarray Type Generators</h2>
- In some situations, the use of nested generators for array_view and
- subarray types is inconvenient. For example, inside a
- function template parameterized upon array type, the extra
- "template" keywords can be obfuscating. More likely though, some
- compilers cannot handle templates nested within template parameters.
- For this reason the type generators, <tt>subarray_gen</tt>,
- <tt>const_subarray_gen</tt>, <tt>array_view_gen</tt>, and
- <tt>const_array_view_gen</tt> are provided. Thus, the two typedefs
- in the following example result in the same type:
- <blockquote>
- <pre>
- template <typename Array>
- void my_function() {
- typedef typename Array::template array_view<3>::type view1_t;
- typedef typename boost::array_view_gen<Array,3>::type view2_t;
- // ...
- }
- </pre>
- </blockquote>
- <a name="sec_dimensions"></a>
- <h2>Specifying Array Dimensions</h2>
- When creating most of the Boost.MultiArray components, it is necessary
- to specify both the number of dimensions and the extent of each
- (<tt>boost::multi_array</tt> also provides a default constructor).
- Though the number of dimensions is always specified as a template
- parameter, two separate mechanisms have been provided to specify the
- extent of each.
- <p>The first method involves passing a
- <a href="../../utility/Collection.html">
- Collection</a> of extents to a
- constructor, most commonly a <tt>boost::array</tt>. The constructor
- will retrieve the beginning iterator from the container and retrieve N
- elements, corresponding to extents for the N dimensions. This is
- useful for writing dimension-independent code.
- <h3>Example</h3>
- <blockquote>
- <pre>
- typedef boost::multi_array<double, 3> array_type;
- boost::array<array_type::index, 3> shape = {{ 3, 4, 2 }};
- array_type A(shape);
- </pre>
- </blockquote>
- <p>The second method involves passing the constructor an <tt>extent_gen</tt>
- object, specifying the matrix dimensions. The <tt>extent_gen</tt> type
- is defined in the <tt>multi_array_types</tt> namespace and as a
- member of every array type, but by default, the library constructs a
- global <tt>extent_gen</tt> object <tt>boost::extents</tt>. In case of
- concern about memory used by these objects, defining
- <tt>BOOST_MULTI_ARRAY_NO_GENERATORS</tt> before including the library
- header inhibits its construction.
- <h3>Example</h3>
- <blockquote>
- <pre>
- typedef boost::multi_array<double, 3> array_type;
- array_type A(boost::extents[3][4][2]);
- </pre>
- </blockquote>
- <a name="sec_access"></a>
- <h2>Accessing Elements</h2>
- The Boost.MultiArray components provide two ways of accessing
- specific elements within a container. The first uses the traditional
- C array notation, provided by <tt>operator[]</tt>.
- <h3>Example</h3>
- <blockquote>
- <pre>
- typedef boost::multi_array<double, 3> array_type;
- array_type A(boost::extents[3][4][2]);
- A[0][0][0] = 3.14;
- assert(A[0][0][0] == 3.14);
- </pre>
- </blockquote>
- <p> The second method involves passing a
- <a href="../../utility/Collection.html">
- Collection</a> of indices to <tt>operator()</tt>. N indices will be retrieved
- from the Collection for the N dimensions of the container.
- <h3>Example</h3>
- <blockquote>
- <pre>
- typedef boost::multi_array<double, 3> array_type;
- array_type A(boost::extents[3][4][2]);
- boost::array<array_type::index,3> idx = {{0,0,0}};
- A(idx) = 3.14;
- assert(A(idx) == 3.14);
- </pre>
- </blockquote>
- This can be useful for writing dimension-independent code, and under
- some compilers may yield higher performance than <tt>operator[].</tt>
- <p>
- By default, both of the above element access methods perform range
- checking. If a supplied index is out of the range defined for an
- array, an assertion will abort the program. To disable range
- checking (for performance reasons in production releases), define
- the <tt>BOOST_DISABLE_ASSERTS</tt> preprocessor macro prior to
- including multi_array.hpp in your application.
- <a name="sec_views"></a>
- <h2>Creating Views</h2>
- Boost.MultiArray provides the facilities for creating a sub-view of an
- already existing array component. It allows you to create a sub-view that
- retains the same number of dimensions as the original array or one
- that has less dimensions than the original as well.
- <p>Sub-view creation occurs by placing a call to operator[], passing
- it an <tt>index_gen</tt> type. The <tt>index_gen</tt> is populated by
- passing <tt>index_range</tt> objects to its <tt>operator[]</tt>.
- The <tt>index_range</tt> and <tt>index_gen</tt> types are defined in
- the <tt>multi_array_types</tt> namespace and as nested members of
- every array type. Similar to <tt>boost::extents</tt>, the library by
- default constructs the object <tt>boost::indices</tt>. You can
- suppress this object by
- defining <tt>BOOST_MULTI_ARRAY_NO_GENERATORS</tt> before including the
- library header. A simple sub-view creation example follows.
- <h3>Example</h3>
- <blockquote>
- <pre>
- // myarray = 2 x 3 x 4
- //
- // array_view dims: [base,bound) (dimension striding default = 1)
- // dim 0: [0,2)
- // dim 1: [1,3)
- // dim 2: [0,4) (strided by 2),
- //
- typedef boost::multi_array_types::index_range range;
- // OR typedef array_type::index_range range;
- array_type::array_view<3>::type myview =
- myarray[ boost::indices[range(0,2)][range(1,3)][range(0,4,2)] ];
- for (array_type::index i = 0; i != 2; ++i)
- for (array_type::index j = 0; j != 2; ++j)
- for (array_type::index k = 0; k != 2; ++k)
- assert(myview[i][j][k] == myarray[i][j+1][k*2]);
- </pre>
- </blockquote>
- <p>By passing an integral value to the index_gen, one may create a
- subview with fewer dimensions than the original array component (also
- called slicing).
- <h3>Example</h3>
- <blockquote>
- <pre>
- // myarray = 2 x 3 x 4
- //
- // array_view dims:
- // [base,stride,bound)
- // [0,1,2), 1, [0,2,4)
- //
- typedef boost::multi_array_types::index_range range;
- array_type::index_gen indices;
- array_type::array_view<2>::type myview =
- myarray[ indices[range(0,2)][1][range(0,4,2)] ];
- for (array_type::index i = 0; i != 2; ++i)
- for (array_type::index j = 0; j != 2; ++j)
- assert(myview[i][j] == myarray[i][1][j*2]);
- </pre>
- </blockquote>
- <h3>More on <tt>index_range</tt></h3>
- The <tt>index_range</tt> type provides several methods of specifying
- ranges for subview generation. Here are a few range instantiations
- that specify the same range.
- <h3>Example</h3>
- <blockquote>
- <pre>
- // [base,stride,bound)
- // [0,2,4)
- typedef boost::multi_array_types::index_range range;
- range a_range;
- a_range = range(0,4,2);
- a_range = range().start(0).finish(4).stride(2);
- a_range = range().start(0).stride(2).finish(4);
- a_range = 0 <= range().stride(2) < 4;
- a_range = 0 <= range().stride(2) <= 3;
- </pre>
- </blockquote>
- An <tt>index_range</tt> object passed to a slicing operation will
- inherit its start and/or finish value from the array being sliced if
- you do not supply one. This conveniently prevents you from having to
- know the bounds of the array dimension in certain cases. For example,
- the default-constructed range will take the full extent of the
- dimension it is used to specify.
- <h3>Example</h3>
- <blockquote>
- <pre>
- typedef boost::multi_array_types::index_range range;
- range a_range;
- // All elements in this dimension
- a_range = range();
- // indices i where 3 <= i
- a_range = range().start(3)
- a_range = 3 <= range();
- a_range = 2 < range();
- // indices i where i < 7
- a_range = range().finish(7)
- a_range = range() < 7;
- a_range = range() <= 6;
- </pre>
- </blockquote>
- The following example slicing operations exhibit some of the
- alternatives shown above
- <blockquote>
- <pre>
- // take all of dimension 1
- // take i < 5 for dimension 2
- // take 4 <= j <= 7 for dimension 3 with stride 2
- myarray[ boost::indices[range()][range() < 5 ][4 <= range().stride(2) <= 7] ];
- </pre>
- </blockquote>
- <a name="sec_storage"></a>
- <h2>Storage Ordering</h2>
- Each array class provides constructors that accept a storage ordering
- parameter. This is most
- useful when interfacing with legacy codes that require an ordering
- different from standard C, such as FORTRAN. The possibilities are
- <tt>c_storage_order</tt>, <tt>fortran_storage_order</tt>, and
- <tt>general_storage_order</tt>.
- <p><tt>c_storage_order</tt>, which is the default, will store elements
- in memory in the same order as a C array would, that is, the
- dimensions are stored from last to first.
- <p><tt>fortran_storage_order</tt> will store elements in memory in the same order
- as FORTRAN would: from the first dimension to
- the last. Note that with use of this parameter, the array
- indices will remain zero-based.
- <h3>Example</h3>
- <blockquote>
- <pre>
- typedef boost::multi_array<double,3> array_type;
- array_type A(boost::extents[3][4][2],boost::fortran_storage_order());
- call_fortran_function(A.data());
- </pre>
- </blockquote>
- <p><tt>general_storage_order</tt> allows one to customize both the order in
- which dimensions are stored in memory and whether dimensions are
- stored in ascending or descending order.
- <h3>Example</h3>
- <blockquote>
- <pre>
- typedef boost::general_storage_order<3> storage;
- typedef boost::multi_array<int,3> array_type;
-
- // Store last dimension, then first, then middle
- array_type::size_type ordering[] = {2,0,1};
- // Store the first dimension(dimension 0) in descending order
- bool ascending[] = {false,true,true};
- array_type A(extents[3][4][2],storage(ordering,ascending));
- </pre>
- </blockquote>
- <a name="sec_base"></a>
- <h2>Setting The Array Base</h2>
- In some situations, it may be inconvenient or awkward to use an
- array that is zero-based.
- the Boost.MultiArray components provide two facilities for changing the
- bases of an array. One may specify a pair of range values, with
- the <tt>extent_range</tt> type, to
- the <tt>extent_gen</tt> constructor in order to set the base value.
- <h3>Example</h3>
- <blockquote>
- <pre>
- typedef boost::multi_array<double, 3> array_type;
- typedef boost::multi_array_types::extent_range range;
- // OR typedef array_type::extent_range range;
- array_type::extent_gen extents;
-
- // dimension 0: 0-based
- // dimension 1: 1-based
- // dimension 2: -1 - based
- array_type A(extents[2][range(1,4)][range(-1,3)]);
- </pre>
- </blockquote>
- <p>
- An alternative is to first construct the array normally then
- reset the bases. To set all bases to the same value, use the
- <tt>reindex</tt> member function, passing it a single new index value.
- <h3>Example</h3>
- <blockquote>
- <pre>
- typedef boost::multi_array<double, 3> array_type;
- array_type::extent_gen extents;
-
- array_type A(extents[2][3][4]);
- // change to 1-based
- A.reindex(1)
- </pre>
- </blockquote>
- <p>
- An alternative is to set each base separately using the
- <tt>reindex</tt> member function, passing it a Collection of index bases.
- <h3>Example</h3>
- <blockquote>
- <pre>
- typedef boost::multi_array<double, 3> array_type;
- array_type::extent_gen extents;
-
- // dimension 0: 0-based
- // dimension 1: 1-based
- // dimension 2: (-1)-based
- array_type A(extents[2][3][4]);
- boost::array<array_type::index,ndims> bases = {{0, 1, -1}};
- A.reindex(bases);
- </pre>
- </blockquote>
- <a name="sec_reshape"></a>
- <h2>Changing an Array's Shape</h2>
- The Boost.MultiArray arrays provide a reshape operation. While the
- number of dimensions must remain the same, the shape of the array may
- change so long as the total number of
- elements contained remains the same.
- <h3>Example</h3>
- <blockquote>
- <pre>
- typedef boost::multi_array<double, 3> array_type;
- array_type::extent_gen extents;
- array_type A(extents[2][3][4]);
- boost::array<array_type::index,ndims> dims = {{4, 3, 2}};
- A.reshape(dims);
- </pre>
- </blockquote>
- <p>
- Note that reshaping an array does not affect the indexing.
- <a name="sec_resize"></a>
- <h2>Resizing an Array</h2>
- The <tt>boost::multi_array</tt> class provides an element-preserving
- resize operation. The number of dimensions must remain the same, but
- the extent of each dimension may be increased and decreased as
- desired. When an array is made strictly larger, the existing elements
- will be preserved by copying them into the new underlying memory and
- subsequently destructing the elements in the old underlying memory.
- Any new elements in the array are default constructed. However, if
- the new array size shrinks some of the dimensions, some elements will
- no longer be available.
- <h3>Example</h3>
- <blockquote>
- <pre>
- typedef boost::multi_array<int, 3> array_type;
- array_type::extent_gen extents;
- array_type A(extents[3][3][3]);
- A[0][0][0] = 4;
- A[2][2][2] = 5;
- A.resize(extents[2][3][4]);
- assert(A[0][0][0] == 4);
- // A[2][2][2] is no longer valid.
- </pre>
- </blockquote>
- <a name="sec_concepts"></a>
- <h2>MultiArray Concept</h2>
- Boost.MultiArray defines and uses the
- <a href="./reference.html#MultiArray">MultiArray</a>
- concept. It specifies an interface for N-dimensional containers.
- <a name="sec_testcases"></a>
- <h2>Test Cases</h2>
- Boost.MultiArray comes with a suite of test cases meant to exercise
- the features and semantics of the library. A description of the test
- cases can be found <a href="./test_cases.html">here</a>.
- <a name="sec_related"></a>
- <h2>Related Work</h2>
- <a href="../../array/index.html">boost::array</a>
- and <a href="https://www.boost.org/sgi/stl/Vector.html">std::vector</a> are
- one-dimensional containers of user data. Both manage their own
- memory. <tt>std::valarray</tt> is a low-level
- C++ Standard Library component
- meant to provide portable high performance for numerical applications.
- <a href="http://www.oonumerics.org/blitz/">Blitz++</a> is
- an array library developed by Todd
- Veldhuizen. It uses
- advanced C++ techniques to provide near-Fortran performance for
- array-based numerical applications.
- <b>array_traits</b> is a beta library, formerly distributed with
- Boost, that provides a means to create iterators over native C++
- arrays.
- This library is analogous to
- <a href="../../array/index.html">boost::array</a> in that it augments C style N-dimensional
- arrays, as <tt>boost::array</tt> does for C one-dimensional arrays.
- <a name="sec_credits"></a>
- <h2>Credits</h2>
- <ul>
-
- <li><a href="mailto:garcia@osl.iu.edu">Ronald Garcia</a>
- is the primary author of the library.
- <li><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>
- helped with the library and provided a sounding board for ideas,
- advice, and assistance porting to Microsoft Visual C++.
- <li><a href="mailto:gbavestrelli@yahoo.com">Giovanni Bavestrelli</a>
- provided an early implementation of an
- N-dimensional array which inspired feedback from the
- <a href="http://www.boost.org/">Boost</a> mailing list
- members. Some design decisions in this work were based upon this
- implementation and the comments it elicited.
- <li><a href="mailto:tveldhui@acm.org">Todd Veldhuizen</a> wrote
- <a href="http://oonumerics.org/blitz/">Blitz++</a>, which
- inspired some aspects of this design. In addition, he supplied
- feedback on the design and implementation of the library.
- <li><a href="mailto:jewillco@osl.iu.edu">Jeremiah Willcock</a>
- provided feedback on the implementation and design of the
- library and some suggestions for features.
- <li><a href="mailto:bdawes@acm.org">Beman Dawes</a>
- helped immensely with porting the library to Microsoft Windows
- compilers.
- <li><a href="mailto:glenjofe@gmail.com">Glen Fernandes</a>
- implemented support for the C++11 allocator model, including
- support for stateful allocators, minimal allocators, and
- optimized storage for stateless allocators.
- </ul>
- <hr>
- <address>
- <a href="mailto:garcia@.cs.indiana.edu">Ronald Garcia</a>
- </address>
- <!-- Created: Fri Jun 29 10:53:07 EST 2001 -->
- <!-- hhmts start -->Last modified: Tue Feb 7 17:15:50 EST 2006 <!-- hhmts end -->
- </body>
- </html>
|