Simbody  3.5
Array.h
Go to the documentation of this file.
1 #ifndef SimTK_SimTKCOMMON_ARRAY_H_
2 #define SimTK_SimTKCOMMON_ARRAY_H_
3 
4 /* -------------------------------------------------------------------------- *
5  * Simbody(tm): SimTKcommon *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from *
8  * Simbios, the NIH National Center for Physics-Based Simulation of *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11  * *
12  * Portions copyright (c) 2010-13 Stanford University and the Authors. *
13  * Authors: Michael Sherman *
14  * Contributors: *
15  * *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17  * not use this file except in compliance with the License. You may obtain a *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19  * *
20  * Unless required by applicable law or agreed to in writing, software *
21  * distributed under the License is distributed on an "AS IS" BASIS, *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23  * See the License for the specific language governing permissions and *
24  * limitations under the License. *
25  * -------------------------------------------------------------------------- */
26 
36 
37 #include <algorithm>
38 #include <iterator>
39 #include <vector>
40 #include <ostream>
41 #include <climits>
42 #include <typeinfo>
43 
44 namespace SimTK {
45 
46 // These are the classes defined in this header.
47 template <class X> struct ArrayIndexTraits;
48 template <class T, class X=unsigned> class ArrayViewConst_;
49 template <class T, class X=unsigned> class ArrayView_;
50 template <class T, class X=unsigned> class Array_;
51 
52 // NOTE: I have attempted to force the compilers to inline certain trivial
53 // methods here because I observed Visual C++ 2013 fail to inline operator[]
54 // in a performance-critical method (getCacheEntry() to be specific). It is
55 // essential that there be no overhead introduced by the Array_ classes, which
56 // Simbody uses extensively specifically because std::vector was too slow.
57 // (sherm 20140404).
58 
59 //==============================================================================
60 // CLASS ArrayIndexTraits
61 //==============================================================================
62 
105 template <class X> struct ArrayIndexTraits {
108  typedef typename X::size_type size_type;
111  typedef typename X::difference_type difference_type;
114  static size_type max_size() {return X::max_size();}
115 };
116 
119 template <> struct ArrayIndexTraits<unsigned> {
120  typedef unsigned size_type;
121  typedef int difference_type;
122  static size_type max_size() {return (unsigned)INT_MAX;}
123 };
124 
126 template <> struct ArrayIndexTraits<int> {
127  typedef int size_type;
128  typedef int difference_type;
129  static size_type max_size() {return INT_MAX;}
130 };
131 
139 template <> struct ArrayIndexTraits<unsigned long> {
140  typedef unsigned long size_type;
141  typedef long difference_type;
142  static size_type max_size() {return (unsigned long)LONG_MAX;}
143 };
144 
152 template <> struct ArrayIndexTraits<long> {
153  typedef long size_type;
154  typedef long difference_type;
155  static size_type max_size() {return LONG_MAX;}
156 };
157 
163 template <> struct ArrayIndexTraits<unsigned short> {
164  typedef unsigned short size_type;
165  typedef int difference_type;
166  static size_type max_size() {return USHRT_MAX;}
167 };
168 
173 template <> struct ArrayIndexTraits<short> {
174  typedef short size_type;
175  typedef short difference_type;
176  static size_type max_size() {return SHRT_MAX;}
177 };
178 
179 
184 template <> struct ArrayIndexTraits<unsigned char> {
185  typedef unsigned char size_type;
186  typedef short difference_type;
187  static size_type max_size() {return UCHAR_MAX;} // not CHAR_MAX
188 };
189 
195 template <> struct ArrayIndexTraits<signed char> {
196  typedef signed char size_type;
197  typedef signed char difference_type;
198  static size_type max_size() {return SCHAR_MAX;}
199 };
200 
207 template <> struct ArrayIndexTraits<char> {
208  typedef char size_type;
209  typedef signed char difference_type;
210  static size_type max_size() {return (char)SCHAR_MAX;}
211 };
212 
218 template <> struct ArrayIndexTraits<bool> {
219  typedef unsigned char size_type;
220  typedef signed char difference_type;
221  static size_type max_size() {return 2;}
222 };
223 
226 template <> struct ArrayIndexTraits<unsigned long long> {
227  typedef unsigned long long size_type;
228  typedef long long difference_type;
229  static size_type max_size()
230  {return (unsigned long long)LLONG_MAX;}
231 };
232 
235 template <> struct ArrayIndexTraits<long long> {
236  typedef long long size_type;
237  typedef long long difference_type;
238  static size_type max_size() {return LLONG_MAX;}
239 };
240 
241 // Don't show this in Doxygen.
243 // This helper class decides what integral type we should use to best pack
244 // the index type's size_type representation. The idea is to pack the whole
245 // Array_ structure into 8 bytes on a 32 bit machine, 16 bytes on a 64 bit
246 // machine, using the largest integral type that will work, giving a layout
247 // like this: | data pointer |
248 // | nUsed | nAllocated |
249 
250 // The default implementation just uses the integral type itself.
251 template <class Integral, class is64Bit> struct ArrayIndexPackTypeHelper
252 { typedef Integral packed_size_type;};
253 
254 // On 32 bit machine, pack anything smaller than a short into a short.
255 template<> struct ArrayIndexPackTypeHelper<bool,FalseType>
256 { typedef unsigned short packed_size_type;};
257 template<> struct ArrayIndexPackTypeHelper<char,FalseType>
258 { typedef unsigned short packed_size_type;};
259 template<> struct ArrayIndexPackTypeHelper<unsigned char,FalseType>
260 { typedef unsigned short packed_size_type;};
261 template<> struct ArrayIndexPackTypeHelper<signed char,FalseType>
262 { typedef short packed_size_type;};
263 
264 // On 64 bit machine, pack anything smaller than an int into an int.
265 template<> struct ArrayIndexPackTypeHelper<bool,TrueType>
266 { typedef unsigned int packed_size_type;};
267 template<> struct ArrayIndexPackTypeHelper<char,TrueType>
268 { typedef unsigned int packed_size_type;};
269 template<> struct ArrayIndexPackTypeHelper<unsigned char,TrueType>
270 { typedef unsigned int packed_size_type;};
271 template<> struct ArrayIndexPackTypeHelper<signed char,TrueType>
272 { typedef int packed_size_type;};
273 template<> struct ArrayIndexPackTypeHelper<unsigned short,TrueType>
274 { typedef unsigned int packed_size_type;};
275 template<> struct ArrayIndexPackTypeHelper<short,TrueType>
276 { typedef int packed_size_type;};
277 
278 template <class Integral> struct ArrayIndexPackType
279 { typedef typename ArrayIndexPackTypeHelper<Integral,Is64BitPlatformType>
280  ::packed_size_type packed_size_type;};
288 //==============================================================================
289 // CLASS ArrayViewConst_
290 //==============================================================================
317 template <class T, class X> class ArrayViewConst_ {
318 public:
319 
320 
321 //------------------------------------------------------------------------------
328 typedef T value_type;
330 typedef X index_type;
332 typedef T* pointer;
334 typedef const T* const_pointer;
336 typedef T& reference;
338 typedef const T& const_reference;
340 typedef T* iterator;
342 typedef const T* const_iterator;
344 typedef std::reverse_iterator<iterator> reverse_iterator;
346 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
353 typedef typename ArrayIndexPackType<size_type>::packed_size_type
358 //------------------------------------------------------------------------------
364 
366 ArrayViewConst_() : pData(0), nUsed(0), nAllocated(0) {}
367 
378 : pData(0), nUsed(src.nUsed), nAllocated(0) {
379  if (nUsed) pData = const_cast<T*>(src.pData);
380 }
381 
382 // Copy assignment is suppressed.
383 
406 ArrayViewConst_(const T* first, const T* last1)
407 : pData(0),nUsed(0),nAllocated(0) {
408  if (last1==first) return; // empty
409 
410  SimTK_ERRCHK((first&&last1)||(first==last1),
411  "ArrayViewConst_<T>(first,last1)",
412  "One of the source pointers was null (0); either both must be"
413  " non-null or both must be null.");
414 
415  SimTK_ERRCHK3(this->isSizeOK(last1-first),
416  "ArrayViewConst_<T>(first,last1)",
417  "The source data's size %llu is too big for this array which"
418  " is limited to %llu elements by its index type %s.",
419  this->ull(last1-first), ullMaxSize(), indexName());
420 
421  pData = const_cast<T*>(first);
422  nUsed = packed_size_type(last1-first);
423  // nAllocated is already zero
424 }
425 
453 template <class A>
454 ArrayViewConst_(const std::vector<T,A>& src)
455 : pData(0),nUsed(0),nAllocated(0) {
456  if (src.empty()) return;
457 
458  SimTK_ERRCHK3(this->isSizeOK(src.size()),
459  "ArrayViewConst_<T>::ctor(std::vector<T>)",
460  "The source std::vector's size %llu is too big for this array which"
461  " is limited to %llu elements by its index type %s.",
462  this->ull(src.size()), ullMaxSize(), indexName());
463 
464  pData = const_cast<T*>(&src.front());
465  nUsed = packed_size_type(src.size());
466  // nAllocated is already zero
467 }
470 operator const ArrayView_<T,X>&() const
471 { return *reinterpret_cast<const ArrayView_<T,X>*>(this); }
474 operator const Array_<T,X>&() const
475 { return *reinterpret_cast<const Array_<T,X>*>(this); }
476 
482 void disconnect() {
483  SimTK_ASSERT(nAllocated==0,
484  "ArrayViewConst_::deallocate(): called on an owner Array_");
485  nUsed = 0;
486  pData = 0;
487 }
488 
492  disconnect();
493 }
497 //------------------------------------------------------------------------------
504 
506 size_type size() const {return size_type(nUsed);}
508 size_type max_size() const
509 { return ArrayIndexTraits<X>::max_size(); }
512 bool empty() const {return nUsed==0;}
517 size_type capacity() const
518 { return size_type(nAllocated?nAllocated:nUsed); }
522 size_type allocated() const {return size_type(nAllocated);}
528 bool isOwner() const {return nAllocated || pData==0;}
529 /*}*/
530 
531 
532 //------------------------------------------------------------------------------
539 
547 SimTK_FORCE_INLINE const T& operator[](index_type i) const {
548  SimTK_INDEXCHECK(size_type(i),size(),"ArrayViewConst_<T>::operator[]()");
549  return pData[i];
550 }
555 const T& at(index_type i) const {
556  SimTK_INDEXCHECK_ALWAYS(size_type(i),size(),"ArrayViewConst_<T>::at()");
557  return pData[i];
558 }
561 SimTK_FORCE_INLINE const T& getElt(index_type i) const {
562  SimTK_INDEXCHECK(size_type(i),size(),"ArrayViewConst_<T>::getElt()");
563  return pData[i];
564 }
570 SimTK_FORCE_INLINE const T& front() const
571 { SimTK_ERRCHK(!empty(), "ArrayViewConst_<T>::front()", "Array was empty.");
572  return pData[0]; }
578 SimTK_FORCE_INLINE const T& back() const
579 { SimTK_ERRCHK(!empty(), "ArrayViewConst_<T>::back()", "Array was empty.");
580  return pData[nUsed-1]; }
581 
600 ArrayViewConst_ operator()(index_type index, size_type length) const {
601  const size_type ix(index);
602  SimTK_ERRCHK2(isSizeInRange(ix, size()), "ArrayViewConst_<T>(index,length)",
603  "For this operator, we must have 0 <= index <= size(), but"
604  " index==%llu and size==%llu.", this->ull(ix), ullSize());
605  SimTK_ERRCHK2(isSizeInRange(length, size_type(size()-ix)),
606  "ArrayViewConst_<T>(index,length)",
607  "This operator requires 0 <= length <= size()-index, but"
608  " length==%llu and size()-index==%llu.",this->ull(length),this->ull(size()-ix));
609 
610  return ArrayViewConst_(pData+ix, pData+ix+length);
611 }
614 ArrayViewConst_ getSubArray(index_type index, size_type length) const
615 { return (*this)(index,length); }
616 
620 //------------------------------------------------------------------------------
629 
634 const T* cbegin() const {return pData;}
639 const T* cend() const {return pData + nUsed;}
641 const T* begin() const {return pData;}
643 const T* end() const {return pData + nUsed;}
644 
647 const_reverse_iterator crbegin() const
648 { return const_reverse_iterator(cend()); }
652 const_reverse_iterator crend() const
653 { return const_reverse_iterator(cbegin()); }
655 const_reverse_iterator rbegin() const {return crbegin();}
657 const_reverse_iterator rend() const {return crend();}
658 
665 const T* cdata() const {return pData;}
667 const T* data() const {return pData;}
671 //------------------------------------------------------------------------------
672  protected:
673 //------------------------------------------------------------------------------
674 // The remainder of this class is for the use of the ArrayView_<T,X> and
675 // Array_<T,X> derived classes only and should not be documented for users to
676 // see.
677 
678 // Don't let doxygen see any of this.
680 packed_size_type psize() const {return nUsed;}
681 packed_size_type pallocated() const {return nAllocated;}
682 
683 // These provide direct access to the data members for our trusted friends.
684 void setData(const T* p) {pData = const_cast<T*>(p);}
685 void setSize(size_type n) {nUsed = packed_size_type(n);}
686 void incrSize() {++nUsed;}
687 void decrSize() {--nUsed;}
688 void setAllocated(size_type n) {nAllocated = packed_size_type(n);}
689 
690 // Check whether a given size is the same as the current size of this array,
691 // avoiding any compiler warnings due to mismatched integral types.
692 template <class S>
693 bool isSameSize(S sz) const
694 { return ull(sz) == ullSize(); }
695 
696 // Check that a source object's size will fit in the array being careful to
697 // avoid overflow and warnings in the comparison.
698 template <class S>
699 bool isSizeOK(S srcSz) const
700 { return ull(srcSz) <= ullMaxSize(); }
701 
702 // This is identical in function to std::distance() (reports how many
703 // elements lie between two iterators) but avoids any slow
704 // Release-build bugcatchers that Microsoft may have felt compelled to add.
705 // The implementation is specialized for random access iterators because
706 // they can measure distance very fast.
707 template<class Iter> static
708 typename std::iterator_traits<Iter>::difference_type
709 iterDistance(const Iter& first, const Iter& last1) {
710  return iterDistanceImpl(first,last1,
711  typename std::iterator_traits<Iter>::iterator_category());
712 }
713 
714 // Generic slow implementation for non-random access iterators. This is fine
715 // for forward and bidirectional iterators, but it will *consume* input
716 // iterators so is useless for them.
717 template<class Iter> static
718 typename std::iterator_traits<Iter>::difference_type
719 iterDistanceImpl(const Iter& first, const Iter& last1, std::input_iterator_tag) {
720  typename std::iterator_traits<Iter>::difference_type d = 0;
721  for (Iter src=first; src != last1; ++src, ++d)
722  ;
723  return d;
724 }
725 
726 // Fast specialization for random access iterators (including ordinary
727 // pointers) -- just subtract.
728 template<class Iter> static
729 typename std::iterator_traits<Iter>::difference_type
730 iterDistanceImpl(const Iter& first, const Iter& last1,
731  std::random_access_iterator_tag) {
732  return last1 - first;
733 }
734 
735 // This method attempts to determine whether any elements in the iterator range
736 // [first,last1) overlap with the elements stored in this array. This is used
737 // for error checks for operations where source is not permitted to overlap the
738 // destination. For random access iterators (including ordinary pointers), we
739 // can answer this question definitively because we expect the data to be
740 // consecutive in memory. For other kinds of iterators, we will just assume
741 // there is no overlap. Note that null ranges do not overlap even if the
742 // pair of equal iterators points within the other range -- what matters is
743 // the number of overlapping elements.
744 template<class Iter> bool
745 overlapsWithData(const Iter& first, const Iter& last1) {
746  return overlapsWithDataImpl(first,last1,
747  typename std::iterator_traits<Iter>::iterator_category());
748 }
749 
750 // This is a partial specialization of the above where the data is given
751 // with ordinary pointers.
752 template <class T2> bool
753 overlapsWithData(const T2* first, const T2* last1) {
754  // Find the start and end+1 of the alleged overlap region. There is
755  // overlap iff end+1 > start. Note that this works if either range
756  // is [0,0) or [p,p), or if last1 is illegally less than first (we just
757  // want to report no overlap in that case -- it is someone else's business
758  // to complain).
759  const T* obegin = std::max(cbegin(), (const T*)first);
760  const T* oend1 = std::min(cend(), (const T*)last1);
761 
762  return obegin < oend1;
763 }
764 
765 // This is the generic implementation for any type of input iterator other than
766 // random access (i.e., bidirectional, forward, or input) -- assume no overlap.
767 template<class Iter> bool
768 overlapsWithDataImpl(const Iter&, const Iter&, std::input_iterator_tag)
769 { return false; }
770 
771 // Here we can actually test for overlap since we have random access iterators.
772 // We convert them to pointers and then look for memory overlap.
773 template<class Iter> bool
774 overlapsWithDataImpl(const Iter& first, const Iter& last1,
775  std::random_access_iterator_tag) {
776  // We must check that the input iterators span a non-zero range before
777  // assuming we can dereference them.
778  if (last1 <= first)
779  return false; // zero or malformed source range: no overlap
780 
781  // We now know we can dereference first and last1-1 (can't safely
782  // dereference last1 but we can use pointer arithmetic to point past
783  // the (last-1)th element in memory). We then take the dereferenced
784  // object's address to get ordinary pointers that we can use to
785  // watch for illegal overlap.
786  return overlapsWithData(&*first, &*(last1-1)); // use pointer overload
787 }
788 
789 // Cast an integral type to maximal-width unsigned long long to avoid accidental
790 // overflows that might otherwise occur due to wraparound that can happen
791 // with small index types.
792 template <class S>
793 static unsigned long long ull(S sz)
794 { return (unsigned long long)sz; }
795 
796 // Return size(), capacity(), and max_size() cast to unsigned long long.
797 unsigned long long ullSize() const {return ull(size());}
798 unsigned long long ullCapacity() const {return ull(capacity());}
799 unsigned long long ullMaxSize() const {return ull(max_size());}
800 
801 // Useful in error messages for explaining why something was too big.
802 const char* indexName() const {return NiceTypeName<X>::name();}
803 
806 private:
807 //------------------------------------------------------------------------------
808 // DATA MEMBERS
809 // These are the only data members and this layout is guaranteed not to change
810 // from release to release. If data is null, then nUsed==nAllocated==0.
811 
812 T* pData; // ptr to data referenced here, or 0 if none
813 packed_size_type nUsed; // number of elements currently present (size)
814 packed_size_type nAllocated; // heap allocation; 0 if pData is not owned
815 
816 ArrayViewConst_& operator=(const ArrayViewConst_& src); // suppressed
817 };
818 
819 
820 
821 
822 
823 
824 //==============================================================================
825 // CLASS ArrayView_
826 //==============================================================================
838 template <class T, class X> class ArrayView_ : public ArrayViewConst_<T,X> {
839 typedef ArrayViewConst_<T,X> CBase;
840 public:
841 //------------------------------------------------------------------------------
846 /*{*/
847 typedef T value_type;
848 typedef X index_type;
849 typedef T* pointer;
850 typedef const T* const_pointer;
851 typedef T& reference;
852 typedef const T& const_reference;
853 typedef T* iterator;
854 typedef const T* const_iterator;
855 typedef std::reverse_iterator<iterator> reverse_iterator;
856 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
859 typedef typename ArrayIndexPackType<size_type>::packed_size_type
861 /*}*/
862 
863 
864 //------------------------------------------------------------------------------
870 
872 ArrayView_() : CBase() {}
873 
875 ArrayView_(const ArrayView_& src) : CBase(src) {}
876 
878 ArrayView_(T* first, const T* last1) : CBase(first,last1) {}
879 
881 template <class A>
882 ArrayView_(std::vector<T,A>& v) : CBase(v) {}
883 
885 operator const Array_<T,X>&() const
886 { return *reinterpret_cast<const Array_<T,X>*>(this); }
887 
889 operator Array_<T,X>&()
890 { return *reinterpret_cast<Array_<T,X>*>(this); }
891 
894 void disconnect() {this->CBase::disconnect();}
895 
898 ~ArrayView_() {this->CBase::disconnect();}
902 //------------------------------------------------------------------------------
914 
917  if (&src != this)
918  avAssignIteratorDispatch(src.cbegin(), src.cend(),
919  std::random_access_iterator_tag(),
920  "ArrayView_<T>::operator=(ArrayView_<T>)");
921  return *this;
922 }
923 
924 
927 template <class T2, class X2>
929  if ((const void*)&src != (void*)this)
930  avAssignIteratorDispatch(src.cbegin(), src.cend(),
931  std::random_access_iterator_tag(),
932  "ArrayView_<T>::operator=(Array_<T2>)");
933  return *this;
934 }
935 
936 // Help out dumb compilers struggling to match the template arguments and
937 // promote the Array_ or ArrayView_ to ArrayConstView_ at the same time.
938 
941 template <class T2, class X2>
943 { return *this = static_cast<const ArrayViewConst_<T2,X2>&>(src); }
946 template <class T2, class X2>
948 { return *this = static_cast<const ArrayViewConst_<T2,X2>&>(src); }
949 
952 template <class T2, class A2>
953 ArrayView_& operator=(const std::vector<T2,A2>& src) {
954  avAssignIteratorDispatch(src.begin(), src.end(),
955  std::random_access_iterator_tag(),
956  "ArrayView_<T>::operator=(std::vector<T2>)");
957  return *this;
958 }
959 
961 ArrayView_& operator=(const T& fillValue)
962 { fill(fillValue); return *this; }
963 
969 ArrayView_& fill(const T& fillValue) {
970  for (T* d = begin(); d != end(); ++d)
971  *d = fillValue; // using T::operator=(T)
972  return *this;
973 }
974 
978 void assign(size_type n, const T& fillValue) {
979  SimTK_ERRCHK2(n == size(), "ArrayView_<T>::assign(n,value)",
980  "Assignment to an ArrayView is permitted only if the source"
981  " is the same size. Here n==%llu element(s) but the"
982  " ArrayView has a fixed size of %llu.",
983  this->ull(n), this->ull(size()));
984 
985  fill(fillValue);
986 }
987 
1005 template <class T2>
1006 void assign(const T2* first, const T2* last1) {
1007  const char* methodName = "ArrayView_<T>::assign(T2* first, T2* last1)";
1008  SimTK_ERRCHK((first&&last1)||(first==last1), methodName,
1009  "One of the source pointers was null (0); either both must be"
1010  " non-null or both must be null.");
1011  // Valid pointers are random access iterators.
1012  avAssignIteratorDispatch(first, last1, std::random_access_iterator_tag(),
1013  methodName);
1014 }
1015 
1045 // Watch out for integral types matching this signature -- they must be
1046 // forwarded to the assign(n, fillValue) signature instead.
1047 template <class Iter>
1048 void assign(const Iter& first, const Iter& last1)
1049 { avAssignDispatch(first,last1,typename IsIntegralType<Iter>::Result(),
1050  "ArrayView_<T>::assign(Iter first, Iter last1)"); }
1054 //------------------------------------------------------------------------------
1061 
1068 SimTK_FORCE_INLINE const T& operator[](index_type i) const
1069 { return this->CBase::operator[](i); }
1070 
1079 { return const_cast<T&>(this->CBase::operator[](i)); }
1080 
1085 const T& at(index_type i) const {return this->CBase::at(i);}
1086 
1091 T& at(index_type i) {return const_cast<T&>(this->CBase::at(i));}
1092 
1095 SimTK_FORCE_INLINE const T& getElt(index_type i) const
1096 { return this->CBase::getElt(i); }
1099 SimTK_FORCE_INLINE T& updElt(index_type i)
1100 { return const_cast<T&>(this->CBase::getElt(i)); }
1101 
1107 SimTK_FORCE_INLINE const T& front() const {return this->CBase::front();}
1108 
1114 SimTK_FORCE_INLINE T& front() {return const_cast<T&>(this->CBase::front());}
1115 
1121 SimTK_FORCE_INLINE const T& back() const {return this->CBase::back();}
1122 
1128 SimTK_FORCE_INLINE T& back() {return const_cast<T&>(this->CBase::back());}
1129 
1148 ArrayView_ operator()(index_type index, size_type length) {
1149  const size_type ix(index);
1150  SimTK_ERRCHK2(isSizeInRange(ix, size()), "ArrayView_<T>(index,length)",
1151  "For this operator, we must have 0 <= index <= size(), but"
1152  " index==%llu and size==%llu.", this->ull(ix), ullSize());
1153  SimTK_ERRCHK2(isSizeInRange(length, size_type(size()-ix)),
1154  "ArrayView_<T>(index,length)",
1155  "This operator requires 0 <= length <= size()-index, but"
1156  " length==%llu and size()-index==%llu.",this->ull(length),this->ull(size()-ix));
1157 
1158  return ArrayView_(data()+ix, data()+ix+length);
1159 }
1162 ArrayView_ updSubArray(index_type index, size_type length)
1163 { return (*this)(index,length); }
1167 //------------------------------------------------------------------------------
1176 
1181 SimTK_FORCE_INLINE const T* cbegin() const {return this->CBase::cbegin();}
1183 SimTK_FORCE_INLINE const T* begin() const {return this->CBase::cbegin();}
1188 SimTK_FORCE_INLINE T* begin() {return const_cast<T*>(this->CBase::cbegin());}
1189 
1194 SimTK_FORCE_INLINE const T* cend() const {return this->CBase::cend();}
1196 SimTK_FORCE_INLINE const T* end() const {return this->CBase::cend();}
1201 SimTK_FORCE_INLINE T* end() {return const_cast<T*>(this->CBase::cend());}
1202 
1205 const_reverse_iterator crbegin() const
1206 { return this->CBase::crbegin(); }
1208 const_reverse_iterator rbegin() const
1209 { return this->CBase::crbegin(); }
1212 reverse_iterator rbegin() {return reverse_iterator(end());}
1213 
1217 const_reverse_iterator crend() const
1218 { return this->CBase::crend(); }
1220 const_reverse_iterator rend() const
1221 { return this->CBase::crend(); }
1225 reverse_iterator rend() {return reverse_iterator(begin());}
1226 
1233 SimTK_FORCE_INLINE const T* cdata() const {return this->CBase::cdata();}
1236 SimTK_FORCE_INLINE const T* data() const {return this->CBase::cdata();}
1240 SimTK_FORCE_INLINE T* data() {return const_cast<T*>(this->CBase::cdata());}
1244 //------------------------------------------------------------------------------
1250 
1251 // Note: these have to be explicitly forwarded to the base class methods
1252 // in order to keep gcc from complaining. Note that the "this->" is
1253 // apparently necessary in order to permit delayed definition of templatized
1254 // methods. Doxygen picks up the comments from the base class.
1255 
1256 SimTK_FORCE_INLINE size_type size() const {return this->CBase::size();}
1257 size_type max_size() const {return this->CBase::max_size();}
1258 bool empty() const {return this->CBase::empty();}
1259 size_type capacity() const {return this->CBase::capacity();}
1260 size_type allocated() const {return this->CBase::allocated();}
1261 bool isOwner() const {return this->CBase::isOwner();}
1265 //------------------------------------------------------------------------------
1266  private:
1267 //------------------------------------------------------------------------------
1268 // no data members are allowed
1269 
1270 //------------------------------------------------------------------------------
1271 // ARRAY VIEW ASSIGN DISPATCH
1272 // This is the assign() implementation for ArrayView_ when the class that
1273 // matched the alleged InputIterator template argument turned out to be one of
1274 // the integral types in which case this should match the assign(n, fillValue)
1275 // signature.
1276 template <class IntegralType>
1277 void avAssignDispatch(IntegralType n, IntegralType v, TrueType isIntegralType,
1278  const char*)
1279 { assign(size_type(n), value_type(v)); }
1280 
1281 // This is the assign() implementation for ArrayView_ when the class that
1282 // matched the alleged InputIterator template argument is NOT an integral type
1283 // and may very well be an iterator.
1284 template <class InputIterator>
1285 void avAssignDispatch(const InputIterator& first, const InputIterator& last1,
1286  FalseType isIntegralType, const char* methodName)
1287 { avAssignIteratorDispatch(first, last1,
1288  typename std::iterator_traits<InputIterator>::iterator_category(),
1289  methodName); }
1290 
1291 // This is the assign() implementation for a plain input_iterator
1292 // (i.e., not a forward, bidirectional, or random access iterator). These
1293 // have the unfortunate property that we can't count the elements in advance.
1294 // Here we're going to complain if there aren't enough; but will simply stop
1295 // when we get size() elements and not insist that the input stream reached
1296 // the supplied last1 iterator. Semantics is elementwise assignment.
1297 template <class InputIterator>
1298 void avAssignIteratorDispatch(const InputIterator& first,
1299  const InputIterator& last1,
1300  std::input_iterator_tag,
1301  const char* methodName)
1302 {
1303  T* p = begin();
1304  InputIterator src = first;
1305  while (src != last1 && p != end())
1306  *p++ = *src++; // call T's assignment operator
1307 
1308  // p now points just after the last element that was copied.
1309  const size_type nCopied = size_type(p - begin());
1310  SimTK_ERRCHK2_ALWAYS(nCopied == size(), methodName,
1311  "The supplied input_iterator provided only %llu elements but this"
1312  " ArrayView has a fixed size of %llu elements.",
1313  this->ull(nCopied), ullSize());
1314 
1315  // We don't care if there are still more input elements available.
1316 }
1317 
1318 // This is the assign() implementation that works for forward and bidirectional
1319 // iterators, but is not used for random_access_iterators. Here we'll count
1320 // the elements as we copy them and complain at the end if there were too
1321 // few or too many.
1322 template <class ForwardIterator>
1323 void avAssignIteratorDispatch(const ForwardIterator& first,
1324  const ForwardIterator& last1,
1325  std::forward_iterator_tag,
1326  const char* methodName)
1327 {
1328  T* p = begin();
1329  ForwardIterator src = first;
1330  while (src != last1 && p != end())
1331  *p++ = *src++; // call T's assignment operator
1332 
1333  // p now points just after the last element that was copied.
1334  const size_type nCopied = size_type(p - begin());
1335  SimTK_ERRCHK2_ALWAYS(nCopied == size(), methodName,
1336  "The supplied forward_ or bidirectional_iterator source range provided"
1337  " only %llu elements but this ArrayView has a fixed size of"
1338  " %llu elements.", this->ull(nCopied), ullSize());
1339 
1340  // Make sure we ran out of source elements.
1341  SimTK_ERRCHK1_ALWAYS(src == last1, methodName,
1342  "The supplied forward_ or bidirectional_iterator source range"
1343  " contained too many elements; this ArrayView has a fixed size of"
1344  " %llu elements.", ullSize());
1345 }
1346 
1347 // This is the assign() implementation that works for random_access_iterators
1348 // including ordinary pointers. Here we check the number of elements in advance
1349 // and complain if the source and destination aren't the same size. The
1350 // copying loop can be done faster in this case.
1351 template <class RandomAccessIterator>
1352 void avAssignIteratorDispatch(const RandomAccessIterator& first,
1353  const RandomAccessIterator& last1,
1354  std::random_access_iterator_tag,
1355  const char* methodName)
1356 {
1357  SimTK_ERRCHK2_ALWAYS(this->isSameSize(last1-first), methodName,
1358  "Assignment to an ArrayView is permitted only if the source"
1359  " is the same size. Here the source had %llu element(s) but the"
1360  " ArrayView has a fixed size of %llu.",
1361  this->ull(last1-first), this->ull(size()));
1362 
1363  SimTK_ERRCHK_ALWAYS(!this->overlapsWithData(first,last1), methodName,
1364  "Source range can't overlap with the destination data.");
1365 
1366  T* p = begin();
1367  RandomAccessIterator src = first;
1368  while (p != end())
1369  *p++ = *src++; // call T's assignment operator
1370 }
1371 
1372 
1373 //------------------------------------------------------------------------------
1374 // The following private methods are protected methods in the ArrayViewConst_
1375 // base class, so they should not need repeating here. However, we explicitly
1376 // forward to the base methods to avoid gcc errors. The gcc complaint
1377 // is due to their not depending on any template parameters; the "this->"
1378 // apparently fixes that problem.
1379 
1380 packed_size_type psize() const
1381 { return this->CBase::psize(); }
1382 packed_size_type pallocated() const
1383 { return this->CBase::pallocated(); }
1384 
1385 // This just cast sizes to unsigned long long so that we can do comparisons
1386 // without getting warnings.
1387 unsigned long long ullSize() const
1388 { return this->CBase::ullSize(); }
1389 unsigned long long ullCapacity() const
1390 { return this->CBase::ullCapacity(); }
1391 unsigned long long ullMaxSize() const
1392 { return this->CBase::ullMaxSize(); }
1393 // This is the index type name and is handy for error messages to explain
1394 // why some size was too big.
1395 const char* indexName() const {return this->CBase::indexName();}
1396 };
1397 
1398 
1399 
1400 
1401 
1402 //==============================================================================
1403 // CLASS Array_
1404 //==============================================================================
1507 template <class T, class X> class Array_ : public ArrayView_<T,X> {
1508  typedef ArrayView_<T,X> Base;
1509  typedef ArrayViewConst_<T,X> CBase;
1510 public:
1511 
1512 
1513 //------------------------------------------------------------------------------
1519 // Doxygen picks up individual descriptions from the base class.
1520 /*{*/
1521 typedef T value_type;
1522 typedef X index_type;
1523 typedef T* pointer;
1524 typedef const T* const_pointer;
1525 typedef T& reference;
1526 typedef const T& const_reference;
1527 typedef T* iterator;
1528 typedef const T* const_iterator;
1529 typedef std::reverse_iterator<iterator> reverse_iterator;
1530 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
1533 typedef typename ArrayIndexPackType<size_type>::packed_size_type
1535 /*}*/
1536 
1537 //------------------------------------------------------------------------------
1544 /*{*/
1545 
1547 Array_() : Base() {}
1548 
1553 explicit Array_(size_type n) : Base() {
1554  SimTK_SIZECHECK(n, max_size(), "Array_<T>::ctor(n)");
1555  allocateNoConstruct(n);
1556  defaultConstruct(data(), data()+n);
1557  setSize(n);
1558 }
1559 
1563 Array_(size_type n, const T& initVal) : Base() {
1564  SimTK_SIZECHECK(n, max_size(), "Array_<T>::ctor(n,T)");
1565  setSize(n);
1566  allocateNoConstruct(size());
1567  fillConstruct(begin(), cend(), initVal);
1568 }
1584 template <class InputIter>
1585 Array_(const InputIter& first, const InputIter& last1) : Base() {
1586  ctorDispatch(first,last1,typename IsIntegralType<InputIter>::Result());
1587 }
1588 
1594 template <class T2>
1595 Array_(const T2* first, const T2* last1) : Base() {
1596  SimTK_ERRCHK((first&&last1)||(first==last1), "Array_<T>(first,last1)",
1597  "Pointers must be non-null unless they are both null.");
1598  SimTK_ERRCHK3(this->isSizeOK(last1-first), "Array_<T>(first,last1)",
1599  "Source has %llu elements but this array is limited to %llu"
1600  " elements by its index type %s.",
1601  this->ull(last1-first), ullMaxSize(), indexName());
1602 
1603  setSize(size_type(last1-first));
1604  allocateNoConstruct(size());
1605  copyConstruct(begin(), cend(), first);
1606 }
1607 
1612 template <class T2>
1613 explicit Array_(const std::vector<T2>& v) : Base() {
1614  if (v.empty()) return;
1615 
1616  SimTK_ERRCHK3(this->isSizeOK(v.size()), "Array_<T>::ctor(std::vector<T2>)",
1617  "The source std::vector's size %llu is too big for this array which"
1618  " is limited to %llu elements by its index type %s.",
1619  this->ull(v.size()), ullMaxSize(), indexName());
1620 
1621  // Call the above constructor, making sure to use pointers into the
1622  // vector's data rather than the iterators begin() and end() in case
1623  // they are different types.
1624  new (this) Array_(&v.front(), (&v.back())+1);
1625 }
1626 
1631 Array_(const Array_& src) : Base() {
1632  setSize(src.size());
1633  allocateNoConstruct(size());
1634  copyConstruct(begin(), cend(), src.data());
1635 }
1636 
1643 template <class T2, class X2>
1644 Array_(const Array_<T2,X2>& src) : Base() {
1645  new (this) Array_(src.begin(), src.cend()); // see above
1646 }
1647 
1677 Array_(T* first, const T* last1, const DontCopy&) : Base(first,last1) {}
1678 
1706 template <class A>
1707 Array_(std::vector<T,A>& v, const DontCopy&) : Base(v) {}
1708 
1713  deallocate();
1714 }
1715 
1725  if (allocated()) { // owner with non-zero allocation
1726  clear(); // each element is destructed; size()=0; allocated() unchanged
1727  deallocateNoDestruct(); // free data(); allocated()=0
1728  }
1729  this->Base::disconnect(); // clear the handle
1730  return *this;
1731 }
1732 
1736 //------------------------------------------------------------------------------
1771 
1789 void assign(size_type n, const T& fillValue) {
1790  SimTK_ERRCHK3(this->isSizeOK(n), "Array_<T>::assign(n,value)",
1791  "Requested size %llu is too big for this array which is limited"
1792  " to %llu elements by its index type %s.",
1793  this->ull(n), ullMaxSize(), indexName());
1794 
1795  SimTK_ERRCHK2(isOwner() || n==size(), "Array_<T>::assign(n,value)",
1796  "Requested size %llu is not allowed because this is a non-owner"
1797  " array of fixed size %llu.", this->ull(n), this->ull(size()));
1798 
1799  if (!isOwner())
1800  this->Base::fill(fillValue);
1801  else {
1802  clear(); // all elements destructed; allocation unchanged
1803  reallocateIfAdvisable(n); // change size if too small or too big
1804  fillConstruct(data(), cdata()+n, fillValue);
1805  setSize(n);
1806  }
1807 }
1808 
1823 void fill(const T& fillValue) {this->Base::fill(fillValue);}
1824 
1825 
1847 template <class T2>
1848 void assign(const T2* first, const T2* last1) {
1849  const char* methodName = "Array_<T>::assign(T2* first, T2* last1)";
1850  SimTK_ERRCHK((first&&last1)||(first==last1), methodName,
1851  "Pointers must be non-null unless they are both null.");
1852  SimTK_ERRCHK(!this->overlapsWithData(first,last1), methodName,
1853  "Source range can't overlap the current array contents.");
1854  // Pointers are random access iterators.
1855  assignIteratorDispatch(first,last1,std::random_access_iterator_tag(),
1856  methodName);
1857 }
1858 
1859 
1895 template <class Iter>
1896 void assign(const Iter& first, const Iter& last1) {
1897  assignDispatch(first,last1,typename IsIntegralType<Iter>::Result(),
1898  "Array_<T>::assign(Iter first, Iter last1)");
1899 }
1900 
1906 Array_& operator=(const Array_& src) {
1907  if (this != &src)
1908  assignIteratorDispatch(src.begin(), src.end(),
1909  std::random_access_iterator_tag(),
1910  "Array_<T>::operator=(Array_<T>)");
1911  return *this;
1912 }
1913 
1919 template <class T2, class X2>
1921  assignIteratorDispatch(src.begin(), src.end(),
1922  std::random_access_iterator_tag(),
1923  "Array_<T>::operator=(Array_<T2,X2>)");
1924  return *this;
1925 }
1926 
1927 
1932 template <class T2, class A>
1933 Array_& operator=(const std::vector<T2,A>& src) {
1934  assignIteratorDispatch(src.begin(), src.end(),
1935  std::random_access_iterator_tag(),
1936  "Array_<T>::operator=(std::vector)");
1937  return *this;
1938 }
1939 
1946 void swap(Array_& other) {
1947  T* const pTmp=data(); setData(other.data()); other.setData(pTmp);
1948  size_type nTmp=size(); setSize(other.size()); other.setSize(nTmp);
1949  nTmp=allocated(); setAllocated(other.allocated()); other.setAllocated(nTmp);
1950 }
1951 
1957 Array_& adoptData(T* newData, size_type dataSize,
1958  size_type dataCapacity)
1959 {
1960  SimTK_SIZECHECK(dataCapacity, max_size(), "Array_<T>::adoptData()");
1961  SimTK_ERRCHK2(dataSize <= dataCapacity, "Array_<T>::adoptData()",
1962  "Specified data size %llu was greater than the specified data"
1963  " capacity of %llu.", this->ull(dataSize), this->ull(dataCapacity));
1964  SimTK_ERRCHK(newData || dataCapacity==0, "Array_<T>::adoptData()",
1965  "A null data pointer is allowed only if the size and capacity are"
1966  " specified as zero.");
1967  SimTK_ERRCHK(!this->overlapsWithData(newData, newData+dataSize),
1968  "Array_<T>::adoptData()",
1969  "The new data can't overlap with the old data.");
1970 
1971  deallocate();
1972  setData(newData);
1973  setSize(dataSize);
1974  setAllocated(dataCapacity);
1975  return *this;
1976 }
1979 Array_& adoptData(T* newData, size_type dataSize)
1980 { return adoptData(newData, dataSize, dataSize); }
1981 
1982 
1996 Array_& shareData(T* newData, size_type dataSize) {
1997  SimTK_SIZECHECK(dataSize, max_size(), "Array_<T>::shareData()");
1998  SimTK_ERRCHK(newData || dataSize==0, "Array_<T>::shareData()",
1999  "A null data pointer is allowed only if the size is zero.");
2000  SimTK_ERRCHK(!this->overlapsWithData(newData, newData+dataSize),
2001  "Array_<T>::shareData()",
2002  "The new data can't overlap with the old data.");
2003 
2004  deallocate();
2005  setData(newData);
2006  setSize(dataSize);
2007  setAllocated(0); // indicates shared data
2008  return *this;
2009 }
2010 
2013 Array_& shareData(T* first, const T* last1) {
2014  SimTK_ERRCHK3(this->isSizeOK(last1-first), "Array_<T>::shareData(first,last1)",
2015  "Requested size %llu is too big for this array which is limited"
2016  " to %llu elements by its index type %s.",
2017  this->ull(last1-first), ullMaxSize(), indexName());
2018  return shareData(first, size_type(last1-first));
2019 }
2020 
2024 //------------------------------------------------------------------------------
2030 
2031 // Note: these have to be explicitly forwarded to the base class methods
2032 // in order to keep gcc from complaining. Note that the "this->" is
2033 // apparently necessary in order to permit delayed definition of templatized
2034 // methods.
2035 
2037 SimTK_FORCE_INLINE size_type size() const {return this->CBase::size();}
2039 size_type max_size() const {return this->CBase::max_size();}
2042 bool empty() const {return this->CBase::empty();}
2047 size_type capacity() const {return this->CBase::capacity();}
2048 
2053 void resize(size_type n) {
2054  if (n == size()) return;
2055 
2056  SimTK_ERRCHK2(isOwner(), "Array_<T>::resize(n)",
2057  "Requested size change to %llu is not allowed because this is a"
2058  " non-owner array of fixed size %llu.", this->ull(n), this->ull(size()));
2059 
2060  if (n < size()) {
2061  erase(data()+n, cend());
2062  return;
2063  }
2064  // n > size()
2065  reserve(n);
2066  defaultConstruct(data()+size(), cdata()+n); // data() has changed
2067  setSize(n);
2068 }
2069 
2074 void resize(size_type n, const T& initVal) {
2075  if (n == size()) return;
2076 
2077  SimTK_ERRCHK2(isOwner(), "Array_<T>::resize(n,value)",
2078  "Requested size change to %llu is not allowed because this is a"
2079  " non-owner array of fixed size %llu.", this->ull(n), this->ull(size()));
2080 
2081  if (n < size()) {
2082  erase(data()+n, cend());
2083  return;
2084  }
2085  // n > size()
2086  reserve(n);
2087  fillConstruct(data()+size(), cdata()+n, initVal);
2088  setSize(n);
2089 }
2090 
2097 void reserve(size_type n) {
2098  if (capacity() >= n)
2099  return;
2100 
2101  SimTK_ERRCHK2(isOwner(), "Array_<T>::reserve()",
2102  "Requested capacity change to %llu is not allowed because this is a"
2103  " non-owner array of fixed size %llu.", this->ull(n), this->ull(size()));
2104 
2105  T* newData = allocN(n); // no construction yet
2106  copyConstructThenDestructSource(newData, newData+size(), data());
2107  freeN(data());
2108  setData(newData);
2109  setAllocated(n);
2110 }
2111 
2133  // Allow 25% slop, but note that if size()==0 this will always reallocate
2134  // unless capacity is already zero.
2135  if (capacity() - size()/4 <= size()) // avoid overflow if size() near max
2136  return;
2137  T* newData = allocN(size());
2138  copyConstructThenDestructSource(newData, newData+size(), data());
2139  deallocateNoDestruct(); // data()=0, allocated()=0, size() unchanged
2140  setData(newData);
2141  setAllocated(size());
2142 }
2143 
2147 size_type allocated() const
2148 { return this->CBase::allocated(); }
2154 bool isOwner() const {return this->CBase::isOwner();}
2158 //------------------------------------------------------------------------------
2167 
2172 SimTK_FORCE_INLINE const T* cbegin() const {return this->CBase::cbegin();}
2174 SimTK_FORCE_INLINE const T* begin() const {return this->CBase::cbegin();}
2179 SimTK_FORCE_INLINE T* begin() {return this->Base::begin();}
2180 
2185 SimTK_FORCE_INLINE const T* cend() const {return this->CBase::cend();}
2187 SimTK_FORCE_INLINE const T* end() const {return this->CBase::cend();}
2192 SimTK_FORCE_INLINE T* end() {return this->Base::end();}
2193 
2196 const_reverse_iterator crbegin() const
2197 { return this->CBase::crbegin(); }
2199 const_reverse_iterator rbegin() const
2200 { return this->CBase::crbegin(); }
2203 reverse_iterator rbegin() {return this->Base::rbegin();}
2204 
2208 const_reverse_iterator crend() const
2209 { return this->CBase::crend(); }
2211 const_reverse_iterator rend() const
2212 { return this->CBase::crend(); }
2216 reverse_iterator rend() {return this->Base::rend();}
2217 
2224 SimTK_FORCE_INLINE const T* cdata() const {return this->CBase::cdata();}
2227 SimTK_FORCE_INLINE const T* data() const {return this->CBase::cdata();}
2231 SimTK_FORCE_INLINE T* data() {return this->Base::data();}
2239 
2246 SimTK_FORCE_INLINE const T& operator[](index_type i) const
2247 { return this->CBase::operator[](i); }
2248 
2256 SimTK_FORCE_INLINE T& operator[](index_type i) {return this->Base::operator[](i);}
2257 
2262 const T& at(index_type i) const {return this->CBase::at(i);}
2263 
2268 T& at(index_type i) {return const_cast<T&>(this->Base::at(i));}
2269 
2272 SimTK_FORCE_INLINE const T& getElt(index_type i) const
2273 { return this->CBase::getElt(i); }
2276 SimTK_FORCE_INLINE T& updElt(index_type i) {return this->Base::updElt(i);}
2277 
2283 SimTK_FORCE_INLINE const T& front() const {return this->CBase::front();}
2284 
2290 SimTK_FORCE_INLINE T& front() {return const_cast<T&>(this->Base::front());}
2291 
2297 SimTK_FORCE_INLINE const T& back() const {return this->CBase::back();}
2298 
2304 SimTK_FORCE_INLINE T& back() {return const_cast<T&>(this->Base::back());}
2305 
2308 ArrayViewConst_<T,X> operator()(index_type index, size_type length) const
2309 { return CBase::operator()(index,length); }
2312 ArrayViewConst_<T,X> getSubArray(index_type index, size_type length) const
2313 { return CBase::getSubArray(index,length); }
2314 
2317 ArrayView_<T,X> operator()(index_type index, size_type length)
2318 { return Base::operator()(index,length); }
2321 ArrayView_<T,X> updSubArray(index_type index, size_type length)
2322 { return Base::updSubArray(index,length); }
2326 //------------------------------------------------------------------------------
2332 
2359 void push_back(const T& value) {
2360  if (pallocated() == psize())
2361  growAtEnd(1,"Array_<T>::push_back(value)");
2362  copyConstruct(end(), value);
2363  incrSize();
2364 }
2365 
2379 void push_back() {
2380  if (pallocated() == psize())
2381  growAtEnd(1,"Array_<T>::push_back()");
2382  defaultConstruct(end());
2383  incrSize();
2384 }
2385 
2402  if (pallocated() == psize())
2403  growAtEnd(1,"Array_<T>::raw_push_back()");
2404  T* const p = end();
2405  incrSize();
2406  return p;
2407 }
2408 
2411 void pop_back() {
2412  SimTK_ERRCHK(!empty(), "Array_<T>::pop_back()", "Array was empty.");
2413  destruct(&back());
2414  decrSize();
2415 }
2416 
2434 T* erase(T* first, const T* last1) {
2435  SimTK_ERRCHK(begin() <= first && first <= last1 && last1 <= end(),
2436  "Array<T>::erase(first,last1)", "Pointers out of range or out of order.");
2437 
2438  const size_type nErased = size_type(last1-first);
2439  SimTK_ERRCHK(isOwner() || nErased==0, "Array<T>::erase(first,last1)",
2440  "No elements can be erased from a non-owner array.");
2441 
2442  if (nErased) {
2443  destruct(first, last1); // Destruct the elements we're erasing.
2444  moveElementsDown(first+nErased, nErased); // Compress followers into the gap.
2445  setSize(size()-nErased);
2446  }
2447  return first;
2448 }
2449 
2469 T* erase(T* p) {
2470  SimTK_ERRCHK(begin() <= p && p < end(),
2471  "Array<T>::erase(p)", "Pointer must point to a valid element.");
2472  SimTK_ERRCHK(isOwner(), "Array<T>::erase(p)",
2473  "No elements can be erased from a non-owner array.");
2474 
2475  destruct(p); // Destruct the element we're erasing.
2476  moveElementsDown(p+1, 1); // Compress followers into the gap.
2477  decrSize();
2478  return p;
2479 }
2480 
2481 
2502 T* eraseFast(T* p) {
2503  SimTK_ERRCHK(begin() <= p && p < end(),
2504  "Array<T>::eraseFast(p)", "Pointer must point to a valid element.");
2505  SimTK_ERRCHK(isOwner(), "Array<T>::eraseFast(p)",
2506  "No elements can be erased from a non-owner array.");
2507 
2508  destruct(p);
2509  if (p+1 != end())
2510  moveOneElement(p, &back());
2511  decrSize();
2512  return p;
2513 }
2514 
2522 void clear() {
2523  SimTK_ERRCHK(isOwner() || empty(), "Array_<T>::clear()",
2524  "clear() is not allowed for a non-owner array.");
2525  destruct(begin(), end());
2526  setSize(0);
2527 }
2528 
2529 
2556 T* insert(T* p, size_type n, const T& value) {
2557  T* const gap = insertGapAt(p, n, "Array<T>::insert(p,n,value)");
2558  // Copy construct into the inserted elements and note the size change.
2559  fillConstruct(gap, gap+n, value);
2560  setSize(size()+n);
2561  return gap;
2562 }
2563 
2568 T* insert(T* p, const T& value) {
2569  T* const gap = insertGapAt(p, 1, "Array<T>::insert(p,value)");
2570  // Copy construct into the inserted element and note the size change.
2571  copyConstruct(gap, value);
2572  incrSize();
2573  return gap;
2574 }
2575 
2605 template <class T2>
2606 T* insert(T* p, const T2* first, const T2* last1) {
2607  const char* methodName = "Array_<T>::insert(T* p, T2* first, T2* last1)";
2608  SimTK_ERRCHK((first&&last1) || (first==last1), methodName,
2609  "One of first or last1 was null; either both or neither must be null.");
2610  SimTK_ERRCHK(!this->overlapsWithData(first,last1), methodName,
2611  "Source range can't overlap with the current array contents.");
2612  // Pointers are random access iterators.
2613  return insertIteratorDispatch(p, first, last1,
2614  std::random_access_iterator_tag(),
2615  methodName);
2616 }
2617 
2620 template <class Iter>
2621 T* insert(T* p, const Iter& first, const Iter& last1) {
2622  return insertDispatch(p, first, last1,
2623  typename IsIntegralType<Iter>::Result(),
2624  "Array_<T>::insert(T* p, Iter first, Iter last1)");
2625 }
2630 //------------------------------------------------------------------------------
2631  private:
2632 //------------------------------------------------------------------------------
2633 
2634 
2635 // This method is used when we have already decided we need to make room for
2636 // some new elements by reallocation, by creating a gap somewhere within the
2637 // existing data. We'll issue an error message if this would violate the
2638 // max_size restriction (we can afford to do that even in a Release build since
2639 // we don't expect to grow very often). Otherwise we'll allocate some more space
2640 // and copy construct the existing elements into the new space, leaving a gap
2641 // where indicated. Note that this method does not change the current size but
2642 // does change the capacity.
2643 //
2644 // The gapPos must point within the existing data with null OK if the array
2645 // itself is null, and end() being OK any time although you should use the
2646 // more specialized growAtEnd() method if you know that's what's happening.
2647 //
2648 // Don't call this with a gapSz of zero.
2649 T* growWithGap(T* gapPos, size_type gapSz, const char* methodName) {
2650  assert(gapSz > 0); // <= 0 is a bug, not a user error
2651 
2652  // Note that gapPos may be null if begin() and end() are also.
2653  SimTK_ERRCHK(begin() <= gapPos && gapPos <= end(), methodName,
2654  "Given insertion point is not valid for this array.");
2655 
2656  // Get some new space of a reasonable size.
2657  setAllocated(calcNewCapacityForGrowthBy(gapSz, methodName));
2658  T* newData = allocN(allocated());
2659 
2660  // How many elements will be before the gap?
2661  const size_type nBefore = (size_type)(gapPos-begin());
2662 
2663  // Locate the gap in the new space allocation.
2664  T* newGap = newData + nBefore;
2665  T* newGapEnd = newGap + gapSz; // one past the last element in the gap
2666 
2667  // Copy elements before insertion point; destruct source as we go.
2668  copyConstructThenDestructSource(newData, newGap, data());
2669  // Copy/destruct elements at and after insertion pt; leave gapSz gap.
2670  copyConstructThenDestructSource(newGapEnd, newData+size(), gapPos);
2671 
2672  // Throw away the old data and switch to the new.
2673  freeN(data()); setData(newData);
2674  return newGap;
2675 }
2676 
2677 // Same as growWithGap(end(), n, methodName); see above.
2678 void growAtEnd(size_type n, const char* methodName) {
2679  assert(n > 0); // <= 0 is a bug, not a user error
2680  // Get some new space of a reasonable size.
2681  setAllocated(calcNewCapacityForGrowthBy(n, methodName));
2682  T* newData = allocN(allocated());
2683  // Copy all the elements; destruct source as we go.
2684  copyConstructThenDestructSource(newData, newData+size(), data());
2685  // Throw away the old data and switch to the new.
2686  freeN(data()); setData(newData);
2687 }
2688 
2689 // This method determines how much we should increase the array's capacity
2690 // when asked to insert n elements, due to an insertion or push_back. We will
2691 // generally allocate more new space than requested, in anticipation of
2692 // further insertions. This has to be based on the current size so that only
2693 // log(n) reallocations are performed to insert n elements one at a time. Our
2694 // policy here is to at least double the capacity unless that would exceed
2695 // max_size(). There is also a minimum amount of allocation we'll do if the
2696 // current size is zero or very small.
2697 size_type calcNewCapacityForGrowthBy(size_type n, const char* methodName) const {
2698  SimTK_ERRCHK3_ALWAYS(isGrowthOK(n), methodName,
2699  "Can't grow this Array by %llu element(s) because it would"
2700  " then exceed the max_size of %llu set by its index type %s.",
2701  (unsigned long long)n, ullMaxSize(), indexName());
2702 
2703  // At this point we know that capacity()+n <= max_size().
2704  const size_type mustHave = capacity() + n;
2705 
2706  // Be careful not to overflow size_type as you could if you
2707  // double capacity() rather than halving max_size().
2708  const size_type wantToHave = capacity() <= max_size()/2
2709  ? 2*capacity()
2710  : max_size();
2711 
2712  const size_type newCapacity = std::max(std::max(mustHave,wantToHave),
2713  minAlloc());
2714  return newCapacity;
2715 }
2716 
2717 // Insert an unconstructed gap of size n beginning at position p. The return
2718 // value is a pointer to the first element in the gap. It will be p if no
2719 // reallocation occurred, otherwise it will be pointing into the new data.
2720 // On return size() will be unchanged although allocated() may be bigger.
2721 T* insertGapAt(T* p, size_type n, const char* methodName) {
2722  // Note that p may be null if begin() and end() are also.
2723  SimTK_ERRCHK(begin() <= p && p <= end(), methodName,
2724  "Given insertion point is not valid for this Array.");
2725 
2726  if (n==0) return p; // nothing to do
2727 
2728  SimTK_ERRCHK_ALWAYS(isOwner(), methodName,
2729  "No elements can be inserted into a non-owner array.");
2730 
2731  // Determine the number of elements before the insertion point and
2732  // the number at or afterwards (those must be moved up by one slot).
2733  const size_type before = (size_type)(p-begin()), after = (size_type)(end()-p);
2734 
2735  // Grow the container if necessary. Note that if we have to grow we
2736  // can create the gap at the same time we copy the old elements over
2737  // to the new space.
2738  if (capacity() >= size()+n) {
2739  moveElementsUp(p, n); // leave a gap at p
2740  } else { // need to grow
2741  setAllocated(calcNewCapacityForGrowthBy(n, methodName));
2742  T* newdata = allocN(allocated());
2743  // Copy the elements before the insertion point, and destroy source.
2744  copyConstructThenDestructSource(newdata, newdata+before, data());
2745  // Copy the elements at and after the insertion point, leaving a gap
2746  // of n elements.
2747  copyConstructThenDestructSource(newdata+before+n,
2748  newdata+before+n+after,
2749  p); // i.e., pData+before
2750  p = newdata + before; // points into newdata now
2751  freeN(data());
2752  setData(newdata);
2753  }
2754 
2755  return p;
2756 }
2757 
2758 //------------------------------------------------------------------------------
2759 // CTOR DISPATCH
2760 // This is the constructor implementation for when the class that matches
2761 // the alleged InputIterator type turns out to be one of the integral types
2762 // in which case this should be the ctor(n, initValue) constructor.
2763 template <class IntegralType> void
2764 ctorDispatch(IntegralType n, IntegralType v, TrueType isIntegralType) {
2765  new(this) Array_(size_type(n), value_type(v));
2766 }
2767 
2768 // This is the constructor implementation for when the class that matches
2769 // the alleged InputIterator type is NOT an integral type and may very well
2770 // be an iterator. In that case we split into iterators for which we can
2771 // determine the number of elements in advance (forward, bidirectional,
2772 // random access) and input iterators, for which we can't. Note: iterator
2773 // types are arranged hierarchically random->bi->forward->input with each
2774 // deriving from the one on its right, so the forward iterator tag also
2775 // matches bi and random.
2776 template <class InputIterator> void
2777 ctorDispatch(const InputIterator& first, const InputIterator& last1,
2778  FalseType isIntegralType)
2779 { ctorIteratorDispatch(first, last1,
2780  typename std::iterator_traits<InputIterator>::iterator_category()); }
2781 
2782 // This is the slow generic ctor implementation for any iterator that can't
2783 // make it up to forward_iterator capability (that is, an input_iterator).
2784 // The issue here is that we can't advance the iterator to count the number
2785 // of elements before allocating because input_iterators are consumed when
2786 // reference so we can't go back to look. That means we may have to reallocate
2787 // memory log n times as we "push back" these elements onto the array.
2788 template <class InputIterator> void
2789 ctorIteratorDispatch(const InputIterator& first, const InputIterator& last1,
2790  std::input_iterator_tag)
2791 {
2792  InputIterator src = first;
2793  while (src != last1) {
2794  // We can afford to check this always since we are probably doing I/O.
2795  // Throwing an exception in a constructor is tricky, though -- this
2796  // won't go through the Array_ destructor although it will call the
2797  // Base (ArrayView_) destructor. Since we have already allocated
2798  // some space, we must call deallocate() manually.
2799  if (size() == max_size()) {
2800  deallocate();
2801  SimTK_ERRCHK2_ALWAYS(!"too many elements",
2802  "Array_::ctor(InputIterator first, InputIterator last1)",
2803  "There were still source elements available when the array"
2804  " reached its maximum size of %llu as determined by its index"
2805  " type %s.", ullMaxSize(), indexName());
2806  }
2807  push_back(*src++);
2808  }
2809 }
2810 
2811 // This is the faster constructor implementation for iterator types for which
2812 // we can calculate the number of elements in advance. This will be optimal
2813 // for a random access iterator since we can count in constant time, but for
2814 // forward or bidirectional we'll have to advance n times to count and then
2815 // go back again to do the copy constructions.
2816 template <class ForwardIterator> void
2817 ctorIteratorDispatch(const ForwardIterator& first, const ForwardIterator& last1,
2818  std::forward_iterator_tag)
2819 {
2820  typedef typename std::iterator_traits<ForwardIterator>::difference_type
2822  // iterDistance() is constant time for random access iterators, but
2823  // O(last1-first) for forward and bidirectional since it has to increment
2824  // to count how far apart they are.
2825  const difference_type nInput = this->iterDistance(first,last1);
2826 
2827  SimTK_ERRCHK(nInput >= 0,
2828  "Array_(ForwardIterator first, ForwardIterator last1)",
2829  "Iterators were out of order.");
2830 
2831  SimTK_ERRCHK3(this->isSizeOK(nInput),
2832  "Array_(ForwardIterator first, ForwardIterator last1)",
2833  "Source has %llu elements but this array is limited to %llu"
2834  " elements by its index type %s.",
2835  this->ull(nInput), ullMaxSize(), indexName());
2836 
2837  const size_type n = size_type(nInput);
2838  setSize(n);
2839  allocateNoConstruct(n);
2840  copyConstruct(data(), data()+n, first);
2841 }
2842 
2843 //------------------------------------------------------------------------------
2844 // INSERT DISPATCH
2845 // This is the insert() implementation for when the class that matches
2846 // the alleged InputIterator type turns out to be one of the integral types
2847 // in which case this should be the insert(p, n, initValue) constructor.
2848 template <class IntegralType>
2849 T* insertDispatch(T* p, IntegralType n, IntegralType v,
2850  TrueType isIntegralType, const char*)
2851 { return insert(p, size_type(n), value_type(v)); }
2852 
2853 // This is the insert() implementation for when the class that matches
2854 // the alleged InputIterator type is NOT an integral type and may very well
2855 // be an iterator. See ctorDispatch() above for more information.
2856 template <class InputIterator>
2857 T* insertDispatch(T* p, const InputIterator& first, const InputIterator& last1,
2858  FalseType isIntegralType, const char* methodName)
2859 { return insertIteratorDispatch(p, first, last1,
2860  typename std::iterator_traits<InputIterator>::iterator_category(),
2861  methodName); }
2862 
2863 // This is the slow generic insert implementation for any iterator that can't
2864 // make it up to forward_iterator capability (that is, an input_iterator).
2865 // See ctorIteratorDispatch() above for more information.
2866 template <class InputIterator>
2867 T* insertIteratorDispatch(T* p, InputIterator first, InputIterator last1,
2868  std::input_iterator_tag, const char* methodName)
2869 {
2870  size_type nInserted = 0;
2871  while (first != last1) {
2872  // We can afford to check this always since we are probably doing I/O.
2873  SimTK_ERRCHK2_ALWAYS(size() < max_size(), methodName,
2874  "There were still source elements available when the array"
2875  " reached its maximum size of %llu as determined by its index"
2876  " type %s.", ullMaxSize(), indexName());
2877  p = insert(p, *first++); // p may now point to reallocated memory
2878  ++p; ++nInserted;
2879  }
2880  // p now points just after the last inserted element; subtract the
2881  // number inserted to get a pointer to the first inserted element.
2882  return p-nInserted;
2883 }
2884 
2885 // This is the faster constructor implementation for iterator types for which
2886 // we can calculate the number of elements in advance. This will be optimal
2887 // for a random access iterator since we can count in constant time, but for
2888 // forward or bidirectional we'll have to advance n times to count and then
2889 // go back again to do the copy constructions.
2890 template <class ForwardIterator>
2891 T* insertIteratorDispatch(T* p, const ForwardIterator& first,
2892  const ForwardIterator& last1,
2893  std::forward_iterator_tag,
2894  const char* methodName)
2895 {
2896  typedef typename std::iterator_traits<ForwardIterator>::difference_type
2898  // iterDistance() is constant time for random access iterators, but
2899  // O(last1-first) for forward and bidirectional since it has to increment
2900  // to count how far apart they are.
2901  const difference_type nInput = this->iterDistance(first,last1);
2902 
2903  SimTK_ERRCHK(nInput >= 0, methodName, "Iterators were out of order.");
2904 
2905  SimTK_ERRCHK3(isGrowthOK(nInput), methodName,
2906  "Source has %llu elements which would make this array exceed the %llu"
2907  " elements allowed by its index type %s.",
2908  this->ull(nInput), ullMaxSize(), indexName());
2909 
2910  const size_type n = size_type(nInput);
2911  p = insertGapAt(p, n, methodName);
2912  copyConstruct(p, p+n, first);
2913  setSize(size()+n);
2914  return p;
2915 }
2916 
2917 //------------------------------------------------------------------------------
2918 // ASSIGN DISPATCH
2919 // This is the assign() implementation for when the class that matches
2920 // the alleged InputIterator type turns out to be one of the integral types
2921 // in which case this should be the assign(n, initValue) constructor.
2922 template <class IntegralType>
2923 void assignDispatch(IntegralType n, IntegralType v, TrueType isIntegralType,
2924  const char* methodName)
2925 { assign(size_type(n), value_type(v)); }
2926 
2927 // This is the assign() implementation for when the class that matches
2928 // the alleged InputIterator type is NOT an integral type and may very well
2929 // be an iterator. See ctorDispatch() above for more information.
2930 template <class InputIterator>
2931 void assignDispatch(const InputIterator& first, const InputIterator& last1,
2932  FalseType isIntegralType, const char* methodName)
2933 { assignIteratorDispatch(first, last1,
2934  typename std::iterator_traits<InputIterator>::iterator_category(),
2935  methodName); }
2936 
2937 // This is the slow generic implementation for a plain input_iterator
2938 // (i.e., not a forward, bidirectional, or random access iterator). These
2939 // have the unfortunate property that we can't count the elements in advance.
2940 template <class InputIterator>
2941 void assignIteratorDispatch(const InputIterator& first,
2942  const InputIterator& last1,
2943  std::input_iterator_tag,
2944  const char* methodName)
2945 {
2946  // TODO: should probably allow this and just blow up when the size()+1st
2947  // element is seen.
2948  SimTK_ERRCHK_ALWAYS(isOwner(), methodName,
2949  "Assignment to a non-owner array can only be done from a source"
2950  " designated with forward iterators or pointers because we"
2951  " must be able to verify that the source and destination sizes"
2952  " are the same.");
2953 
2954  clear(); // TODO: change space allocation here?
2955  InputIterator src = first;
2956  while (src != last1) {
2957  // We can afford to check this always since we are probably doing I/O.
2958  SimTK_ERRCHK2_ALWAYS(size() < max_size(), methodName,
2959  "There were still source elements available when the array"
2960  " reached its maximum size of %llu as determined by its index"
2961  " type %s.", ullMaxSize(), indexName());
2962 
2963  push_back(*src++);
2964  }
2965 }
2966 
2967 // This is the faster implementation that works for forward, bidirectional,
2968 // and random access iterators including ordinary pointers. We can check here that the
2969 // iterators are in the right order, and that the source is not too big to
2970 // fit in this array. Null pointer checks should be done prior to calling,
2971 // however, since iterators in general aren't pointers.
2972 template <class ForwardIterator>
2973 void assignIteratorDispatch(const ForwardIterator& first,
2974  const ForwardIterator& last1,
2975  std::forward_iterator_tag,
2976  const char* methodName)
2977 {
2978  typedef typename std::iterator_traits<ForwardIterator>::difference_type
2979  IterDiffType;
2980  // iterDistance() is constant time for random access iterators, but
2981  // O(last1-first) for forward and bidirectional since it has to increment
2982  // to count how far apart they are.
2983  const IterDiffType nInput = this->iterDistance(first,last1);
2984 
2985  SimTK_ERRCHK(nInput >= 0, methodName, "Iterators were out of order.");
2986 
2987  SimTK_ERRCHK3(this->isSizeOK(nInput), methodName,
2988  "Source has %llu elements but this Array is limited to %llu"
2989  " elements by its index type %s.",
2990  this->ull(nInput), ullMaxSize(), indexName());
2991 
2992  const size_type n = size_type(nInput);
2993  if (isOwner()) {
2994  // This is an owner Array; assignment is considered deallocation
2995  // followed by copy construction.
2996 
2997  clear(); // all elements destructed; allocation unchanged
2998  reallocateIfAdvisable(n); // change allocation if too small or too big
2999  copyConstruct(data(), cdata()+n, first);
3000  setSize(n);
3001  } else {
3002  // This is a non-owner Array. Assignment can occur only if the
3003  // source is the same size as the array, and the semantics are of
3004  // repeated assignment using T::operator=() not destruction followed
3005  // by copy construction.
3006  SimTK_ERRCHK2(n == size(), methodName,
3007  "Source has %llu elements which does not match the size %llu"
3008  " of the non-owner array it is being assigned into.",
3009  this->ull(n), ullSize());
3010 
3011  T* p = begin();
3012  ForwardIterator src = first;
3013  while (src != last1)
3014  *p++ = *src++; // call T's assignment operator
3015  }
3016 }
3017 
3018 // We are going to put a total of n elements into the Array (probably
3019 // because of an assignment or resize) and we want the space allocation
3020 // to be reasonable. That means of course that the allocation must be
3021 // *at least* n, but we also don't want it to be too big. Our policy
3022 // here is that if it is currently less than twice what we need we
3023 // won't reallocate, otherwise we'll shrink the space. When changing
3024 // the size to zero or something very small we'll treat the Array as
3025 // though its current size is minAlloc, meaning we won't reallocate
3026 // if the existing space is less than twice minAlloc.
3027 // nAllocated will be set appropriately; size() is not touched here.
3028 // No constructors or destructors are called.
3029 void reallocateIfAdvisable(size_type n) {
3030  if (allocated() < n || allocated()/2 > std::max(minAlloc(), n))
3031  reallocateNoDestructOrConstruct(n);
3032 }
3033 
3034 
3035 void allocateNoConstruct(size_type n)
3036 { setData(allocN(n)); setAllocated(n); } // size() left unchanged
3037 void deallocateNoDestruct()
3038 { freeN(data()); setData(0); setAllocated(0); } // size() left unchanged
3039 void reallocateNoDestructOrConstruct(size_type n)
3040 { deallocateNoDestruct(); allocateNoConstruct(n); }
3041 
3042 // This sets the smallest allocation we'll do when growing.
3043 size_type minAlloc() const
3044 { return std::min(max_size(), size_type(4)); }
3045 
3046 // Allocate without construction. Returns a null pointer if asked
3047 // to allocate 0 elements. In Debug mode we'll fill memory with
3048 // all 1's as a bug catcher.
3049 static T* allocN(size_type n) {
3050  if (n==0) return 0;
3051  unsigned char* newdata = new unsigned char[n * sizeof(T)];
3052  #ifndef NDEBUG
3053  unsigned char* b=newdata;
3054  const unsigned char* e=newdata+(n*sizeof(T));
3055  while (b != e) *b++ = 0xff;
3056  #endif
3057  return reinterpret_cast<T*>(newdata);
3058 }
3059 
3060 // Free memory without calling T's destructor. Nothing happens if passed
3061 // a null pointer.
3062 static void freeN(T* p) {
3063  delete[] reinterpret_cast<char*>(p);
3064 }
3065 
3066 // default construct one element
3067 static void defaultConstruct(T* p) {new(p) T();}
3068 // default construct range [b,e)
3069 static void defaultConstruct(T* b, const T* e)
3070 { while (b!=e) new(b++) T(); }
3071 
3072 // copy construct range [b,e) with repeats of a given value
3073 static void fillConstruct(T* b, const T* e, const T& v)
3074 { while(b!=e) new(b++) T(v); }
3075 
3076 // copy construct one element from a given value
3077 static void copyConstruct(T* p, const T& v) {new(p) T(v);}
3078 // copy construct range [b,e) from sequence of source values
3079 static void copyConstruct(T* b, const T* e, T* src)
3080 { while(b!=e) new(b++) T(*src++); }
3081 // Templatized copy construct will work if the source elements are
3082 // assignment compatible with the destination elements.
3083 template <class InputIterator>
3084 static void copyConstruct(T* b, const T* e, InputIterator src)
3085 { while(b!=e) new(b++) T(*src++); }
3086 
3087 // Copy construct range [b,e] from sequence of source values and
3088 // destruct the source after it is copied. It's better to alternate
3089 // copying and destructing than to do this in two passes since we
3090 // will already have touched the memory.
3091 static void copyConstructThenDestructSource(T* b, const T* e, T* src)
3092 { while(b!=e) {new(b++) T(*src); src++->~T();} }
3093 
3094 // We have an element at from that we would like to move into the currently-
3095 // unconstructed slot at to. Both from and to are expected to be pointing to
3096 // elements within the currently allocated space. From's slot will be left
3097 // unconstructed.
3098 void moveOneElement(T* to, T* from) {
3099  assert(data() <= to && to < data()+allocated());
3100  assert(data() <= from && from < data()+allocated());
3101  copyConstruct(to, *from);
3102  destruct(from);
3103 }
3104 
3105 
3106 // Move elements from p to end() down by n>0 places to fill an unconstructed
3107 // gap beginning at p-n. Any leftover space at the end will be unconstructed.
3108 void moveElementsDown(T* p, size_type n) {
3109  assert(n > 0);
3110  for (; p != end(); ++p)
3111  moveOneElement(p-n,p);
3112 }
3113 
3114 // Move elements from p to end() up by n>0 places to make an unconstructed gap
3115 // at [p,p+n). Note that this has to be done backwards so that we don't
3116 // write on any elements until after they've been copied.
3117 void moveElementsUp(T* p, size_type n) {
3118  assert(n > 0);
3119  T* src = end(); // points one past source element (begin()-1 not allowed)
3120  while (src != p) {
3121  --src; // now points to source
3122  moveOneElement(src+n, src);;
3123  }
3124 }
3125 
3126 // destruct one element
3127 static void destruct(T* p) {p->~T();}
3128 // destruct range [b,e)
3129 static void destruct(T* b, const T* e)
3130 { while(b!=e) b++->~T(); }
3131 
3132 // Check that growing this array by n elements wouldn't cause it to exceed
3133 // its allowable maximum size.
3134 template <class S>
3135 bool isGrowthOK(S n) const
3136 { return this->isSizeOK(ullCapacity() + this->ull(n)); }
3137 
3138 // The following private methods are protected methods in the ArrayView base
3139 // class, so they should not need repeating here. Howevr, we explicitly
3140 // forward to the Base methods to avoid gcc errors. The gcc complaint
3141 // is due to their not depending on any template parameters; the "this->"
3142 // apparently fixes that problem.
3143 
3144 // These provide direct access to the data members.
3145 packed_size_type psize() const {return this->CBase::psize();}
3146 packed_size_type pallocated() const {return this->CBase::pallocated();}
3147 
3148 void setData(const T* p) {this->CBase::setData(p);}
3149 void setSize(size_type n) {this->CBase::setSize(n);}
3150 void incrSize() {this->CBase::incrSize();}
3151 void decrSize() {this->CBase::decrSize();}
3152 void setAllocated(size_type n) {this->CBase::setAllocated(n);}
3153 // This just cast sizes to unsigned long long so that we can do comparisons
3154 // without getting warnings.
3155 unsigned long long ullSize() const
3156 { return this->CBase::ullSize(); }
3157 unsigned long long ullCapacity() const
3158 { return this->CBase::ullCapacity(); }
3159 unsigned long long ullMaxSize() const
3160 { return this->CBase::ullMaxSize(); }
3161 // This is the index type name and is handy for error messages to explain
3162 // why some size was too big.
3163 const char* indexName() const {return this->CBase::indexName();}
3164 };
3165 
3166 
3167 // This "private" static method is used to implement ArrayView's
3168 // fillArrayViewFromStream() and Array's readArrayFromStream() namespace-scope
3169 // static methods, which are in turn used to implement ArrayView's and
3170 // Array's stream extraction operators ">>". This method has to be in the
3171 // header file so that we don't need to pass streams through the API, but it
3172 // is not intended for use by users and has no Doxygen presence, unlike
3173 // fillArrayFromStream() and readArrayFromStream() and (more commonly)
3174 // the extraction operators.
3175 template <class T, class X> static inline
3176 std::istream& readArrayFromStreamHelper
3177  (std::istream& in, bool isFixedSize, Array_<T,X>& out)
3178 {
3179  // If already failed, bad, or eof, set failed bit and return without
3180  // touching the Array.
3181  if (!in.good()) {in.setstate(std::ios::failbit); return in;}
3182 
3183  // If the passed-in Array isn't an owner, then we have to treat it as
3184  // a fixed size ArrayView regardless of the setting of the isFixedSize
3185  // argument.
3186  if (!out.isOwner())
3187  isFixedSize = true; // might be overriding the argument here
3188 
3189  // numRequired will be ignored unless isFixedSize==true.
3190  const typename Array_<T,X>::size_type
3191  numRequired = isFixedSize ? out.size() : 0;
3192 
3193  if (!isFixedSize)
3194  out.clear(); // We're going to replace the entire contents of the Array.
3195 
3196  // Skip initial whitespace. If that results in eof this may be a successful
3197  // read of a 0-length, unbracketed Array. That is OK for either a
3198  // variable-length Array or a fixed-length ArrayView of length zero.
3199  std::ws(in); if (in.fail()) return in;
3200  if (in.eof()) {
3201  if (isFixedSize && numRequired != 0)
3202  in.setstate(std::ios_base::failbit); // zero elements not OK
3203  return in;
3204  }
3205 
3206  // Here the stream is good and the next character is non-white.
3207  assert(in.good());
3208 
3209  // Use this for raw i/o (peeks and gets).
3210  typename std::iostream::int_type ch;
3211 
3212  #ifndef NDEBUG // avoid unused variable warnings in Release
3213  const typename std::iostream::int_type EOFch =
3214  std::iostream::traits_type::eof();
3215  #endif
3216 
3217  // Now see if the sequence is bare or surrounded by (), [], or {}.
3218  bool lookForCloser = true;
3219  char openBracket, closeBracket;
3220  ch = in.peek(); if (in.fail()) return in;
3221  assert(ch != EOFch); // we already checked above
3222 
3223  openBracket = (char)ch;
3224  if (openBracket=='(') {in.get(); closeBracket = ')';}
3225  else if (openBracket=='[') {in.get(); closeBracket = ']';}
3226  else if (openBracket=='{') {in.get(); closeBracket = '}';}
3227  else lookForCloser = false;
3228 
3229  // If lookForCloser is true, then closeBracket contains the terminating
3230  // delimiter, otherwise we're not going to quit until eof.
3231 
3232  // Eat whitespace after the opening bracket to see what's next.
3233  if (in.good()) std::ws(in);
3234 
3235  // If we're at eof now it must be because the open bracket was the
3236  // last non-white character in the stream, which is an error.
3237  if (!in.good()) {
3238  if (in.eof()) {
3239  assert(lookForCloser); // or we haven't read anything that could eof
3240  in.setstate(std::ios::failbit);
3241  }
3242  return in;
3243  }
3244 
3245  // istream is good and next character is non-white; ready to read first
3246  // value or terminator.
3247 
3248  // We need to figure out whether the elements are space- or comma-
3249  // separated and then insist on consistency.
3250  bool commaOK = true, commaRequired = false;
3251  bool terminatorSeen = false;
3252  X nextIndex(0);
3253  while (true) {
3254  char c;
3255 
3256  // Here at the top of this loop, we have already successfully read
3257  // n=nextIndex values of type T. For fixed-size reads, it might be
3258  // the case that n==numRequired already, but we still may need to
3259  // look for a closing bracket before we can declare victory.
3260  // The stream is good() (not at eof) but it might be the case that
3261  // there is nothing but white space left; we don't know yet because
3262  // if we have satisfied the fixed-size count and are not expecting
3263  // a terminator then we should quit without absorbing the trailing
3264  // white space.
3265  assert(in.good());
3266 
3267  // Look for closing bracket before trying to read value.
3268  if (lookForCloser) {
3269  // Eat white space to find the closing bracket.
3270  std::ws(in); if (!in.good()) break; // eof?
3271  ch = in.peek(); assert(ch != EOFch);
3272  if (!in.good()) break;
3273  c = (char)ch;
3274  if (c == closeBracket) {
3275  in.get(); // absorb the closing bracket
3276  terminatorSeen = true;
3277  break;
3278  }
3279  // next char not a closing bracket; fall through
3280  }
3281 
3282  // We didn't look or didn't find a closing bracket. The istream is good
3283  // but we might be looking at white space.
3284 
3285  // If we already got all the elements we want, break for final checks.
3286  if (isFixedSize && (nextIndex == numRequired))
3287  break; // that's a full count.
3288 
3289  // Look for comma before value, except the first time.
3290  if (commaOK && nextIndex != 0) {
3291  // Eat white space to find the comma.
3292  std::ws(in); if (!in.good()) break; // eof?
3293  ch = in.peek(); assert(ch != EOFch);
3294  if (!in.good()) break;
3295  c = (char)ch;
3296  if (c == ',') {
3297  in.get(); // absorb comma
3298  commaRequired = true; // all commas from now on
3299  } else { // next char not a comma
3300  if (commaRequired) // bad, e.g.: v1, v2, v3 v4
3301  { in.setstate(std::ios::failbit); break; }
3302  else commaOK = false; // saw: v1 v2 (no commas now)
3303  }
3304  if (!in.good()) break; // might be eof
3305  }
3306 
3307  // No closing bracket yet; don't have enough elements; skipped comma
3308  // if any; istream is good; might be looking at white space.
3309  assert(in.good());
3310 
3311  // Now read in an element of type T.
3312  // The extractor T::operator>>() will ignore leading white space.
3313  if (!isFixedSize)
3314  out.push_back(); // grow by one (default consructed)
3315  in >> out[nextIndex]; if (in.fail()) break;
3316  ++nextIndex;
3317 
3318  if (!in.good()) break; // might be eof
3319  }
3320 
3321  // We will get here under a number of circumstances:
3322  // - the fail bit is set in the istream, or
3323  // - we reached eof
3324  // - we saw a closing brace
3325  // - we got all the elements we wanted (for a fixed-size read)
3326  // Note that it is possible that we consumed everything except some
3327  // trailing white space (meaning we're not technically at eof), but
3328  // for consistency with built-in operator>>()'s we won't try to absorb
3329  // that trailing white space.
3330 
3331  if (!in.fail()) {
3332  if (lookForCloser && !terminatorSeen)
3333  in.setstate(std::ios::failbit); // missing terminator
3334 
3335  if (isFixedSize && nextIndex != numRequired)
3336  in.setstate(std::ios::failbit); // wrong number of values
3337  }
3338 
3339  return in;
3340 }
3341 
3342 
3343 
3344 //------------------------------------------------------------------------------
3345 // RELATED GLOBAL OPERATORS
3346 //------------------------------------------------------------------------------
3347 // These are logically part of the Array_<T,X> class but are not actually
3348 // class members; that is, they are in the SimTK namespace.
3349 
3350 // Some of the serialization methods could have been member functions but
3351 // then an attempt to explicitly instantiate the whole Array_<T> class for
3352 // some type T would fail if T did not support the requisite I/O operations
3353 // even if those operations were never used. This came up when Chris Bruns was
3354 // trying to wrap Array objects for Python, which requires explicit
3355 // instantiation.
3356 
3364 
3368 template <class T, class X> inline void
3369 writeUnformatted(std::ostream& o, const Array_<T,X>& v) {
3370  for (X i(0); i < v.size(); ++i) {
3371  if (i != 0) o << " ";
3372  writeUnformatted(o, v[i]);
3373  }
3374 }
3375 
3376 
3380 template <class T, class X> inline void
3381 writeFormatted(std::ostream& o, const Array_<T,X>& v) {
3382  o << '(';
3383  for (X i(0); i < v.size(); ++i) {
3384  if (i != 0) o << ',';
3385  writeFormatted(o, v[i]);
3386  }
3387  o << ')';
3388 }
3389 
3396 template <class T, class X> inline
3397 std::ostream&
3398 operator<<(std::ostream& o,
3399  const ArrayViewConst_<T,X>& a)
3400 {
3401  o << '(';
3402  if (!a.empty()) {
3403  o << a.front();
3404  for (const T* p = a.begin()+1; p != a.end(); ++p)
3405  o << ',' << *p;
3406  }
3407  return o << ')';
3408 }
3409 
3410 
3414 template <class T, class X> inline bool
3415 readUnformatted(std::istream& in, Array_<T,X>& v) {
3416  v.clear();
3417  T element;
3418  std::ws(in); // Make sure we're at eof if stream is all whitespace.
3419  while (!in.eof() && readUnformatted(in, element))
3420  v.push_back(element);
3421  return !in.fail(); // eof is expected and ok
3422 }
3423 
3428 template <class T, class X> inline bool
3429 readUnformatted(std::istream& in, ArrayView_<T,X>& v) {
3430  for (X i(0); i < v.size(); ++i)
3431  if (!readUnformatted(in, v[i])) return false;
3432  return true;
3433 }
3434 
3435 
3441 template <class T, class X> inline bool
3442 readFormatted(std::istream& in, Array_<T,X>& v) {
3443  return !readArrayFromStream(in,v).fail();
3444 }
3445 
3451 template <class T, class X> inline bool
3452 readFormatted(std::istream& in, ArrayView_<T,X>& v) {
3453  return !fillArrayViewFromStream(in,v).fail();
3454 }
3455 
3485 template <class T, class X> static inline
3486 std::istream& readArrayFromStream(std::istream& in, Array_<T,X>& out)
3487 { return readArrayFromStreamHelper<T,X>(in, false /*variable sizez*/, out); }
3488 
3489 
3490 
3515 template <class T, class X> static inline
3516 std::istream& fillArrayFromStream(std::istream& in, Array_<T,X>& out)
3517 { return readArrayFromStreamHelper<T,X>(in, true /*fixed size*/, out); }
3518 
3523 template <class T, class X> static inline
3524 std::istream& fillArrayViewFromStream(std::istream& in, ArrayView_<T,X>& out)
3525 { return readArrayFromStreamHelper<T,X>(in, true /*fixed size*/, out); }
3526 
3527 
3528 
3529 
3539 template <class T, class X> inline
3540 std::istream& operator>>(std::istream& in, Array_<T,X>& out)
3541 { return readArrayFromStream<T,X>(in, out); }
3542 
3550 template <class T, class X> inline
3551 std::istream& operator>>(std::istream& in, ArrayView_<T,X>& out)
3552 { return fillArrayViewFromStream<T,X>(in, out); }
3553 
3563 
3566 template <class T1, class X1, class T2, class X2> inline bool
3568  // Avoid warnings in size comparison by using common type.
3569  const ptrdiff_t sz1 = a1.end()-a1.begin();
3570  const ptrdiff_t sz2 = a2.end()-a2.begin();
3571  if (sz1 != sz2) return false;
3572  const T1* p1 = a1.begin();
3573  const T2* p2 = a2.begin();
3574  while (p1 != a1.end())
3575  if (!(*p1++ == *p2++)) return false;
3576  return true;
3577 }
3580 template <class T1, class X1, class T2, class X2> inline bool
3582 { return !(a1 == a2); }
3583 
3588 template <class T1, class X1, class T2, class X2> inline bool
3589 operator<(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2) {
3590  const T1* p1 = a1.begin();
3591  const T2* p2 = a2.begin();
3592  while (p1 != a1.end() && p2 != a2.end()) {
3593  if (!(*p1 == *p2))
3594  return *p1 < *p2; // otherwise p1 > p2
3595  ++p1; ++p2;
3596  }
3597  // All elements were equal until one or both arrays ran out of elements.
3598  // a1 is less than a2 only if a1 ran out and a2 didn't.
3599  return p1 == a1.end() && p2 != a2.end();
3600 }
3603 template <class T1, class X1, class T2, class X2> inline bool
3605 { return !(a1 < a2); }
3609 template <class T1, class X1, class T2, class X2> inline bool
3611 { return a2 < a1; }
3614 template <class T1, class X1, class T2, class X2> inline bool
3615 operator<=(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2)
3616 { return !(a1 > a2); }
3617 
3621 template <class T1, class X1, class T2, class A2> inline bool
3622 operator==(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3623 { return a1 == ArrayViewConst_<T2,size_t>(v2); }
3624 
3628 template <class T1, class A1, class T2, class X2> inline bool
3629 operator==(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3630 { return a2 == v1; }
3631 
3634 template <class T1, class X1, class T2, class A2> inline bool
3635 operator!=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3636 { return !(a1 == v2); }
3639 template <class T1, class A1, class T2, class X2> inline bool
3640 operator!=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3641 { return !(a2 == v1); }
3642 
3648 template <class T1, class X1, class T2, class A2> inline bool
3649 operator<(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3650 { return a1 < ArrayViewConst_<T2,size_t>(v2); }
3651 
3657 template <class T1, class A1, class T2, class X2> inline bool
3658 operator<(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3659 { return ArrayViewConst_<T1,size_t>(v1) < a2; }
3660 
3663 template <class T1, class X1, class T2, class A2> inline bool
3664 operator>=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3665 { return !(a1 < v2); }
3668 template <class T1, class A1, class T2, class X2> inline bool
3669 operator>=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3670 { return !(v1 < a2); }
3671 
3675 template <class T1, class X1, class T2, class A2> inline bool
3676 operator>(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3677 { return v2 < a1; }
3681 template <class T1, class A1, class T2, class X2> inline bool
3682 operator>(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3683 { return a2 < v1; }
3684 
3687 template <class T1, class X1, class T2, class A2> inline bool
3688 operator<=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3689 { return !(a1 > v2); }
3692 template <class T1, class A1, class T2, class X2> inline bool
3693 operator<=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3694 { return !(v1 > a2); }
3695 
3698 } // namespace SimTK
3699 
3700 namespace std {
3704 template <class T, class X> inline void
3706  a1.swap(a2);
3707 }
3708 
3709 } // namespace std
3710 
3711 #endif // SimTK_SimTKCOMMON_ARRAY_H_
static size_type max_size()
Definition: Array.h:238
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 t...
Definition: Array.h:3369
T & back()
Return a writable reference to the last element in this array, which must not be empty.
Definition: Array.h:1128
This Array_ helper class is the base class for Array_, extending ArrayViewConst_ to add the ability t...
Definition: Array.h:49
bool readUnformatted(std::istream &in, ArrayView_< T, X > &v)
Specialization of readUnformatted() for fixed-length ArrayView_<T,X>; reads whitespace-separated toke...
Definition: Array.h:3429
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 ...
Definition: Array.h:1920
unsigned char size_type
Definition: Array.h:219
const T & back() const
Return a const reference to the last element in this array, which must not be empty.
Definition: Array.h:2297
ArrayView_ & operator=(const ArrayViewConst_< T2, X2 > &src)
Assignment from any other array object is allowed as long as the number of elements matches and the t...
Definition: Array.h:928
const T * data() const
The const version of the data() method is identical to cdata().
Definition: Array.h:2227
ArrayIndexTraits< X >::difference_type difference_type
A signed integral type that can represent the difference between any two legitimate index values for ...
Definition: Array.h:351
const T * end() const
The const version of end() is the same as cend().
Definition: Array.h:643
static size_type max_size()
Definition: Array.h:198
static size_type max_size()
Definition: Array.h:210
const T & front() const
Return a const reference to the first element in this array, which must not be empty.
Definition: Array.h:1107
bool empty() const
Definition: Array.h:1258
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...
Definition: Array.h:1194
#define SimTK_ERRCHK2_ALWAYS(cond, whereChecked, fmt, a1, a2)
Definition: ExceptionMacros.h:289
void fill(const T &fillValue)
Assign all current elements of the array to the same fillValue.
Definition: Array.h:1823
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.
Definition: Array.h:3676
T value_type
The type of object stored in this container.
Definition: Array.h:328
#define SimTK_SIZECHECK(sz, maxsz, where)
Definition: ExceptionMacros.h:146
ArrayView_()
Default constructor allocates no heap space and is very fast.
Definition: Array.h:872
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 eleme...
Definition: Array.h:3622
const T & at(index_type i) const
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:1085
unsigned long long size_type
Definition: Array.h:227
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: Array.h:856
~ArrayViewConst_()
The destructor just disconnects the array view handle from its data; see disconnect() for more inform...
Definition: Array.h:491
const T * cdata() const
Return a const pointer to the first element of the array, or possibly (but not necessarily) null (0) ...
Definition: Array.h:2224
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.
Definition: Array.h:1644
const T & front() const
Return a const reference to the first element in this array, which must not be empty.
Definition: Array.h:2283
T * iterator
A writable iterator for this container (same as pointer here).
Definition: Array.h:340
const_reverse_iterator crend() const
Return the past-the-end reverse iterator that tests equal to a reverse iterator that has been increme...
Definition: Array.h:652
const_reverse_iterator rbegin() const
The const version of rbegin() is the same as crbegin().
Definition: Array.h:2199
const T & at(index_type i) const
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:555
signed char difference_type
Definition: Array.h:209
This is a special type used for causing invocation of a particular constructor or method overload tha...
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:628
#define SimTK_ERRCHK1_ALWAYS(cond, whereChecked, fmt, a1)
Definition: ExceptionMacros.h:285
void assign(size_type n, const T &fillValue)
Set this array to be n copies of the supplied fillValue.
Definition: Array.h:1789
size_type allocated() const
Return the amount of heap space owned by this array; this is the same as capacity() for owner arrays ...
Definition: Array.h:2147
std::reverse_iterator< iterator > reverse_iterator
Definition: Array.h:1529
T & reference
Definition: Array.h:1525
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 po...
Definition: Array.h:1848
size_type size() const
Return the current number of elements stored in this array.
Definition: Array.h:506
bool readUnformatted(std::istream &in, T &v)
The default implementation of readUnformatted<T> reads in the next whitespace-separated token and the...
Definition: Serialize.h:188
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition: Assembler.h:37
bool readUnformatted(std::istream &in, Array_< T, X > &v)
Specialization of readUnformatted() for variable-length Array_<T,X>; continues reading whitespace-sep...
Definition: Array.h:3415
long size_type
Definition: Array.h:153
ArrayViewConst_(const std::vector< T, A > &src)
Construct a ArrayViewConst_<T> by referencing (sharing) the data in a const std::vector<T>, without copying the data; this is also an implicit conversion.
Definition: Array.h:454
const T & operator[](index_type i) const
Select an element by its index, returning a const reference.
Definition: Array.h:547
void resize(size_type n)
Change the size of this Array, preserving all the elements that will still fit, and default construct...
Definition: Array.h:2053
int difference_type
Definition: Array.h:121
T * iterator
Definition: Array.h:853
Array_(size_type n)
Construct an array containing n default-constructed elements.
Definition: Array.h:1553
char size_type
Definition: Array.h:208
This templatized type is used by the Array_<T,X> classes to obtain the information they need to use t...
Definition: Array.h:47
const T * begin() const
The const version of begin() is the same as cbegin().
Definition: Array.h:641
bool isOwner() const
Does this array own the data to which it refers? If not, it can&#39;t be resized, and the destructor will...
Definition: Array.h:528
const T & const_reference
A const value_type reference.
Definition: Array.h:338
static size_type max_size()
Definition: Array.h:221
T * pointer
A writable pointer to a value_type.
Definition: Array.h:332
const_reverse_iterator rend() const
The const version of rend() is the same as crend().
Definition: Array.h:657
const T * end() const
The const version of end() is the same as cend().
Definition: Array.h:1196
Array_(const InputIter &first, const InputIter &last1)
Construct an Array_<T> from a range [first,last1) of values identified by a pair of iterators...
Definition: Array.h:1585
size_type size() const
Definition: Array.h:1256
bool operator!=(const std::vector< T1, A1 > &v1, const ArrayViewConst_< T2, X2 > &a2)
The not equal operator is implemented using the equal operator.
Definition: Array.h:3640
unsigned long size_type
Definition: Array.h:140
long long difference_type
Definition: Array.h:237
T * pointer
Definition: Array.h:1523
reverse_iterator rbegin()
Return a writable reverse iterator pointing to the last element in the array or rend() if the array i...
Definition: Array.h:2203
STL namespace.
T value_type
Definition: Array.h:847
ELEM min(const VectorBase< ELEM > &v)
Definition: VectorMath.h:178
T & at(index_type i)
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:2268
const_reverse_iterator rend() const
The const version of rend() is the same as crend().
Definition: Array.h:1220
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.
Definition: Array.h:3610
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 valu...
Definition: Array.h:2568
ArrayIndexPackType< size_type >::packed_size_type packed_size_type
Definition: Array.h:860
#define SimTK_ASSERT(cond, msg)
Definition: ExceptionMacros.h:374
unsigned size_type
Definition: Array.h:120
void pop_back()
Remove the last element from this array, which must not be empty.
Definition: Array.h:2411
ArrayIndexTraits< X >::size_type size_type
Definition: Array.h:1531
T * raw_push_back()
This dangerous method increases the Array&#39;s size by one element at the end but doesn&#39;t perform any co...
Definition: Array.h:2401
ArrayView_(std::vector< T, A > &v)
Construct to reference memory owned by a writable std::vector.
Definition: Array.h:882
#define SimTK_ERRCHK3(cond, whereChecked, fmt, a1, a2, a3)
Definition: ExceptionMacros.h:330
size_type size() const
Return the current number of elements stored in this array.
Definition: Array.h:2037
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 doe...
Definition: Array.h:1613
ArrayIndexTraits< X >::size_type size_type
Definition: Array.h:857
ArrayViewConst_(const ArrayViewConst_ &src)
Copy constructor is shallow; the constructed const array object will be referencing the original sour...
Definition: Array.h:377
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 a...
Definition: Array.h:1957
~Array_()
The destructor performs a deallocate() operation which may result in element destruction and freeing ...
Definition: Array.h:1712
short difference_type
Definition: Array.h:186
T * begin()
Return a writable pointer to the first element of this array if any, otherwise end().
Definition: Array.h:1188
ArrayView_ updSubArray(index_type index, size_type length)
Same as non-const operator()(index,length); exists to provide non-operator access to that functionali...
Definition: Array.h:1162
static size_type max_size()
Definition: Array.h:229
ArrayViewConst_()
Default constructor allocates no heap space and is very fast.
Definition: Array.h:366
const T * end() const
The const version of end() is the same as cend().
Definition: Array.h:2187
T & reference
A writable value_type reference.
Definition: Array.h:336
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.
Definition: Array.h:2172
const T * cdata() const
Return a const pointer to the first element of the array, or possibly (but not necessarily) null (0) ...
Definition: Array.h:1233
T * erase(T *first, const T *last1)
Erase elements in range [first,last1), packing in any later elements into the newly-available space a...
Definition: Array.h:2434
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 option...
Definition: Array.h:3486
T & operator[](index_type i)
Select an element by its index, returning a writable (lvalue) reference.
Definition: Array.h:1078
X index_type
Definition: Array.h:848
Array_ & operator=(const std::vector< T2, A > &src)
This is assignment from a source std::vector<T2>.
Definition: Array.h:1933
This file contains macros which are convenient to use for sprinkling error checking around liberally ...
ArrayView_ & operator=(const ArrayView_ &src)
Copy assignment; source must be the same size as this array.
Definition: Array.h:916
Array_(size_type n, const T &initVal)
Construct an array containing n elements each set to a copy of the given initial value.
Definition: Array.h:1563
bool isOwner() const
Does this array own the data to which it refers? If not, it can&#39;t be resized, and the destructor will...
Definition: Array.h:2154
This is a compile-time equivalent of "false", used in compile-time condition checking in templatized ...
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:636
Array_ & adoptData(T *newData, size_type dataSize)
A variant of adoptData() that assumes the capacity is the same as the current size.
Definition: Array.h:1979
T * erase(T *p)
Erase just one element, moving all subsequent elements down one slot and reducing the array&#39;s size by...
Definition: Array.h:2469
int difference_type
Definition: Array.h:128
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 functio...
Definition: Array.h:2312
const T * const_iterator
Definition: Array.h:854
size_type allocated() const
Return the amount of heap space owned by this array; this is the same as capacity() for owner arrays ...
Definition: Array.h:522
T & at(index_type i)
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:1091
static const char * name()
The default implementation of name() here returns the raw result from typeid(T).name() which will be ...
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:765
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: Array.h:1530
const T * cbegin() const
Return a const pointer to the first element of this array if any, otherwise end(), which may be null (0) in that case but does not have to be.
Definition: Array.h:1181
ArrayView_ & operator=(const T &fillValue)
Fill assignment – all elements are set to fillValue.
Definition: Array.h:961
const T * begin() const
The const version of begin() is the same as cbegin().
Definition: Array.h:2174
void push_back()
This is a non-standard version of push_back() that increases the size of the array by one default-con...
Definition: Array.h:2379
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable from
Definition: LICENSE.txt:39
static std::istream & fillArrayFromStream(std::istream &in, Array_< T, X > &out)
Read in a fixed number of elements from a stream into an Array.
Definition: Array.h:3516
reverse_iterator rbegin()
Return a writable reverse iterator pointing to the last element in the array or rend() if the array i...
Definition: Array.h:1212
const_reverse_iterator rend() const
The const version of rend() is the same as crend().
Definition: Array.h:2211
const_reverse_iterator rbegin() const
The const version of rbegin() is the same as crbegin().
Definition: Array.h:1208
static size_type max_size()
Definition: Array.h:176
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 ele...
Definition: Array.h:2556
ArrayIndexTraits< X >::difference_type difference_type
Definition: Array.h:1532
short difference_type
Definition: Array.h:175
void assign(const T2 *first, const T2 *last1)
Assign to this array to make it a copy of the elements in range [first,last1) given by ordinary point...
Definition: Array.h:1006
The SimTK::Array_<T> container class is a plug-compatible replacement for the C++ standard template l...
Definition: Array.h:50
T * end()
Return a writable pointer to what would be the element just after the last one in this array...
Definition: Array.h:1201
#define SimTK_ERRCHK_ALWAYS(cond, whereChecked, msg)
Definition: ExceptionMacros.h:281
ArrayIndexPackType< size_type >::packed_size_type packed_size_type
Definition: Array.h:1534
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...
Definition: Array.h:2185
ArrayIndexPackType< size_type >::packed_size_type packed_size_type
The integral type we actually use internally to store size_type values.
Definition: Array.h:354
const T * data() const
The const version of the data() method is identical to cdata().
Definition: Array.h:1236
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 c...
Definition: Array.h:1095
void disconnect()
Forward to base class disconnect() method – clears the handle without doing anything to the data...
Definition: Array.h:894
bool empty() const
Return true if there are no elements currently stored in this array.
Definition: Array.h:512
const T & operator[](index_type i) const
Select an element by its index, returning a const reference.
Definition: Array.h:2246
T & front()
Return a writable reference to the first element in this array, which must not be empty...
Definition: Array.h:1114
signed char difference_type
Definition: Array.h:197
#define SimTK_ERRCHK3_ALWAYS(cond, whereChecked, fmt, a1, a2, a3)
Definition: ExceptionMacros.h:293
long long size_type
Definition: Array.h:236
const T & const_reference
Definition: Array.h:852
ELEM max(const VectorBase< ELEM > &v)
Definition: VectorMath.h:251
const_reverse_iterator rbegin() const
The const version of rbegin() is the same as crbegin().
Definition: Array.h:655
std::reverse_iterator< iterator > reverse_iterator
Definition: Array.h:855
ArrayView_ & operator=(const Array_< T2, X2 > &src)
Assignment from any other array object is allowed as long as the number of elements matches and the t...
Definition: Array.h:947
T * data()
Return a writable pointer to the first allocated element of the array, or a null pointer if no space ...
Definition: Array.h:1240
static size_type max_size()
Definition: Array.h:166
const T * const_pointer
Definition: Array.h:1524
void assign(size_type n, const T &fillValue)
This is the same as fill() but has the usual std::vector signature for compatibility; it will only wo...
Definition: Array.h:978
const T * const_pointer
A const pointer to a value_type.
Definition: Array.h:334
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.
Definition: Array.h:3604
void reserve(size_type n)
Ensure that this array has enough allocated capacity to hold the indicated number of elements...
Definition: Array.h:2097
T value_type
Definition: Array.h:1521
ArrayViewConst_ getSubArray(index_type index, size_type length) const
Same as const form of operator()(index,length); exists to provide non-operator access to that functio...
Definition: Array.h:614
bool operator!=(const ArrayViewConst_< T1, X1 > &a1, const std::vector< T2, A2 > &v2)
The not equal operator is implemented using the equal operator.
Definition: Array.h:3635
const T & const_reference
Definition: Array.h:1526
static size_type max_size()
Definition: Array.h:155
long long difference_type
Definition: Array.h:228
ArrayIndexTraits< X >::difference_type difference_type
Definition: Array.h:858
unsigned char size_type
Definition: Array.h:185
bool isOwner() const
Definition: Array.h:1261
size_type max_size() const
Definition: Array.h:1257
#define SimTK_FORCE_INLINE
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:282
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 c...
Definition: Array.h:2272
std::ostream & operator<<(std::ostream &o, const ContactForce &f)
Definition: CompliantContactSubsystem.h:387
int size_type
Definition: Array.h:127
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.
Definition: Array.h:3682
unsigned short size_type
Definition: Array.h:164
std::reverse_iterator< iterator > reverse_iterator
A writable reverse iterator for this container.
Definition: Array.h:344
static size_type max_size()
Definition: Array.h:122
void swap(Array_ &other)
This is a specialized algorithm providing constant time exchange of data with another array that has ...
Definition: Array.h:1946
#define SimTK_INDEXCHECK_ALWAYS(ix, ub, where)
Definition: ExceptionMacros.h:106
void writeFormatted(std::ostream &o, const Array_< T, X > &v)
Specialize writeFormatted() for Array_<E,X> to delegate to element type E, with surrounding parenthes...
Definition: Array.h:3381
#define SimTK_ERRCHK(cond, whereChecked, msg)
Definition: ExceptionMacros.h:324
long difference_type
Definition: Array.h:141
gikDdMV wfaIJt A٩t1 JcA nr S q is3 ֧ VK C 9Z D q Fxn n T Y < ['jd< K JvTMH"sw>}o_o? z'z:mV$yng͖i۸J{ Ta*dE|lzbX@!^Ooi_=O}&ŲQUVWTsh!P_7DRAVfʿbOԹɫt0Y!|'x'óݥ:/ V[,}-B֞/܂;:;;Iޘ[nK4#-='Gf\lb41۩> Os7x f pZzB I g n
Definition: SimmathUserGuide.doc:2262
T * end()
Return a writable pointer to what would be the element just after the last one in this array...
Definition: Array.h:2192
#define SimTK_ERRCHK2(cond, whereChecked, fmt, a1, a2)
Definition: ExceptionMacros.h:328
This Array_ helper class is the base class for ArrayView_ which is the base class for Array_; here we...
Definition: Array.h:48
const_reverse_iterator crend() const
Return the past-the-end reverse iterator that tests equal to a reverse iterator that has been increme...
Definition: Array.h:1217
T & back()
Return a writable reference to the last element in this array, which must not be empty.
Definition: Array.h:2304
ArrayViewConst_ operator()(index_type index, size_type length) const
Select a contiguous subarray of the elements of this array and create another ArrayViewConst_ that re...
Definition: Array.h:600
Array_()
Default constructor allocates no heap space and is very fast.
Definition: Array.h:1547
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(...
Definition: Array.h:3705
const T & operator[](index_type i) const
Select an element by its index, returning a const reference.
Definition: Array.h:1068
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.
Definition: Array.h:1677
const_reverse_iterator crbegin() const
Return a const reverse iterator pointing to the last element in the array or crend() if the array is ...
Definition: Array.h:2196
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.
Definition: Array.h:3664
Mandatory first inclusion for any Simbody source or header file.
reverse_iterator rend()
Return a writable past-the-end reverse iterator that tests equal to a reverse iterator that has been ...
Definition: Array.h:2216
X index_type
Definition: Array.h:1522
const_reverse_iterator crbegin() const
Return a const reverse iterator pointing to the last element in the array or crend() if the array is ...
Definition: Array.h:647
Array_ & deallocate()
Empty this array of its contents, returning the array to its default-constructed, all-zero state...
Definition: Array.h:1724
This file contains definitions of templatized serialize-to-stream methods specialized for the built-i...
void clear()
Erase all the elements currently in this array without changing the capacity; equivalent to erase(beg...
Definition: Array.h:2522
const T * begin() const
The const version of begin() is the same as cbegin().
Definition: Array.h:1183
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...
Definition: Array.h:639
#define SimTK_INDEXCHECK(ix, ub, where)
Definition: ExceptionMacros.h:145
const_reverse_iterator crend() const
Return the past-the-end reverse iterator that tests equal to a reverse iterator that has been increme...
Definition: Array.h:2208
ArrayViewConst_(const T *first, const T *last1)
Construct an ArrayViewConst_<T> by referencing (sharing) a given range of const data [first...
Definition: Array.h:406
long difference_type
Definition: Array.h:154
X index_type
The index type (an extension).
Definition: Array.h:330
size_type allocated() const
Definition: Array.h:1260
T * iterator
Definition: Array.h:1527
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 ...
Definition: Array.h:3567
ArrayIndexTraits< X >::size_type size_type
An integral type suitable for all indices and sizes for this array.
Definition: Array.h:348
void assign(const Iter &first, const Iter &last1)
Assign to this array to make it a copy of the elements in range [first,last1) given by non-pointer it...
Definition: Array.h:1048
Array_(const Array_ &src)
Copy constructor allocates exactly as much memory as is in use in the source (not its capacity) and c...
Definition: Array.h:1631
signed char difference_type
Definition: Array.h:220
T & updElt(index_type i)
Same as the non-const form of operator[]; exists to provide a non-operator method for element access ...
Definition: Array.h:1099
const T * const_pointer
Definition: Array.h:850
std::istream & operator>>(std::istream &in, ArrayView_< T, X > &out)
Read a (fixed size n) ArrayView_<T> from a stream as a sequence of space- or comma-separated values o...
Definition: Array.h:3551
static size_type max_size()
Definition: Array.h:187
const T * const_iterator
Definition: Array.h:1528
X::difference_type difference_type
A signed integral type large enough to hold the full range of possible signed differences i-j between...
Definition: Array.h:111
bool operator!=(const ArrayViewConst_< T1, X1 > &a1, const ArrayViewConst_< T2, X2 > &a2)
The not equal operator is implemented using the equal operator.
Definition: Array.h:3581
T * begin()
Return a writable pointer to the first element of this array if any, otherwise end().
Definition: Array.h:2179
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.
Definition: Array.h:2621
T & reference
Definition: Array.h:851
const T & front() const
Return a const reference to the first element in this array, which must not be empty (we&#39;ll check in ...
Definition: Array.h:570
static size_type max_size()
Definition: Array.h:129
const T * cdata() const
Return a const pointer to the first element of the array, or possibly (but not necessarily) null (0) ...
Definition: Array.h:665
reverse_iterator rend()
Return a writable past-the-end reverse iterator that tests equal to a reverse iterator that has been ...
Definition: Array.h:1225
bool readFormatted(std::istream &in, ArrayView_< T, X > &v)
Specialization of readFormatted() for fixed-length ArrayView_<T,X>; uses fillArrayViewFromStream() to...
Definition: Array.h:3452
const T & at(index_type i) const
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:2262
const T * const_iterator
A const iterator for this container (same as const_pointer here).
Definition: Array.h:342
ArrayView_ & fill(const T &fillValue)
Assign the supplied fill value to each element of this array, using T&#39;s copy assignment operator for ...
Definition: Array.h:969
const T & back() const
Return a const reference to the last element in this array, which must not be empty (we&#39;ll check in a...
Definition: Array.h:578
T * eraseFast(T *p)
Be careful with this non-standard extension; it erases one element and then moves the last one in its...
Definition: Array.h:2502
void disconnect()
Disconnect this array handle from any data to which it refers, restoring it to the condition it would...
Definition: Array.h:482
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 functionali...
Definition: Array.h:2321
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 da...
Definition: Array.h:1707
size_type capacity() const
Definition: Array.h:1259
signed char size_type
Definition: Array.h:196
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 ...
Definition: Array.h:2074
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.
Definition: Array.h:3669
T & front()
Return a writable reference to the first element in this array, which must not be empty...
Definition: Array.h:2290
int difference_type
Definition: Array.h:165
ArrayView_ operator()(index_type index, size_type length)
Select a contiguous subarray of the elements of this array and create another ArrayView_ that refers ...
Definition: Array.h:1148
size_type capacity() const
Return the number of elements this array can currently hold without requiring reallocation.
Definition: Array.h:517
ArrayView_ & operator=(const ArrayView_< T2, X2 > &src)
Assignment from any other array object is allowed as long as the number of elements matches and the t...
Definition: Array.h:942
void shrink_to_fit()
Request that the capacity of this array be reduced to the minimum necessary to hold the number of ele...
Definition: Array.h:2132
Array_ & operator=(const Array_ &src)
Copy assignment operator destructs the current contents of this array and then makes it a copy of the...
Definition: Array.h:1906
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...
Definition: Array.h:2359
T & updElt(index_type i)
Same as the non-const form of operator[]; exists to provide a non-operator method for element access ...
Definition: Array.h:2276
size_type max_size() const
Return the maximum allowable size for this array.
Definition: Array.h:508
bool readFormatted(std::istream &in, Array_< T, X > &v)
Specialization of readFormatted() for variable-length Array_<T,X>; uses readArrayFromStream() to cons...
Definition: Array.h:3442
std::reverse_iterator< const_iterator > const_reverse_iterator
A const reverse iterator for this container.
Definition: Array.h:346
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_ refe...
Definition: Array.h:2308
Array_ & shareData(T *newData, size_type dataSize)
This dangerous extension allows you to make this array handle refer to someone else&#39;s data without co...
Definition: Array.h:1996
T & operator[](index_type i)
Select an element by its index, returning a writable (lvalue) reference.
Definition: Array.h:2256
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 eleme...
Definition: Array.h:3629
~ArrayView_()
The destructor just disconnects the array view handle from its data; see ArrayViewConst_<T,X>::disconnect() for more information.
Definition: Array.h:898
T * pointer
Definition: Array.h:849
ArrayView_(T *first, const T *last1)
Construct from a range of writable memory.
Definition: Array.h:878
void assign(const Iter &first, const Iter &last1)
Assign this array from a range [first,last1) given by non-pointer iterators.
Definition: Array.h:1896
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 refere...
Definition: Array.h:2013
T * data()
Return a writable pointer to the first allocated element of the array, or a null pointer if no space ...
Definition: Array.h:2231
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 c...
Definition: Array.h:561
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 th...
Definition: Array.h:2317
size_type capacity() const
Return the number of elements this array can currently hold without requiring reallocation.
Definition: Array.h:2047
static size_type max_size()
Definition: Array.h:142
const_reverse_iterator crbegin() const
Return a const reverse iterator pointing to the last element in the array or crend() if the array is ...
Definition: Array.h:1205
static size_type max_size()
The maximum allowable size for any Array_<T,X> that uses this type X as its index type...
Definition: Array.h:114
bool isSizeInRange(char sz, char mx)
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:347
static std::istream & readArrayFromStreamHelper(std::istream &in, bool isFixedSize, Array_< T, X > &out)
Definition: Array.h:3177
size_type max_size() const
Return the maximum allowable size for this array.
Definition: Array.h:2039
bool empty() const
Return true if there are no elements currently stored in this array.
Definition: Array.h:2042
short size_type
Definition: Array.h:174
const T & back() const
Return a const reference to the last element in this array, which must not be empty.
Definition: Array.h:1121
static std::istream & fillArrayViewFromStream(std::istream &in, ArrayView_< T, X > &out)
Read in a fixed number of elements from a stream into an ArrayView.
Definition: Array.h:3524
X::size_type size_type
The signed or unsigned integral type to which an object of index type X can be converted without prod...
Definition: Array.h:108
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...
Definition: Array.h:3540
void writeFormatted(std::ostream &o, const T &v)
The default implementation of writeFormatted<T> converts the object to a String using the templatized...
Definition: Serialize.h:312
void writeUnformatted(std::ostream &o, const T &v)
The default implementation of writeUnformatted<T> converts the object to a String using the templatiz...
Definition: Serialize.h:75
ArrayView_(const ArrayView_ &src)
Copy constructor is shallow.
Definition: Array.h:875
const T * data() const
The const version of the data() method is identical to cdata().
Definition: Array.h:667
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.
Definition: Array.h:634
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...
Definition: Array.h:1595
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 ...
Definition: Array.h:2606
ArrayView_ & operator=(const std::vector< T2, A2 > &src)
Assignment from any std::vector object is allowed as long as the number of elements matches and the t...
Definition: Array.h:953