The Array_<T> container class is a plug-compatible replacement for the C++ standard template library (STL) std::vector<T> class, but with some important advantages in performance, and functionality, and binary compatibility.
More...
|
|
A variety of constructors are provided for this class, including all those required by the C++ standard for std::vector implementations, plus additional ones providing smooth conversions between Array_<T> and std::vector<T> objects.
|
| Array_ () |
| Default constructor allocates no heap space and is very fast. More...
|
|
| Array_ (size_type n) |
| Construct an array containing n default-constructed elements. More...
|
|
| Array_ (size_type n, const T &initVal) |
| Construct an array containing n elements each set to a copy of the given initial value. More...
|
|
template<class InputIter > |
| Array_ (const InputIter &first, const InputIter &last1) |
| Construct an Array_<T> from a range [first,last1) of values identified by a pair of iterators. More...
|
|
template<class T2 > |
| Array_ (const T2 *first, const T2 *last1) |
| Construct an Array_<T> from a range [first,last1) of values identified by a pair of ordinary pointers to elements of type T2 (where T2 might be the same as T but doesn't have to be). More...
|
|
| Array_ (std::initializer_list< T > ilist) |
| Construct an Array_<T> from an std::initializer_list whose elements were convertible to type T, provided that the number of source elements does not exceed the array's max_size(). More...
|
|
template<class T2 > |
| Array_ (const std::vector< T2 > &v) |
| Construct an Array_<T> by copying from an std::vector<T2>, where T2 may be the same type as T but doesn't have to be. More...
|
|
| Array_ (const Array_ &src) |
| Copy constructor allocates exactly as much memory as is in use in the source (not its capacity) and copy constructs the elements so that T's copy constructor will be called exactly src.size() times. More...
|
|
| Array_ (Array_ &&src) |
| Move constructor swaps in the source and leaves the source default constructed. More...
|
|
template<class T2 , class X2 > |
| Array_ (const Array_< T2, X2 > &src) |
| Construct this Array_<T,X> as a copy of another Array_<T2,X2> where T2!=T or X2!=X. More...
|
|
| Array_ (T *first, const T *last1, const DontCopy &) |
| Construct an Array_<T> by referencing (sharing) a given range of data [first,last1), without copying that data; better to use the corresponding ArrayView_<T> constructor if you can. More...
|
|
template<class A > |
| Array_ (std::vector< T, A > &v, const DontCopy &) |
| Construct an Array_<T> by referencing (sharing) the data in an std::vector<T>, without copying the data; better to use the ArrayView_<T> constructor instead if you can. More...
|
|
| ~Array_ () |
| The destructor performs a deallocate() operation which may result in element destruction and freeing of heap space; see deallocate() for more information. More...
|
|
Array_ & | deallocate () |
| Empty this array of its contents, returning the array to its default-constructed, all-zero state. More...
|
|
|
These methods put new data values in an existing array, but the meaning of assignment is subtly different for resizeable (owner) arrays and fixed (non-owner) arrays.
The standard std::vector type is always an owner so the non-owner description here is an extension applying only to Array_.
For the normal case of resizeable arrays, assignment does not have an elementwise definition because the source will typically have a different number of elements than the array's current size. So regardless of the actual numbers, assignment in the resizeable case is defined as it is for std::vector: first clear the array by erasing (destructing) all the current elements in the array, then reserve sufficient heap space to hold a copy of the source, then use appropriate constructors of type T (most commonly T's copy constructor T(T)) to initialize each element to be a copy of the corresponding source element. T's assignment operators are never used in this case.
For fixed arrays, the source must have the same number of elements as are currently in the array and the meaning is conventional elementwise assignment; that is, an appropriate assignment operator of type T (most commonly T's copy assignment operator T=T) is used to change the value of each existing element.
So there are different requirements on the value type T for owner and non-owner assignments to type T2: for owner assignment T must have a constructor T(T2) available; for non-owner assignment, T must have an assignment operator T=T2 available.
|
void | assign (size_type n, const T &fillValue) |
| Set this array to be n copies of the supplied fillValue. More...
|
|
void | fill (const T &fillValue) |
| Assign all current elements of the array to the same fillValue. More...
|
|
template<class T2 > |
void | assign (const T2 *first, const T2 *last1) |
| Assign to this array to to make it a copy of the elements in range [first,last1) given by ordinary pointers. More...
|
|
template<class Iter > |
void | assign (const Iter &first, const Iter &last1) |
| Assign this array from a range [first,last1) given by non-pointer iterators. More...
|
|
Array_ & | operator= (const Array_ &src) |
| Copy assignment operator destructs the current contents of this array and then makes it a copy of the source array by repeated calls to the element type's copy constructor. More...
|
|
Array_ & | operator= (Array_ &&src) |
| Move assignment operator swaps the contents of this Array_ with the source Array_. More...
|
|
template<class T2 , class X2 > |
Array_ & | operator= (const Array_< T2, X2 > &src) |
| This is assignment from a source array whose element type T2 and/or index type X2 are different from this array's T and X. More...
|
|
template<class T2 , class A > |
Array_ & | operator= (const std::vector< T2, A > &src) |
| This is assignment from a source std::vector<T2>. More...
|
|
void | swap (Array_ &other) |
| This is a specialized algorithm providing constant time exchange of data with another array that has identical element and index types. More...
|
|
Array_ & | adoptData (T *newData, size_type dataSize, size_type dataCapacity) |
| This dangerous extension allows you to supply your own already-allocated heap space for use by this array, which then becomes the owner of the supplied heap space. More...
|
|
Array_ & | adoptData (T *newData, size_type dataSize) |
| A variant of adoptData() that assumes the capacity is the same as the current size. More...
|
|
Array_ & | shareData (T *newData, size_type dataSize) |
| This dangerous extension allows you to make this array handle refer to someone else's data without copying it. More...
|
|
Array_ & | shareData (T *first, const T *last1) |
| Same as shareData(data,size) but uses a pointer range [first,last1) to identify the data to be referenced. More...
|
|
|
These methods examine and alter the number of elements (size) or the amount of allocated heap space (capacity) or both.
|
size_type | size () const |
| Return the current number of elements stored in this array. More...
|
|
size_type | max_size () const |
| Return the maximum allowable size for this array. More...
|
|
bool | empty () const |
| Return true if there are no elements currently stored in this array. More...
|
|
size_type | capacity () const |
| Return the number of elements this array can currently hold without requiring reallocation. More...
|
|
void | resize (size_type n) |
| Change the size of this Array, preserving all the elements that will still fit, and default constructing any new elements that are added. More...
|
|
void | resize (size_type n, const T &initVal) |
| Change the size of this array, preserving all the elements that will still fit, and initializing any new elements that are added by repeatedly copy- constructing from the supplied value. More...
|
|
void | reserve (size_type n) |
| Ensure that this array has enough allocated capacity to hold the indicated number of elements. More...
|
|
void | shrink_to_fit () |
| Request that the capacity of this array be reduced to the minimum necessary to hold the number of elements currently in use. More...
|
|
size_type | allocated () const |
| Return the amount of heap space owned by this array; this is the same as capacity() for owner arrays but is zero for non-owners. More...
|
|
bool | isOwner () const |
| Does this array own the data to which it refers? If not, it can't be resized, and the destructor will not free any heap space nor call any element destructors. More...
|
|
|
These methods deal in iterators, which are STL generalized pointers.
For this class, iterators are just ordinary pointers to T, and you may depend on that. By necessity, reverse iterators can't be just pointers; however, they contain an ordinary iterator (i.e. a pointer) that can be obtained by calling the reverse iterator's base() method.
|
const T * | cbegin () const |
| Return a const pointer to the first element of this array if any, otherwise cend(), which may be null (0) in that case but does not have to be. More...
|
|
const T * | begin () const |
| The const version of begin() is the same as cbegin(). More...
|
|
T * | begin () |
| Return a writable pointer to the first element of this array if any, otherwise end(). More...
|
|
const T * | cend () const |
| Return a const pointer to what would be the element just after the last one in the array; this may be null (0) if there are no elements but doesn't have to be. More...
|
|
const T * | end () const |
| The const version of end() is the same as cend(). More...
|
|
T * | end () |
| Return a writable pointer to what would be the element just after the last one in this array. More...
|
|
const_reverse_iterator | crbegin () const |
| Return a const reverse iterator pointing to the last element in the array or crend() if the array is empty. More...
|
|
const_reverse_iterator | rbegin () const |
| The const version of rbegin() is the same as crbegin(). More...
|
|
reverse_iterator | rbegin () |
| Return a writable reverse iterator pointing to the last element in the array or rend() if the array is empty. More...
|
|
const_reverse_iterator | crend () const |
| Return the past-the-end reverse iterator that tests equal to a reverse iterator that has been incremented past the front of the array. More...
|
|
const_reverse_iterator | rend () const |
| The const version of rend() is the same as crend(). More...
|
|
reverse_iterator | rend () |
| Return a writable past-the-end reverse iterator that tests equal to a reverse iterator that has been incremented past the front of the array. More...
|
|
const T * | cdata () const |
| Return a const pointer to the first element of the array, or possibly (but not necessarily) null (0) if the array is empty. More...
|
|
const T * | data () const |
| The const version of the data() method is identical to cdata(). More...
|
|
T * | data () |
| Return a writable pointer to the first allocated element of the array, or a null pointer if no space is associated with the array. More...
|
|
|
These methods provide read and write access to individual elements, or groups of elements, that are currently present in the array.
|
const T & | operator[] (index_type i) const |
| Select an element by its index, returning a const reference. More...
|
|
T & | operator[] (index_type i) |
| Select an element by its index, returning a writable (lvalue) reference. More...
|
|
const T & | at (index_type i) const |
| Same as operator[] but always range-checked, even in a Release build. More...
|
|
T & | at (index_type i) |
| Same as operator[] but always range-checked, even in a Release build. More...
|
|
const T & | getElt (index_type i) const |
| Same as the const form of operator[]; exists to provide a non-operator method for element access in case that's needed. More...
|
|
T & | updElt (index_type i) |
| Same as the non-const form of operator[]; exists to provide a non-operator method for element access in case that's needed. More...
|
|
const T & | front () const |
| Return a const reference to the first element in this array, which must not be empty. More...
|
|
T & | front () |
| Return a writable reference to the first element in this array, which must not be empty. More...
|
|
const T & | back () const |
| Return a const reference to the last element in this array, which must not be empty. More...
|
|
T & | back () |
| Return a writable reference to the last element in this array, which must not be empty. More...
|
|
ArrayViewConst_< T, X > | operator() (index_type index, size_type length) const |
| Select a subrange of this const array by starting index and length, and return a ArrayViewConst_ referencing that data without copying it. More...
|
|
ArrayViewConst_< T, X > | getSubArray (index_type index, size_type length) const |
| Same as const form of operator()(index,length); exists to provide non-operator access to that functionality in case it is needed. More...
|
|
ArrayView_< T, X > | operator() (index_type index, size_type length) |
| Select a subrange of this array by starting index and length, and return an ArrayView_ referencing that data without copying it. More...
|
|
ArrayView_< T, X > | updSubArray (index_type index, size_type length) |
| Same as non-const operator()(index,length); exists to provide non-operator access to that functionality in case it is needed. More...
|
|
|
(Note that these are not member functions.)
|
template<class T , class X > |
void | swap (SimTK::Array_< T, X > &a1, SimTK::Array_< T, X > &a2) |
| This is a specialization of the STL std::swap() algorithm which uses the constant time built-in swap() member of the Array_ class. More...
|
|
template<class T , class X > |
Xml::Element | toXmlElement (const Array_< T, X > &thing, const std::string &name="") |
| Partial specialization for XML serialization of Array_ objects. More...
|
|
|
These methods are at namespace scope but are logically part of the Array classes.
These deal with reading and writing Arrays from and to streams, which places an additional requirement on the element type T: the element must support the same operation you are trying to do on the Array as a whole.
|
template<class T , class X > |
void | writeUnformatted (std::ostream &o, const Array_< T, X > &v) |
| Specialize writeUnformatted() for Array_<E,X> to delegate to element type E, with spaces separating the elements. More...
|
|
template<class T , class X > |
void | writeFormatted (std::ostream &o, const Array_< T, X > &v) |
| Specialize writeFormatted() for Array_<E,X> to delegate to element type E, with surrounding parentheses and commas separating the elements. More...
|
|
template<class T , class X > |
std::ostream & | operator<< (std::ostream &o, const ArrayViewConst_< T, X > &a) |
| Output a human readable representation of an array to an std::ostream (like std::cout). More...
|
|
template<class T , class X > |
bool | readUnformatted (std::istream &in, Array_< T, X > &v) |
| Specialization of readUnformatted() for variable-length Array_<T,X>; continues reading whitespace-separated tokens until error or eof. More...
|
|
template<class T , class X > |
bool | readFormatted (std::istream &in, Array_< T, X > &v) |
| Specialization of readFormatted() for variable-length Array_<T,X>; uses readArrayFromStream() to consume an appropriately-formatted array until error, closing parenthesis or bracket, or eof. More...
|
|
template<class T , class X > |
static std::istream & | readArrayFromStream (std::istream &in, Array_< T, X > &out) |
| Read in an Array_<T> from a stream, as a sequence of space-separated or comma-separated values optionally surrounded by parentheses (), square brackets [], or curly braces {}. More...
|
|
template<class T , class X > |
static std::istream & | fillArrayFromStream (std::istream &in, Array_< T, X > &out) |
| Read in a fixed number of elements from a stream into an Array. More...
|
|
template<class T , class X > |
std::istream & | operator>> (std::istream &in, Array_< T, X > &out) |
| Read an Array_<T> from a stream as a sequence of space- or comma-separated values of type T, optionally delimited by parentheses, brackets, or braces. More...
|
|
|
These operators permit lexicographical comparisons between two comparable Array_ objects, possibly with differing element and index types, and between an Array_ object and a comparable std::vector object.
|
template<class T1 , class X1 , class T2 , class X2 > |
bool | operator== (const ArrayViewConst_< T1, X1 > &a1, const ArrayViewConst_< T2, X2 > &a2) |
| Two Array_ objects are equal if and only if they are the same size() and each element compares equal using an operator T1==T2. More...
|
|
template<class T1 , class X1 , class T2 , class X2 > |
bool | operator!= (const ArrayViewConst_< T1, X1 > &a1, const ArrayViewConst_< T2, X2 > &a2) |
| The not equal operator is implemented using the equal operator. More...
|
|
template<class T1 , class X1 , class T2 , class X2 > |
bool | operator< (const ArrayViewConst_< T1, X1 > &a1, const ArrayViewConst_< T2, X2 > &a2) |
| Array_ objects are ordered lexicographically; that is, by first differing element or by length if there are no differing elements up to the length of the shorter array (in which case the shorter one is "less than" the longer). More...
|
|
template<class T1 , class X1 , class T2 , class X2 > |
bool | operator>= (const ArrayViewConst_< T1, X1 > &a1, const ArrayViewConst_< T2, X2 > &a2) |
| The greater than or equal operator is implemented using the less than operator. More...
|
|
template<class T1 , class X1 , class T2 , class X2 > |
bool | operator> (const ArrayViewConst_< T1, X1 > &a1, const ArrayViewConst_< T2, X2 > &a2) |
| The greater than operator is implemented by using less than with the arguments reversed, meaning the elements must have working comparison operators of the form T2==T1 and T2<T1. More...
|
|
template<class T1 , class X1 , class T2 , class X2 > |
bool | operator<= (const ArrayViewConst_< T1, X1 > &a1, const ArrayViewConst_< T2, X2 > &a2) |
| The less than or equal operator is implemented using the greater than operator. More...
|
|
template<class T1 , class X1 , class T2 , class A2 > |
bool | operator== (const ArrayViewConst_< T1, X1 > &a1, const std::vector< T2, A2 > &v2) |
| An Array_<T1> and an std::vector<T2> are equal if and only if they are the same size() and each element compares equal using an operator T1==T2. More...
|
|
template<class T1 , class A1 , class T2 , class X2 > |
bool | operator== (const std::vector< T1, A1 > &v1, const ArrayViewConst_< T2, X2 > &a2) |
| An std::vector<T1> and an Array_<T2> are equal if and only if they are the same size() and each element compares equal using an operator T2==T1. More...
|
|
template<class T1 , class X1 , class T2 , class A2 > |
bool | operator!= (const ArrayViewConst_< T1, X1 > &a1, const std::vector< T2, A2 > &v2) |
| The not equal operator is implemented using the equal operator. More...
|
|
template<class T1 , class A1 , class T2 , class X2 > |
bool | operator!= (const std::vector< T1, A1 > &v1, const ArrayViewConst_< T2, X2 > &a2) |
| The not equal operator is implemented using the equal operator. More...
|
|
template<class T1 , class X1 , class T2 , class A2 > |
bool | operator< (const ArrayViewConst_< T1, X1 > &a1, const std::vector< T2, A2 > &v2) |
| An Array_<T1> and std::vector<T2> are ordered lexicographically; that is, by first differing element or by length if there are no differing elements up to the length of the shorter container (in which case the shorter one is "less than" the longer). More...
|
|
template<class T1 , class A1 , class T2 , class X2 > |
bool | operator< (const std::vector< T1, A1 > &v1, const ArrayViewConst_< T2, X2 > &a2) |
| An std::vector<T1> and Array_<T2> are ordered lexicographically; that is, by first differing element or by length if there are no differing elements up to the length of the shorter container (in which case the shorter one is "less than" the longer). More...
|
|
template<class T1 , class X1 , class T2 , class A2 > |
bool | operator>= (const ArrayViewConst_< T1, X1 > &a1, const std::vector< T2, A2 > &v2) |
| The greater than or equal operator is implemented using the less than operator. More...
|
|
template<class T1 , class A1 , class T2 , class X2 > |
bool | operator>= (const std::vector< T1, A1 > &v1, const ArrayViewConst_< T2, X2 > &a2) |
| The greater than or equal operator is implemented using the less than operator. More...
|
|
template<class T1 , class X1 , class T2 , class A2 > |
bool | operator> (const ArrayViewConst_< T1, X1 > &a1, const std::vector< T2, A2 > &v2) |
| The greater than operator is implemented by using less than with the arguments reversed, meaning the elements must have working comparison operators of the form T2==T1 and T2<T1. More...
|
|
template<class T1 , class A1 , class T2 , class X2 > |
bool | operator> (const std::vector< T1, A1 > &v1, const ArrayViewConst_< T2, X2 > &a2) |
| The greater than operator is implemented by using less than with the arguments reversed, meaning the elements must have working comparison operators of the form T2==T1 and T2<T1. More...
|
|
template<class T1 , class X1 , class T2 , class A2 > |
bool | operator<= (const ArrayViewConst_< T1, X1 > &a1, const std::vector< T2, A2 > &v2) |
| The less than or equal operator is implemented using the greater than operator. More...
|
|
template<class T1 , class A1 , class T2 , class X2 > |
bool | operator<= (const std::vector< T1, A1 > &v1, const ArrayViewConst_< T2, X2 > &a2) |
| The less than or equal operator is implemented using the greater than operator. More...
|
|
|
These are methods that change the number of elements in the array by insertion or erasure.
|
void | push_back (const T &value) |
| This method increases the size of the Array by one element at the end and initializes that element by copy constructing it from the given value. More...
|
|
void | push_back (T &&value) |
| This is the move form of push_back(), taking an rvalue reference rather than an lvalue reference. More...
|
|
template<class... Args> |
void | emplace_back (Args &&... args) |
| This is similar to push_back() but rather than copying, it constructs the element in place at the end of the array. More...
|
|
void | push_back () |
| (Deprecated, use emplace_back() instead) This is a non-standard version of push_back() that increases the size of the array by one default-constructed element at the end. More...
|
|
T * | raw_push_back () |
| (Deprecated, use emplace_back() instead) This dangerous non-standard method increases the Array's size by one element at the end but doesn't perform any construction so the memory is filled with garbage. More...
|
|
void | pop_back () |
| Remove the last element from this array, which must not be empty. More...
|
|
T * | erase (T *first, const T *last1) |
| Erase elements in range [first,last1), packing in any later elements into the newly-available space and reducing the array's size by the number of elements erased. More...
|
|
T * | erase (T *p) |
| Erase just one element, moving all subsequent elements down one slot and reducing the array's size by one. More...
|
|
T * | eraseFast (T *p) |
| Be careful with this non-standard extension; it erases one element and then moves the last one in its place which changes the element order from what it was before (unlike the standard erase() method). More...
|
|
void | clear () |
| Erase all the elements currently in this array without changing the capacity; equivalent to erase(begin(),end()) but a little faster. More...
|
|
T * | insert (T *p, size_type n, const T &value) |
| Insert n copies of a given value at a particular location within this array, moving all following elements up by n positions. More...
|
|
T * | insert (T *p, const T &value) |
| Insert a new element at a given location within this array, initializing it to a copy of a given value and moving all following elements up one position. More...
|
|
template<class... Args> |
T * | emplace (T *p, Args &&... args) |
| Insert a new element at a given location within this array, by invoking T's constructor whose signature matches the supplied arguments. More...
|
|
template<class T2 > |
T * | insert (T *p, const T2 *first, const T2 *last1) |
| Insert elements in a range [first,last1) into this array at a given position p, moving all following elements up by n=(last1-first) positions. More...
|
|
template<class Iter > |
T * | insert (T *p, const Iter &first, const Iter &last1) |
| Insert elements in a range [first,last1) where the range is given by non-pointer iterators. More...
|
|
template<class T, class X>
class SimTK::Array_< T, X >
The Array_<T> container class is a plug-compatible replacement for the C++ standard template library (STL) std::vector<T> class, but with some important advantages in performance, and functionality, and binary compatibility.
- Template Parameters
-
T | The type of object to be stored in this container. |
X | The type to be used for indexing this container, with default unsigned (not size_t). Any integral type may be used, as well as user types that satisfy the requirements discussed with class ArrayIndexTraits. |
- Performance:
- There are several performance and memory footprint problems with the C++ standard STL design in general, and with Microsoft's implementation in particular, that are addressed here. Microsoft in its wisdom decided that STL containers should still do runtime range checks in Release builds for safety, but that makes them too slow for use in some high-performance contexts (and also breaks the promise of generic programming but that's another rant). In practice, VC++12 (2013) std::vector runs about half speed for simple operations like indexing and push_back (see Simbody's TestArray regression test for an executable performance comparison). Attempting to disable these runtime checks with
_SECURE_SCL
breaks binary compatibility with other code built with the same compiler but without the flag. In contrast the performance of this Array_<T> class on any platform is indistinguishable from what you would get by managing your own heap-allocated arrays. 64 bit compilers vary on how well they handle 32 bit integers though, so in some cases the default index type (32 bit unsigned) won't be as fast as if you use a 64 bit unsigned type as does std::vector.
- Regarding memory footprint, the typical implementation of std::vector uses three pointers: 12 bytes for 32 bit machines; 24 bytes for 64 bit machines. Microsoft somehow manages to trump this with 20 to 24 bytes on a 32 bit machine (last checked in VC++9); they are at 24 bytes for 64 bit Release builds in VC++12, 32 bytes in Debug builds. Array_ instead uses one pointer and two lengths for a total size as little as 8 bytes on 32 bits and 16 on 64 bits; see below for details. The binary representation for Array_ is the same in Release and Debug builds.
- Some nuts and bolts:
- We promise that no heap allocation occurs when an empty Array_<T> object is declared (that is, when an Array_<T> is default-constructed); in that case both begin() and end() are null.
- Array_<T> methods are extremely fast in Release builds with zero overhead, inline, unchecked methods. The implementations of inline methods are kept small to ensure that they are actually inlined in practice; and generated assembly code was examined to make sure.
- There are some dangerous extensions provided that permit the expert user to construct objects directly into the array without having to copy them, a big win for complicated objects and even bigger for those that don't have copy constructors!
- There is a constant-time eraseFast() method you can use if you don't mind the array being reordered after the erase. This avoids the extremely expensive "compress" activity required by the standard erase() method.
- The optional index-type template parameter can be used to reduce the memory footprint to as little as 8 bytes on a 32 bit machine (e.g., a 32 bit pointer and two shorts).
- The default size_type for an Array_<T> is a 32-bit unsigned integer rather than a size_t. On a 64-bit machine that keeps the memory footprint down substantially since the structure is then one 64-bit pointer and two 32-bit integers, fitting tightly into a cleanly alignable 16 bytes.
- Functionality:
- For the most part Array_<T> is a plug-compatible replacement for std::vector<T>, and everything that both classes can do is done with an identical API. However, there are a few additions and subtractions:
- This class always uses the default new/delete allocator; there is no option to specify your own as there is in std::vector.
- Instead of an allocator, the second template argument X to Array_<T,X> is an optional index type which can be used to provide type-safe indexing (i.e. the array can only be indexed by indices of a particular type, like MobilizedBodyIndex). This has zero performance cost if the index is an integral type or class consisting of only an integral value such as those produced by the SimTK_DEFINE_UNIQUE_INDEX_TYPE macro.
- You can create uninitialized slots in the array and construct directly into them rather than having to construct a temporary object which must then be copied into the array.
- You can create Array_<T> objects that reference existing data, including the contents of std::vectors.
- This class implements the std::vector features from the C++11 standard (with a few exceptions; see below).
- Compatibility:
- Included here are binary compatibility issues and compatibility with the C++ standard STL objects.
- Most important, it is safe to pass an Array_<T> through an API to a binary library without worrying about compiler version or Release/Debug compatibility issues. For a given compiler (e.g. gcc or Microsoft cl) and word size (64 bit vs. 32 bit), Array_<T> has an extremely stable memory layout that is preserved across compiler versions, and between Release and Debug builds. This allows us to use Array_<T> in the SimTK API where use of std::vector<T> would be desirable but problematic.
- It supports all standard types, methods, iterators, and operators of the C++11 standard std::vector, so it works smoothly with all STL containers and algorithms. However, it does not provide the same guarantees of behavior when exceptions occur. In particular, when resizing Array_ will use move construction if available even if the move constructor hasn't been marked "nothrow".
- It is convertible to and from std::vector, usually without copying the elements. It is easy to provide APIs that accept either Array_<T> or std::vector<T>; the std::vector's data is referenced by an Array_ handle that is used to convey the data across the API without binary compatibility problems.
- See also
- Array_, ArrayViewConst_, ArrayIndexTraits