Simbody  3.7
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-15 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 #include <type_traits>
44 #include <initializer_list>
45 #include <utility>
46 
47 namespace SimTK {
48 
49 // These are the classes defined in this header.
50 template <class X> struct ArrayIndexTraits;
51 template <class T, class X=unsigned> class ArrayViewConst_;
52 template <class T, class X=unsigned> class ArrayView_;
53 template <class T, class X=unsigned> class Array_;
54 
55 namespace Xml {
56 class Element;
57 }
58 
59 // NOTE: I have attempted to force the compilers to inline certain trivial
60 // methods here because I observed Visual C++ 2013 fail to inline operator[]
61 // in a performance-critical method (getCacheEntry() to be specific). It is
62 // essential that there be no overhead introduced by the Array_ classes, which
63 // Simbody uses extensively specifically because std::vector was too slow.
64 // (sherm 20140404).
65 
66 //==============================================================================
67 // CLASS ArrayIndexTraits
68 //==============================================================================
69 
112 template <class X> struct ArrayIndexTraits {
115  typedef typename X::size_type size_type;
118  typedef typename X::difference_type difference_type;
121  static size_type max_size() {return X::max_size();}
122 };
123 
126 template <> struct ArrayIndexTraits<unsigned> {
127  typedef unsigned size_type;
128  typedef int difference_type;
129  static size_type max_size() {return (unsigned)INT_MAX;}
130 };
131 
133 template <> struct ArrayIndexTraits<int> {
134  typedef int size_type;
135  typedef int difference_type;
136  static size_type max_size() {return INT_MAX;}
137 };
138 
146 template <> struct ArrayIndexTraits<unsigned long> {
147  typedef unsigned long size_type;
148  typedef long difference_type;
149  static size_type max_size() {return (unsigned long)LONG_MAX;}
150 };
151 
159 template <> struct ArrayIndexTraits<long> {
160  typedef long size_type;
161  typedef long difference_type;
162  static size_type max_size() {return LONG_MAX;}
163 };
164 
170 template <> struct ArrayIndexTraits<unsigned short> {
171  typedef unsigned short size_type;
172  typedef int difference_type;
173  static size_type max_size() {return USHRT_MAX;}
174 };
175 
180 template <> struct ArrayIndexTraits<short> {
181  typedef short size_type;
182  typedef short difference_type;
183  static size_type max_size() {return SHRT_MAX;}
184 };
185 
186 
191 template <> struct ArrayIndexTraits<unsigned char> {
192  typedef unsigned char size_type;
193  typedef short difference_type;
194  static size_type max_size() {return UCHAR_MAX;} // not CHAR_MAX
195 };
196 
202 template <> struct ArrayIndexTraits<signed char> {
203  typedef signed char size_type;
204  typedef signed char difference_type;
205  static size_type max_size() {return SCHAR_MAX;}
206 };
207 
214 template <> struct ArrayIndexTraits<char> {
215  typedef char size_type;
216  typedef signed char difference_type;
217  static size_type max_size() {return (char)SCHAR_MAX;}
218 };
219 
225 template <> struct ArrayIndexTraits<bool> {
226  typedef unsigned char size_type;
227  typedef signed char difference_type;
228  static size_type max_size() {return 2;}
229 };
230 
233 template <> struct ArrayIndexTraits<unsigned long long> {
234  typedef unsigned long long size_type;
235  typedef long long difference_type;
236  static size_type max_size()
237  {return (unsigned long long)LLONG_MAX;}
238 };
239 
242 template <> struct ArrayIndexTraits<long long> {
243  typedef long long size_type;
244  typedef long long difference_type;
245  static size_type max_size() {return LLONG_MAX;}
246 };
247 
248 // Don't show this in Doxygen.
250 // This helper class decides what integral type we should use to best pack
251 // the index type's size_type representation. The idea is to pack the whole
252 // Array_ structure into 8 bytes on a 32 bit machine, 16 bytes on a 64 bit
253 // machine, using the largest integral type that will work, giving a layout
254 // like this: | data pointer |
255 // | nUsed | nAllocated |
256 
257 // The default implementation just uses the integral type itself.
258 template <class Integral, class is64Bit> struct ArrayIndexPackTypeHelper
259 { typedef Integral packed_size_type;};
260 
261 // On 32 bit machine, pack anything smaller than a short into a short.
262 template<> struct ArrayIndexPackTypeHelper<bool,FalseType>
263 { typedef unsigned short packed_size_type;};
264 template<> struct ArrayIndexPackTypeHelper<char,FalseType>
265 { typedef unsigned short packed_size_type;};
266 template<> struct ArrayIndexPackTypeHelper<unsigned char,FalseType>
267 { typedef unsigned short packed_size_type;};
268 template<> struct ArrayIndexPackTypeHelper<signed char,FalseType>
269 { typedef short packed_size_type;};
270 
271 // On 64 bit machine, pack anything smaller than an int into an int.
272 template<> struct ArrayIndexPackTypeHelper<bool,TrueType>
273 { typedef unsigned int packed_size_type;};
274 template<> struct ArrayIndexPackTypeHelper<char,TrueType>
275 { typedef unsigned int packed_size_type;};
276 template<> struct ArrayIndexPackTypeHelper<unsigned char,TrueType>
277 { typedef unsigned int packed_size_type;};
278 template<> struct ArrayIndexPackTypeHelper<signed char,TrueType>
279 { typedef int packed_size_type;};
280 template<> struct ArrayIndexPackTypeHelper<unsigned short,TrueType>
281 { typedef unsigned int packed_size_type;};
282 template<> struct ArrayIndexPackTypeHelper<short,TrueType>
283 { typedef int packed_size_type;};
284 
285 template <class Integral> struct ArrayIndexPackType
286 { typedef typename ArrayIndexPackTypeHelper<Integral,Is64BitPlatformType>
287  ::packed_size_type packed_size_type;};
295 //==============================================================================
296 // CLASS ArrayViewConst_
297 //==============================================================================
324 template <class T, class X> class ArrayViewConst_ {
325 public:
326 
327 
328 //------------------------------------------------------------------------------
335 typedef T value_type;
337 typedef X index_type;
339 typedef T* pointer;
341 typedef const T* const_pointer;
343 typedef T& reference;
345 typedef const T& const_reference;
347 typedef T* iterator;
349 typedef const T* const_iterator;
351 typedef std::reverse_iterator<iterator> reverse_iterator;
353 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
360 typedef typename ArrayIndexPackType<size_type>::packed_size_type
365 //------------------------------------------------------------------------------
371 
373 ArrayViewConst_() : pData(0), nUsed(0), nAllocated(0) {}
374 
385 : pData(0), nUsed(src.nUsed), nAllocated(0) {
386  if (nUsed) pData = const_cast<T*>(src.pData);
387 }
388 
389 // Copy assignment is suppressed.
390 
413 ArrayViewConst_(const T* first, const T* last1)
414 : pData(0),nUsed(0),nAllocated(0) {
415  if (last1==first) return; // empty
416 
417  SimTK_ERRCHK((first&&last1)||(first==last1),
418  "ArrayViewConst_<T>(first,last1)",
419  "One of the source pointers was null (0); either both must be"
420  " non-null or both must be null.");
421 
422  SimTK_ERRCHK3(this->isSizeOK(last1-first),
423  "ArrayViewConst_<T>(first,last1)",
424  "The source data's size %llu is too big for this array which"
425  " is limited to %llu elements by its index type %s.",
426  this->ull(last1-first), ullMaxSize(), indexName());
427 
428  pData = const_cast<T*>(first);
429  nUsed = packed_size_type(last1-first);
430  // nAllocated is already zero
431 }
432 
460 template <class A>
461 ArrayViewConst_(const std::vector<T,A>& src)
462 : pData(0),nUsed(0),nAllocated(0) {
463  if (src.empty()) return;
464 
465  SimTK_ERRCHK3(this->isSizeOK(src.size()),
466  "ArrayViewConst_<T>::ctor(std::vector<T>)",
467  "The source std::vector's size %llu is too big for this array which"
468  " is limited to %llu elements by its index type %s.",
469  this->ull(src.size()), ullMaxSize(), indexName());
470 
471  pData = const_cast<T*>(&src.front());
472  nUsed = packed_size_type(src.size());
473  // nAllocated is already zero
474 }
477 operator const ArrayView_<T,X>&() const
478 { return *reinterpret_cast<const ArrayView_<T,X>*>(this); }
481 operator const Array_<T,X>&() const
482 { return *reinterpret_cast<const Array_<T,X>*>(this); }
483 
489 void disconnect() {
490  SimTK_ASSERT(nAllocated==0,
491  "ArrayViewConst_::deallocate(): called on an owner Array_");
492  nUsed = 0;
493  pData = 0;
494 }
495 
499  disconnect();
500 }
504 //------------------------------------------------------------------------------
511 
513 size_type size() const {return size_type(nUsed);}
516 { return ArrayIndexTraits<X>::max_size(); }
519 bool empty() const {return nUsed==0;}
525 { return size_type(nAllocated?nAllocated:nUsed); }
529 size_type allocated() const {return size_type(nAllocated);}
535 bool isOwner() const {return nAllocated || pData==0;}
536 /*}*/
537 
538 
539 //------------------------------------------------------------------------------
546 
555  SimTK_INDEXCHECK(size_type(i),size(),"ArrayViewConst_<T>::operator[]()");
556  return pData[i];
557 }
562 const T& at(index_type i) const {
563  SimTK_INDEXCHECK_ALWAYS(size_type(i),size(),"ArrayViewConst_<T>::at()");
564  return pData[i];
565 }
569  SimTK_INDEXCHECK(size_type(i),size(),"ArrayViewConst_<T>::getElt()");
570  return pData[i];
571 }
577 SimTK_FORCE_INLINE const T& front() const
578 { SimTK_ERRCHK(!empty(), "ArrayViewConst_<T>::front()", "Array was empty.");
579  return pData[0]; }
585 SimTK_FORCE_INLINE const T& back() const
586 { SimTK_ERRCHK(!empty(), "ArrayViewConst_<T>::back()", "Array was empty.");
587  return pData[nUsed-1]; }
588 
608  const size_type ix(index);
609  SimTK_ERRCHK2(isSizeInRange(ix, size()), "ArrayViewConst_<T>(index,length)",
610  "For this operator, we must have 0 <= index <= size(), but"
611  " index==%llu and size==%llu.", this->ull(ix), ullSize());
612  SimTK_ERRCHK2(isSizeInRange(length, size_type(size()-ix)),
613  "ArrayViewConst_<T>(index,length)",
614  "This operator requires 0 <= length <= size()-index, but"
615  " length==%llu and size()-index==%llu.",this->ull(length),this->ull(size()-ix));
616 
617  return ArrayViewConst_(pData+ix, pData+ix+length);
618 }
622 { return (*this)(index,length); }
623 
627 //------------------------------------------------------------------------------
636 
641 const T* cbegin() const {return pData;}
646 const T* cend() const {return pData + nUsed;}
648 const T* begin() const {return pData;}
650 const T* end() const {return pData + nUsed;}
651 
655 { return const_reverse_iterator(cend()); }
660 { return const_reverse_iterator(cbegin()); }
664 const_reverse_iterator rend() const {return crend();}
665 
672 const T* cdata() const {return pData;}
674 const T* data() const {return pData;}
678 //------------------------------------------------------------------------------
679  protected:
680 //------------------------------------------------------------------------------
681 // The remainder of this class is for the use of the ArrayView_<T,X> and
682 // Array_<T,X> derived classes only and should not be documented for users to
683 // see.
684 
685 // Don't let doxygen see any of this.
687 packed_size_type psize() const {return nUsed;}
688 packed_size_type pallocated() const {return nAllocated;}
689 
690 // These provide direct access to the data members for our trusted friends.
691 void setData(const T* p) {pData = const_cast<T*>(p);}
692 void setSize(size_type n) {nUsed = packed_size_type(n);}
693 void incrSize() {++nUsed;}
694 void decrSize() {--nUsed;}
695 void setAllocated(size_type n) {nAllocated = packed_size_type(n);}
696 
697 // Check whether a given size is the same as the current size of this array,
698 // avoiding any compiler warnings due to mismatched integral types.
699 template <class S>
700 bool isSameSize(S sz) const
701 { return ull(sz) == ullSize(); }
702 
703 // Check that a source object's size will fit in the array being careful to
704 // avoid overflow and warnings in the comparison.
705 template <class S>
706 bool isSizeOK(S srcSz) const
707 { return ull(srcSz) <= ullMaxSize(); }
708 
709 // This is identical in function to std::distance() (reports how many
710 // elements lie between two iterators) but avoids any slow
711 // Release-build bugcatchers that Microsoft may have felt compelled to add.
712 // The implementation is specialized for random access iterators because
713 // they can measure distance very fast.
714 template<class Iter> static
715 typename std::iterator_traits<Iter>::difference_type
716 iterDistance(const Iter& first, const Iter& last1) {
717  return iterDistanceImpl(first,last1,
718  typename std::iterator_traits<Iter>::iterator_category());
719 }
720 
721 // Generic slow implementation for non-random access iterators. This is fine
722 // for forward and bidirectional iterators, but it will *consume* input
723 // iterators so is useless for them.
724 template<class Iter> static
725 typename std::iterator_traits<Iter>::difference_type
726 iterDistanceImpl(const Iter& first, const Iter& last1, std::input_iterator_tag) {
727  typename std::iterator_traits<Iter>::difference_type d = 0;
728  for (Iter src=first; src != last1; ++src, ++d)
729  ;
730  return d;
731 }
732 
733 // Fast specialization for random access iterators (including ordinary
734 // pointers) -- just subtract.
735 template<class Iter> static
736 typename std::iterator_traits<Iter>::difference_type
737 iterDistanceImpl(const Iter& first, const Iter& last1,
738  std::random_access_iterator_tag) {
739  return last1 - first;
740 }
741 
742 // This method attempts to determine whether any elements in the iterator range
743 // [first,last1) overlap with the elements stored in this array. This is used
744 // for error checks for operations where source is not permitted to overlap the
745 // destination. For random access iterators (including ordinary pointers), we
746 // can answer this question definitively because we expect the data to be
747 // consecutive in memory. For other kinds of iterators, we will just assume
748 // there is no overlap. Note that null ranges do not overlap even if the
749 // pair of equal iterators points within the other range -- what matters is
750 // the number of overlapping elements.
751 template<class Iter> bool
752 overlapsWithData(const Iter& first, const Iter& last1) {
753  return overlapsWithDataImpl(first,last1,
754  typename std::iterator_traits<Iter>::iterator_category());
755 }
756 
757 // This is a partial specialization of the above where the data is given
758 // with ordinary pointers.
759 template <class T2> bool
760 overlapsWithData(const T2* first, const T2* last1) {
761  // Find the start and end+1 of the alleged overlap region. There is
762  // overlap iff end+1 > start. Note that this works if either range
763  // is [0,0) or [p,p), or if last1 is illegally less than first (we just
764  // want to report no overlap in that case -- it is someone else's business
765  // to complain).
766  const T* obegin = std::max(cbegin(), (const T*)first);
767  const T* oend1 = std::min(cend(), (const T*)last1);
768 
769  return obegin < oend1;
770 }
771 
772 // This is the generic implementation for any type of input iterator other than
773 // random access (i.e., bidirectional, forward, or input) -- assume no overlap.
774 template<class Iter> bool
775 overlapsWithDataImpl(const Iter&, const Iter&, std::input_iterator_tag)
776 { return false; }
777 
778 // Here we can actually test for overlap since we have random access iterators.
779 // We convert them to pointers and then look for memory overlap.
780 template<class Iter> bool
781 overlapsWithDataImpl(const Iter& first, const Iter& last1,
782  std::random_access_iterator_tag) {
783  // We must check that the input iterators span a non-zero range before
784  // assuming we can dereference them.
785  if (last1 <= first)
786  return false; // zero or malformed source range: no overlap
787 
788  // We now know we can dereference first and last1-1 (can't safely
789  // dereference last1 but we can use pointer arithmetic to point past
790  // the (last-1)th element in memory). We then take the dereferenced
791  // object's address to get ordinary pointers that we can use to
792  // watch for illegal overlap.
793  return overlapsWithData(&*first, &*(last1-1)); // use pointer overload
794 }
795 
796 // Cast an integral type to maximal-width unsigned long long to avoid accidental
797 // overflows that might otherwise occur due to wraparound that can happen
798 // with small index types.
799 template <class S>
800 static unsigned long long ull(S sz)
801 { return (unsigned long long)sz; }
802 
803 // Return size(), capacity(), and max_size() cast to unsigned long long.
804 unsigned long long ullSize() const {return ull(size());}
805 unsigned long long ullCapacity() const {return ull(capacity());}
806 unsigned long long ullMaxSize() const {return ull(max_size());}
807 
808 // Useful in error messages for explaining why something was too big.
809 const char* indexName() const {return NiceTypeName<X>::name();}
810 
813 private:
814 //------------------------------------------------------------------------------
815 // DATA MEMBERS
816 // These are the only data members and this layout is guaranteed not to change
817 // from release to release. If data is null, then nUsed==nAllocated==0.
818 
819 T* pData; // ptr to data referenced here, or 0 if none
820 packed_size_type nUsed; // number of elements currently present (size)
821 packed_size_type nAllocated; // heap allocation; 0 if pData is not owned
822 
823 ArrayViewConst_& operator=(const ArrayViewConst_& src); // suppressed
824 };
825 
826 
827 
828 
829 
830 
831 //==============================================================================
832 // CLASS ArrayView_
833 //==============================================================================
845 template <class T, class X> class ArrayView_ : public ArrayViewConst_<T,X> {
846 typedef ArrayViewConst_<T,X> CBase;
847 public:
848 //------------------------------------------------------------------------------
853 /*{*/
854 typedef T value_type;
855 typedef X index_type;
856 typedef T* pointer;
857 typedef const T* const_pointer;
858 typedef T& reference;
859 typedef const T& const_reference;
860 typedef T* iterator;
861 typedef const T* const_iterator;
862 typedef std::reverse_iterator<iterator> reverse_iterator;
863 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
866 typedef typename ArrayIndexPackType<size_type>::packed_size_type
868 /*}*/
869 
870 
871 //------------------------------------------------------------------------------
877 
880 
882 ArrayView_(const ArrayView_& src) : CBase(src) {}
883 
885 ArrayView_(T* first, const T* last1) : CBase(first,last1) {}
886 
888 template <class A>
889 ArrayView_(std::vector<T,A>& v) : CBase(v) {}
890 
892 operator const Array_<T,X>&() const
893 { return *reinterpret_cast<const Array_<T,X>*>(this); }
894 
896 operator Array_<T,X>&()
897 { return *reinterpret_cast<Array_<T,X>*>(this); }
898 
901 void disconnect() {this->CBase::disconnect();}
902 
909 //------------------------------------------------------------------------------
921 
924  if (&src != this)
925  avAssignIteratorDispatch(src.cbegin(), src.cend(),
926  std::random_access_iterator_tag(),
927  "ArrayView_<T>::operator=(ArrayView_<T>)");
928  return *this;
929 }
930 
931 
934 template <class T2, class X2>
936  if ((const void*)&src != (void*)this)
937  avAssignIteratorDispatch(src.cbegin(), src.cend(),
938  std::random_access_iterator_tag(),
939  "ArrayView_<T>::operator=(Array_<T2>)");
940  return *this;
941 }
942 
943 // Help out dumb compilers struggling to match the template arguments and
944 // promote the Array_ or ArrayView_ to ArrayConstView_ at the same time.
945 
948 template <class T2, class X2>
950 { return *this = static_cast<const ArrayViewConst_<T2,X2>&>(src); }
953 template <class T2, class X2>
955 { return *this = static_cast<const ArrayViewConst_<T2,X2>&>(src); }
956 
959 template <class T2, class A2>
960 ArrayView_& operator=(const std::vector<T2,A2>& src) {
961  avAssignIteratorDispatch(src.begin(), src.end(),
962  std::random_access_iterator_tag(),
963  "ArrayView_<T>::operator=(std::vector<T2>)");
964  return *this;
965 }
966 
968 ArrayView_& operator=(const T& fillValue)
969 { fill(fillValue); return *this; }
970 
976 ArrayView_& fill(const T& fillValue) {
977  for (T* d = begin(); d != end(); ++d)
978  *d = fillValue; // using T::operator=(T)
979  return *this;
980 }
981 
985 void assign(size_type n, const T& fillValue) {
986  SimTK_ERRCHK2(n == size(), "ArrayView_<T>::assign(n,value)",
987  "Assignment to an ArrayView is permitted only if the source"
988  " is the same size. Here n==%llu element(s) but the"
989  " ArrayView has a fixed size of %llu.",
990  this->ull(n), this->ull(size()));
991 
992  fill(fillValue);
993 }
994 
1012 template <class T2>
1013 void assign(const T2* first, const T2* last1) {
1014  const char* methodName = "ArrayView_<T>::assign(T2* first, T2* last1)";
1015  SimTK_ERRCHK((first&&last1)||(first==last1), methodName,
1016  "One of the source pointers was null (0); either both must be"
1017  " non-null or both must be null.");
1018  // Valid pointers are random access iterators.
1019  avAssignIteratorDispatch(first, last1, std::random_access_iterator_tag(),
1020  methodName);
1021 }
1022 
1052 // Watch out for integral types matching this signature -- they must be
1053 // forwarded to the assign(n, fillValue) signature instead.
1054 template <class Iter>
1055 void assign(const Iter& first, const Iter& last1)
1056 { avAssignDispatch(first,last1,typename IsIntegralType<Iter>::Result(),
1057  "ArrayView_<T>::assign(Iter first, Iter last1)"); }
1061 //------------------------------------------------------------------------------
1068 
1076 { return this->CBase::operator[](i); }
1077 
1086 { return const_cast<T&>(this->CBase::operator[](i)); }
1087 
1092 const T& at(index_type i) const {return this->CBase::at(i);}
1093 
1098 T& at(index_type i) {return const_cast<T&>(this->CBase::at(i));}
1099 
1103 { return this->CBase::getElt(i); }
1107 { return const_cast<T&>(this->CBase::getElt(i)); }
1108 
1114 SimTK_FORCE_INLINE const T& front() const {return this->CBase::front();}
1115 
1121 SimTK_FORCE_INLINE T& front() {return const_cast<T&>(this->CBase::front());}
1122 
1128 SimTK_FORCE_INLINE const T& back() const {return this->CBase::back();}
1129 
1135 SimTK_FORCE_INLINE T& back() {return const_cast<T&>(this->CBase::back());}
1136 
1156  const size_type ix(index);
1157  SimTK_ERRCHK2(isSizeInRange(ix, size()), "ArrayView_<T>(index,length)",
1158  "For this operator, we must have 0 <= index <= size(), but"
1159  " index==%llu and size==%llu.", this->ull(ix), ullSize());
1160  SimTK_ERRCHK2(isSizeInRange(length, size_type(size()-ix)),
1161  "ArrayView_<T>(index,length)",
1162  "This operator requires 0 <= length <= size()-index, but"
1163  " length==%llu and size()-index==%llu.",this->ull(length),this->ull(size()-ix));
1164 
1165  return ArrayView_(data()+ix, data()+ix+length);
1166 }
1170 { return (*this)(index,length); }
1174 //------------------------------------------------------------------------------
1183 
1188 SimTK_FORCE_INLINE const T* cbegin() const {return this->CBase::cbegin();}
1190 SimTK_FORCE_INLINE const T* begin() const {return this->CBase::cbegin();}
1195 SimTK_FORCE_INLINE T* begin() {return const_cast<T*>(this->CBase::cbegin());}
1196 
1201 SimTK_FORCE_INLINE const T* cend() const {return this->CBase::cend();}
1203 SimTK_FORCE_INLINE const T* end() const {return this->CBase::cend();}
1208 SimTK_FORCE_INLINE T* end() {return const_cast<T*>(this->CBase::cend());}
1209 
1212 const_reverse_iterator crbegin() const
1213 { return this->CBase::crbegin(); }
1215 const_reverse_iterator rbegin() const
1216 { return this->CBase::crbegin(); }
1219 reverse_iterator rbegin() {return reverse_iterator(end());}
1220 
1225 { return this->CBase::crend(); }
1227 const_reverse_iterator rend() const
1228 { return this->CBase::crend(); }
1232 reverse_iterator rend() {return reverse_iterator(begin());}
1233 
1240 SimTK_FORCE_INLINE const T* cdata() const {return this->CBase::cdata();}
1243 SimTK_FORCE_INLINE const T* data() const {return this->CBase::cdata();}
1247 SimTK_FORCE_INLINE T* data() {return const_cast<T*>(this->CBase::cdata());}
1251 //------------------------------------------------------------------------------
1257 
1258 // Note: these have to be explicitly forwarded to the base class methods
1259 // in order to keep gcc from complaining. Note that the "this->" is
1260 // apparently necessary in order to permit delayed definition of templatized
1261 // methods. Doxygen picks up the comments from the base class.
1262 
1263 SimTK_FORCE_INLINE size_type size() const {return this->CBase::size();}
1264 size_type max_size() const {return this->CBase::max_size();}
1265 bool empty() const {return this->CBase::empty();}
1266 size_type capacity() const {return this->CBase::capacity();}
1267 size_type allocated() const {return this->CBase::allocated();}
1268 bool isOwner() const {return this->CBase::isOwner();}
1272 //------------------------------------------------------------------------------
1273  private:
1274 //------------------------------------------------------------------------------
1275 // no data members are allowed
1276 
1277 //------------------------------------------------------------------------------
1278 // ARRAY VIEW ASSIGN DISPATCH
1279 // This is the assign() implementation for ArrayView_ when the class that
1280 // matched the alleged InputIterator template argument turned out to be one of
1281 // the integral types in which case this should match the assign(n, fillValue)
1282 // signature.
1283 template <class IntegralType>
1284 void avAssignDispatch(IntegralType n, IntegralType v, TrueType isIntegralType,
1285  const char*)
1286 { assign(size_type(n), value_type(v)); }
1287 
1288 // This is the assign() implementation for ArrayView_ when the class that
1289 // matched the alleged InputIterator template argument is NOT an integral type
1290 // and may very well be an iterator.
1291 template <class InputIterator>
1292 void avAssignDispatch(const InputIterator& first, const InputIterator& last1,
1293  FalseType isIntegralType, const char* methodName)
1294 { avAssignIteratorDispatch(first, last1,
1295  typename std::iterator_traits<InputIterator>::iterator_category(),
1296  methodName); }
1297 
1298 // This is the assign() implementation for a plain input_iterator
1299 // (i.e., not a forward, bidirectional, or random access iterator). These
1300 // have the unfortunate property that we can't count the elements in advance.
1301 // Here we're going to complain if there aren't enough; but will simply stop
1302 // when we get size() elements and not insist that the input stream reached
1303 // the supplied last1 iterator. Semantics is elementwise assignment.
1304 template <class InputIterator>
1305 void avAssignIteratorDispatch(const InputIterator& first,
1306  const InputIterator& last1,
1307  std::input_iterator_tag,
1308  const char* methodName)
1309 {
1310  T* p = begin();
1311  InputIterator src = first;
1312  while (src != last1 && p != end())
1313  *p++ = *src++; // call T's assignment operator
1314 
1315  // p now points just after the last element that was copied.
1316  const size_type nCopied = size_type(p - begin());
1317  SimTK_ERRCHK2_ALWAYS(nCopied == size(), methodName,
1318  "The supplied input_iterator provided only %llu elements but this"
1319  " ArrayView has a fixed size of %llu elements.",
1320  this->ull(nCopied), ullSize());
1321 
1322  // We don't care if there are still more input elements available.
1323 }
1324 
1325 // This is the assign() implementation that works for forward and bidirectional
1326 // iterators, but is not used for random_access_iterators. Here we'll count
1327 // the elements as we copy them and complain at the end if there were too
1328 // few or too many.
1329 template <class ForwardIterator>
1330 void avAssignIteratorDispatch(const ForwardIterator& first,
1331  const ForwardIterator& last1,
1332  std::forward_iterator_tag,
1333  const char* methodName)
1334 {
1335  T* p = begin();
1336  ForwardIterator src = first;
1337  while (src != last1 && p != end())
1338  *p++ = *src++; // call T's assignment operator
1339 
1340  // p now points just after the last element that was copied.
1341  const size_type nCopied = size_type(p - begin());
1342  SimTK_ERRCHK2_ALWAYS(nCopied == size(), methodName,
1343  "The supplied forward_ or bidirectional_iterator source range provided"
1344  " only %llu elements but this ArrayView has a fixed size of"
1345  " %llu elements.", this->ull(nCopied), ullSize());
1346 
1347  // Make sure we ran out of source elements.
1348  SimTK_ERRCHK1_ALWAYS(src == last1, methodName,
1349  "The supplied forward_ or bidirectional_iterator source range"
1350  " contained too many elements; this ArrayView has a fixed size of"
1351  " %llu elements.", ullSize());
1352 }
1353 
1354 // This is the assign() implementation that works for random_access_iterators
1355 // including ordinary pointers. Here we check the number of elements in advance
1356 // and complain if the source and destination aren't the same size. The
1357 // copying loop can be done faster in this case.
1358 template <class RandomAccessIterator>
1359 void avAssignIteratorDispatch(const RandomAccessIterator& first,
1360  const RandomAccessIterator& last1,
1361  std::random_access_iterator_tag,
1362  const char* methodName)
1363 {
1364  SimTK_ERRCHK2_ALWAYS(this->isSameSize(last1-first), methodName,
1365  "Assignment to an ArrayView is permitted only if the source"
1366  " is the same size. Here the source had %llu element(s) but the"
1367  " ArrayView has a fixed size of %llu.",
1368  this->ull(last1-first), this->ull(size()));
1369 
1370  SimTK_ERRCHK_ALWAYS(!this->overlapsWithData(first,last1), methodName,
1371  "Source range can't overlap with the destination data.");
1372 
1373  T* p = begin();
1374  RandomAccessIterator src = first;
1375  while (p != end())
1376  *p++ = *src++; // call T's assignment operator
1377 }
1378 
1379 
1380 //------------------------------------------------------------------------------
1381 // The following private methods are protected methods in the ArrayViewConst_
1382 // base class, so they should not need repeating here. However, we explicitly
1383 // forward to the base methods to avoid gcc errors. The gcc complaint
1384 // is due to their not depending on any template parameters; the "this->"
1385 // apparently fixes that problem.
1386 
1387 packed_size_type psize() const
1388 { return this->CBase::psize(); }
1389 packed_size_type pallocated() const
1390 { return this->CBase::pallocated(); }
1391 
1392 // This just cast sizes to unsigned long long so that we can do comparisons
1393 // without getting warnings.
1394 unsigned long long ullSize() const
1395 { return this->CBase::ullSize(); }
1396 unsigned long long ullCapacity() const
1397 { return this->CBase::ullCapacity(); }
1398 unsigned long long ullMaxSize() const
1399 { return this->CBase::ullMaxSize(); }
1400 // This is the index type name and is handy for error messages to explain
1401 // why some size was too big.
1402 const char* indexName() const {return this->CBase::indexName();}
1403 };
1404 
1405 
1406 //==============================================================================
1407 // CLASS Array_
1408 //==============================================================================
1520 template <class T, class X> class Array_ : public ArrayView_<T,X> {
1521  typedef ArrayView_<T,X> Base;
1522  typedef ArrayViewConst_<T,X> CBase;
1523 public:
1524 
1525 
1526 //------------------------------------------------------------------------------
1532 // Doxygen picks up individual descriptions from the base class.
1533 /*{*/
1534 typedef T value_type;
1535 typedef X index_type;
1536 typedef T* pointer;
1537 typedef const T* const_pointer;
1538 typedef T& reference;
1539 typedef const T& const_reference;
1540 typedef T* iterator;
1541 typedef const T* const_iterator;
1542 typedef std::reverse_iterator<iterator> reverse_iterator;
1543 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
1546 typedef typename ArrayIndexPackType<size_type>::packed_size_type
1548 /*}*/
1549 
1550 //------------------------------------------------------------------------------
1557 /*{*/
1558 
1560 Array_() : Base() {}
1561 
1566 explicit Array_(size_type n) : Base() {
1567  SimTK_SIZECHECK(n, max_size(), "Array_<T>::ctor(n)");
1568  allocateNoConstruct(n);
1569  defaultConstruct(data(), data()+n);
1570  setSize(n);
1571 }
1572 
1576 Array_(size_type n, const T& initVal) : Base() {
1577  SimTK_SIZECHECK(n, max_size(), "Array_<T>::ctor(n,T)");
1578  setSize(n);
1579  allocateNoConstruct(size());
1580  fillConstruct(begin(), cend(), initVal);
1581 }
1597 template <class InputIter>
1598 Array_(const InputIter& first, const InputIter& last1) : Base() {
1599  ctorDispatch(first,last1,typename IsIntegralType<InputIter>::Result());
1600 }
1601 
1607 template <class T2>
1608 Array_(const T2* first, const T2* last1) : Base() {
1609  static_assert(std::is_assignable<T&,T2>::value,
1610  "Array_<T> construction from T2 requires that "
1611  "T2 implicitly converts to T");
1612  SimTK_ERRCHK((first&&last1)||(first==last1), "Array_<T>(first,last1)",
1613  "Pointers must be non-null unless they are both null.");
1614  SimTK_ERRCHK3(this->isSizeOK(last1-first), "Array_<T>(first,last1)",
1615  "Source has %llu elements but this array is limited to %llu"
1616  " elements by its index type %s.",
1617  this->ull(last1-first), ullMaxSize(), indexName());
1618 
1619  setSize(size_type(last1-first));
1620  allocateNoConstruct(size());
1621  copyConstruct(begin(), cend(), first);
1622 }
1623 
1628 Array_(std::initializer_list<T> ilist)
1629 : Array_(ilist.begin(), ilist.end()) {} // invoke above constructor for T*
1630 
1635 template <class T2>
1636 explicit Array_(const std::vector<T2>& v) : Base() {
1637  if (v.empty()) return;
1638 
1639  SimTK_ERRCHK3(this->isSizeOK(v.size()), "Array_<T>::ctor(std::vector<T2>)",
1640  "The source std::vector's size %llu is too big for this array which"
1641  " is limited to %llu elements by its index type %s.",
1642  this->ull(v.size()), ullMaxSize(), indexName());
1643 
1644  // Call the above constructor, making sure to use pointers into the
1645  // vector's data rather than the iterators begin() and end() in case
1646  // they are different types.
1647  new (this) Array_(&v.front(), (&v.back())+1);
1648 }
1649 
1654 Array_(const Array_& src) : Base() {
1655  setSize(src.size());
1656  allocateNoConstruct(size());
1657  copyConstruct(begin(), cend(), src.data());
1658 }
1659 
1662 Array_(Array_&& src) : Base() {
1663  swap(src);
1664 }
1665 
1672 template <class T2, class X2>
1673 Array_(const Array_<T2,X2>& src) : Base() {
1674  new (this) Array_(src.begin(), src.cend()); // see above
1675 }
1676 
1706 Array_(T* first, const T* last1, const DontCopy&) : Base(first,last1) {}
1707 
1735 template <class A>
1736 Array_(std::vector<T,A>& v, const DontCopy&) : Base(v) {}
1737 
1742  deallocate();
1743 }
1744 
1754  if (allocated()) { // owner with non-zero allocation
1755  clear(); // each element is destructed; size()=0; allocated() unchanged
1756  deallocateNoDestruct(); // free data(); allocated()=0
1757  }
1758  this->Base::disconnect(); // clear the handle
1759  return *this;
1760 }
1761 
1765 //------------------------------------------------------------------------------
1800 
1818 void assign(size_type n, const T& fillValue) {
1819  SimTK_ERRCHK3(this->isSizeOK(n), "Array_<T>::assign(n,value)",
1820  "Requested size %llu is too big for this array which is limited"
1821  " to %llu elements by its index type %s.",
1822  this->ull(n), ullMaxSize(), indexName());
1823 
1824  SimTK_ERRCHK2(isOwner() || n==size(), "Array_<T>::assign(n,value)",
1825  "Requested size %llu is not allowed because this is a non-owner"
1826  " array of fixed size %llu.", this->ull(n), this->ull(size()));
1827 
1828  if (!isOwner())
1829  this->Base::fill(fillValue);
1830  else {
1831  clear(); // all elements destructed; allocation unchanged
1832  reallocateIfAdvisable(n); // change size if too small or too big
1833  fillConstruct(data(), cdata()+n, fillValue);
1834  setSize(n);
1835  }
1836 }
1837 
1852 void fill(const T& fillValue) {this->Base::fill(fillValue);}
1853 
1854 
1876 template <class T2>
1877 void assign(const T2* first, const T2* last1) {
1878  const char* methodName = "Array_<T>::assign(T2* first, T2* last1)";
1879  SimTK_ERRCHK((first&&last1)||(first==last1), methodName,
1880  "Pointers must be non-null unless they are both null.");
1881  SimTK_ERRCHK(!this->overlapsWithData(first,last1), methodName,
1882  "Source range can't overlap the current array contents.");
1883  // Pointers are random access iterators.
1884  assignIteratorDispatch(first,last1,std::random_access_iterator_tag(),
1885  methodName);
1886 }
1887 
1888 
1924 template <class Iter>
1925 void assign(const Iter& first, const Iter& last1) {
1926  assignDispatch(first,last1,typename IsIntegralType<Iter>::Result(),
1927  "Array_<T>::assign(Iter first, Iter last1)");
1928 }
1929 
1935 Array_& operator=(const Array_& src) {
1936  if (this != &src)
1937  assignIteratorDispatch(src.begin(), src.end(),
1938  std::random_access_iterator_tag(),
1939  "Array_<T>::operator=(Array_<T>)");
1940  return *this;
1941 }
1942 
1946  swap(src);
1947  return *this;
1948 }
1949 
1955 template <class T2, class X2>
1957  assignIteratorDispatch(src.begin(), src.end(),
1958  std::random_access_iterator_tag(),
1959  "Array_<T>::operator=(Array_<T2,X2>)");
1960  return *this;
1961 }
1962 
1963 
1968 template <class T2, class A>
1969 Array_& operator=(const std::vector<T2,A>& src) {
1970  assignIteratorDispatch(src.begin(), src.end(),
1971  std::random_access_iterator_tag(),
1972  "Array_<T>::operator=(std::vector)");
1973  return *this;
1974 }
1975 
1983 void swap(Array_& other) {
1984  T* const pTmp=data(); setData(other.data()); other.setData(pTmp);
1985  size_type nTmp=size(); setSize(other.size()); other.setSize(nTmp);
1986  nTmp=allocated(); setAllocated(other.allocated()); other.setAllocated(nTmp);
1987 }
1988 
1994 Array_& adoptData(T* newData, size_type dataSize,
1995  size_type dataCapacity)
1996 {
1997  SimTK_SIZECHECK(dataCapacity, max_size(), "Array_<T>::adoptData()");
1998  SimTK_ERRCHK2(dataSize <= dataCapacity, "Array_<T>::adoptData()",
1999  "Specified data size %llu was greater than the specified data"
2000  " capacity of %llu.", this->ull(dataSize), this->ull(dataCapacity));
2001  SimTK_ERRCHK(newData || dataCapacity==0, "Array_<T>::adoptData()",
2002  "A null data pointer is allowed only if the size and capacity are"
2003  " specified as zero.");
2004  SimTK_ERRCHK(!this->overlapsWithData(newData, newData+dataSize),
2005  "Array_<T>::adoptData()",
2006  "The new data can't overlap with the old data.");
2007 
2008  deallocate();
2009  setData(newData);
2010  setSize(dataSize);
2011  setAllocated(dataCapacity);
2012  return *this;
2013 }
2016 Array_& adoptData(T* newData, size_type dataSize)
2017 { return adoptData(newData, dataSize, dataSize); }
2018 
2019 
2033 Array_& shareData(T* newData, size_type dataSize) {
2034  SimTK_SIZECHECK(dataSize, max_size(), "Array_<T>::shareData()");
2035  SimTK_ERRCHK(newData || dataSize==0, "Array_<T>::shareData()",
2036  "A null data pointer is allowed only if the size is zero.");
2037  SimTK_ERRCHK(!this->overlapsWithData(newData, newData+dataSize),
2038  "Array_<T>::shareData()",
2039  "The new data can't overlap with the old data.");
2040 
2041  deallocate();
2042  setData(newData);
2043  setSize(dataSize);
2044  setAllocated(0); // indicates shared data
2045  return *this;
2046 }
2047 
2050 Array_& shareData(T* first, const T* last1) {
2051  SimTK_ERRCHK3(this->isSizeOK(last1-first),
2052  "Array_<T>::shareData(first,last1)",
2053  "Requested size %llu is too big for this array which is limited"
2054  " to %llu elements by its index type %s.",
2055  this->ull(last1-first), ullMaxSize(), indexName());
2056  return shareData(first, size_type(last1-first));
2057 }
2058 
2062 //------------------------------------------------------------------------------
2068 
2069 // Note: these have to be explicitly forwarded to the base class methods
2070 // in order to keep gcc from complaining. Note that the "this->" is
2071 // apparently necessary in order to permit delayed definition of templatized
2072 // methods.
2073 
2077 size_type max_size() const {return this->CBase::max_size();}
2080 bool empty() const {return this->CBase::empty();}
2085 size_type capacity() const {return this->CBase::capacity();}
2086 
2091 void resize(size_type n) {
2092  if (n == size()) return;
2093 
2094  SimTK_ERRCHK2(isOwner(), "Array_<T>::resize(n)",
2095  "Requested size change to %llu is not allowed because this is a "
2096  "non-owner array of fixed size %llu.",
2097  this->ull(n), this->ull(size()));
2098 
2099  if (n < size()) {
2100  erase(data()+n, cend());
2101  return;
2102  }
2103  // n > size()
2104  reserve(n);
2105  defaultConstruct(data()+size(), cdata()+n); // data() has changed
2106  setSize(n);
2107 }
2108 
2113 void resize(size_type n, const T& initVal) {
2114  if (n == size()) return;
2115 
2116  SimTK_ERRCHK2(isOwner(), "Array_<T>::resize(n,value)",
2117  "Requested size change to %llu is not allowed because this is a"
2118  " non-owner array of fixed size %llu.", this->ull(n), this->ull(size()));
2119 
2120  if (n < size()) {
2121  erase(data()+n, cend());
2122  return;
2123  }
2124  // n > size()
2125  reserve(n);
2126  fillConstruct(data()+size(), cdata()+n, initVal);
2127  setSize(n);
2128 }
2129 
2137  if (capacity() >= n)
2138  return;
2139 
2140  SimTK_ERRCHK2(isOwner(), "Array_<T>::reserve()",
2141  "Requested capacity change to %llu is not allowed because this is a "
2142  "non-owner array of fixed size %llu.",
2143  this->ull(n), this->ull(size()));
2144 
2145  T* newData = allocN(n); // no construction yet
2146  moveConstructThenDestructSource(newData, newData+size(), data());
2147  freeN(data());
2148  setData(newData);
2149  setAllocated(n);
2150 }
2151 
2173  // Allow 25% slop, but note that if size()==0 this will always reallocate
2174  // unless capacity is already zero.
2175  if (capacity() - size()/4 <= size()) // avoid overflow if size() near max
2176  return;
2177  T* newData = allocN(size());
2178  moveConstructThenDestructSource(newData, newData+size(), data());
2179  deallocateNoDestruct(); // data()=0, allocated()=0, size() unchanged
2180  setData(newData);
2181  setAllocated(size());
2182 }
2183 
2188 { return this->CBase::allocated(); }
2194 bool isOwner() const {return this->CBase::isOwner();}
2198 //------------------------------------------------------------------------------
2207 
2212 SimTK_FORCE_INLINE const T* cbegin() const {return this->CBase::cbegin();}
2214 SimTK_FORCE_INLINE const T* begin() const {return this->CBase::cbegin();}
2219 SimTK_FORCE_INLINE T* begin() {return this->Base::begin();}
2220 
2225 SimTK_FORCE_INLINE const T* cend() const {return this->CBase::cend();}
2227 SimTK_FORCE_INLINE const T* end() const {return this->CBase::cend();}
2232 SimTK_FORCE_INLINE T* end() {return this->Base::end();}
2233 
2236 const_reverse_iterator crbegin() const
2237 { return this->CBase::crbegin(); }
2239 const_reverse_iterator rbegin() const
2240 { return this->CBase::crbegin(); }
2243 reverse_iterator rbegin() {return this->Base::rbegin();}
2244 
2248 const_reverse_iterator crend() const
2249 { return this->CBase::crend(); }
2251 const_reverse_iterator rend() const
2252 { return this->CBase::crend(); }
2256 reverse_iterator rend() {return this->Base::rend();}
2257 
2264 SimTK_FORCE_INLINE const T* cdata() const {return this->CBase::cdata();}
2267 SimTK_FORCE_INLINE const T* data() const {return this->CBase::cdata();}
2271 SimTK_FORCE_INLINE T* data() {return this->Base::data();}
2279 
2287 { return this->CBase::operator[](i); }
2288 
2297 
2302 const T& at(index_type i) const {return this->CBase::at(i);}
2303 
2308 T& at(index_type i) {return const_cast<T&>(this->Base::at(i));}
2309 
2313 { return this->CBase::getElt(i); }
2317 
2323 SimTK_FORCE_INLINE const T& front() const {return this->CBase::front();}
2324 
2330 SimTK_FORCE_INLINE T& front() {return const_cast<T&>(this->Base::front());}
2331 
2337 SimTK_FORCE_INLINE const T& back() const {return this->CBase::back();}
2338 
2344 SimTK_FORCE_INLINE T& back() {return const_cast<T&>(this->Base::back());}
2345 
2349 { return CBase::operator()(index,length); }
2353 { return CBase::getSubArray(index,length); }
2354 
2358 { return Base::operator()(index,length); }
2362 { return Base::updSubArray(index,length); }
2366 //------------------------------------------------------------------------------
2372 
2399 void push_back(const T& value) {
2400  if (pallocated() == psize())
2401  growAtEnd(1,"Array_<T>::push_back(const T& value)");
2402  copyConstruct(end(), value);
2403  incrSize();
2404 }
2405 
2410 void push_back(T&& value) {
2411  if (pallocated() == psize())
2412  growAtEnd(1,"Array_<T>::push_back(T&& value)");
2413  moveConstruct(end(), std::move(value));
2414  incrSize();
2415 }
2416 
2425 template<class... Args>
2426 void emplace_back(Args&&... args) { // special syntax; not an rvalue reference
2427  if (pallocated() == psize())
2428  growAtEnd(1,"Array_<T>::emplace_back(Args...)");
2429  new(end()) T(std::forward<Args>(args)...); // invoke constructor for T
2430  incrSize();
2431 }
2432 
2450 void push_back() {
2451  if (pallocated() == psize())
2452  growAtEnd(1,"Array_<T>::push_back()");
2453  defaultConstruct(end());
2454  incrSize();
2455 }
2456 
2478  if (pallocated() == psize())
2479  growAtEnd(1,"Array_<T>::raw_push_back()");
2480  T* const p = end();
2481  incrSize();
2482  return p;
2483 }
2484 
2487 void pop_back() {
2488  SimTK_ERRCHK(!empty(), "Array_<T>::pop_back()", "Array was empty.");
2489  destruct(&back());
2490  decrSize();
2491 }
2492 
2510 T* erase(T* first, const T* last1) {
2511  SimTK_ERRCHK(begin() <= first && first <= last1 && last1 <= end(),
2512  "Array_<T>::erase(first,last1)", "Pointers out of range or out of order.");
2513 
2514  const size_type nErased = size_type(last1-first);
2515  SimTK_ERRCHK(isOwner() || nErased==0, "Array_<T>::erase(first,last1)",
2516  "No elements can be erased from a non-owner array.");
2517 
2518  if (nErased) {
2519  destruct(first, last1); // Destruct the elements we're erasing.
2520  moveElementsDown(first+nErased, nErased); //Compress followers into gap.
2521  setSize(size()-nErased);
2522  }
2523  return first;
2524 }
2525 
2545 T* erase(T* p) {
2546  SimTK_ERRCHK(begin() <= p && p < end(),
2547  "Array_<T>::erase(p)", "Pointer must point to a valid element.");
2548  SimTK_ERRCHK(isOwner(), "Array_<T>::erase(p)",
2549  "No elements can be erased from a non-owner array.");
2550 
2551  destruct(p); // Destruct the element we're erasing.
2552  moveElementsDown(p+1, 1); // Compress followers into the gap.
2553  decrSize();
2554  return p;
2555 }
2556 
2557 
2578 T* eraseFast(T* p) {
2579  SimTK_ERRCHK(begin() <= p && p < end(),
2580  "Array_<T>::eraseFast(p)", "Pointer must point to a valid element.");
2581  SimTK_ERRCHK(isOwner(), "Array_<T>::eraseFast(p)",
2582  "No elements can be erased from a non-owner array.");
2583 
2584  destruct(p);
2585  if (p+1 != end())
2586  moveOneElement(p, &back());
2587  decrSize();
2588  return p;
2589 }
2590 
2598 void clear() {
2599  SimTK_ERRCHK(isOwner() || empty(), "Array_<T>::clear()",
2600  "clear() is not allowed for a non-owner array.");
2601  destruct(begin(), end());
2602  setSize(0);
2603 }
2604 
2605 
2632 T* insert(T* p, size_type n, const T& value) {
2633  T* const gap = insertGapAt(p, n, "Array_<T>::insert(p,n,value)");
2634  // Copy construct into the inserted elements and note the size change.
2635  fillConstruct(gap, gap+n, value);
2636  setSize(size()+n);
2637  return gap;
2638 }
2639 
2644 T* insert(T* p, const T& value) {
2645  T* const gap = insertGapAt(p, 1, "Array_<T>::insert(p,value)");
2646  // Copy construct into the inserted element and note the size change.
2647  copyConstruct(gap, value);
2648  incrSize();
2649  return gap;
2650 }
2651 
2657 template <class... Args>
2658 T* emplace(T* p, Args&&... args) { // special syntax; not an rvalue reference
2659  T* const gap = insertGapAt(p, 1, "Array_<T>::emplace(p,Args...)");
2660  // Construct into the inserted element and note the size change.
2661  new(gap) T(std::forward<Args>(args)...); // invoke the constructor
2662  incrSize();
2663  return gap;
2664 }
2665 
2695 template <class T2>
2696 T* insert(T* p, const T2* first, const T2* last1) {
2697  const char* methodName = "Array_<T>::insert(T* p, T2* first, T2* last1)";
2698  SimTK_ERRCHK((first&&last1) || (first==last1), methodName,
2699  "One of first or last1 was null; either both or neither must be null.");
2700  SimTK_ERRCHK(!this->overlapsWithData(first,last1), methodName,
2701  "Source range can't overlap with the current array contents.");
2702  // Pointers are random access iterators.
2703  return insertIteratorDispatch(p, first, last1,
2704  std::random_access_iterator_tag(),
2705  methodName);
2706 }
2707 
2710 template <class Iter>
2711 T* insert(T* p, const Iter& first, const Iter& last1) {
2712  return insertDispatch(p, first, last1,
2713  typename IsIntegralType<Iter>::Result(),
2714  "Array_<T>::insert(T* p, Iter first, Iter last1)");
2715 }
2720 //------------------------------------------------------------------------------
2721  private:
2722 //------------------------------------------------------------------------------
2723 
2724 
2725 // This method is used when we have already decided we need to make room for
2726 // some new elements by reallocation, by creating a gap somewhere within the
2727 // existing data. We'll issue an error message if this would violate the
2728 // max_size restriction (we can afford to do that even in a Release build since
2729 // we don't expect to grow very often). Otherwise we'll allocate some more space
2730 // and move construct the existing elements into the new space, leaving a gap
2731 // where indicated. Note that this method does not change the current size but
2732 // does change the capacity.
2733 //
2734 // The gapPos must point within the existing data with null OK if the array
2735 // itself is null, and end() being OK any time although you should use the
2736 // more specialized growAtEnd() method if you know that's what's happening.
2737 //
2738 // Don't call this with a gapSz of zero.
2739 T* growWithGap(T* gapPos, size_type gapSz, const char* methodName) {
2740  assert(gapSz > 0); // <= 0 is a bug, not a user error
2741 
2742  // Note that gapPos may be null if begin() and end() are also.
2743  SimTK_ERRCHK(begin() <= gapPos && gapPos <= end(), methodName,
2744  "Given insertion point is not valid for this array.");
2745 
2746  // Get some new space of a reasonable size.
2747  setAllocated(calcNewCapacityForGrowthBy(gapSz, methodName));
2748  T* newData = allocN(allocated());
2749 
2750  // How many elements will be before the gap?
2751  const size_type nBefore = (size_type)(gapPos-begin());
2752 
2753  // Locate the gap in the new space allocation.
2754  T* newGap = newData + nBefore;
2755  T* newGapEnd = newGap + gapSz; // one past the last element in the gap
2756 
2757  // Move elements before insertion point; destruct source as we go.
2758  moveConstructThenDestructSource(newData, newGap, data());
2759  // Move/destruct elements at and after insertion pt; leave gapSz gap.
2760  moveConstructThenDestructSource(newGapEnd, newData+size(), gapPos);
2761 
2762  // Throw away the old data and switch to the new.
2763  freeN(data()); setData(newData);
2764  return newGap;
2765 }
2766 
2767 // Same as growWithGap(end(), n, methodName); see above.
2768 void growAtEnd(size_type n, const char* methodName) {
2769  assert(n > 0); // <= 0 is a bug, not a user error
2770  // Get some new space of a reasonable size.
2771  setAllocated(calcNewCapacityForGrowthBy(n, methodName));
2772  T* newData = allocN(allocated());
2773  // Copy all the elements; destruct source as we go.
2774  moveConstructThenDestructSource(newData, newData+size(), data());
2775  // Throw away the old data and switch to the new.
2776  freeN(data()); setData(newData);
2777 }
2778 
2779 // This method determines how much we should increase the array's capacity
2780 // when asked to insert n elements, due to an insertion or push_back. We will
2781 // generally allocate more new space than requested, in anticipation of
2782 // further insertions. This has to be based on the current size so that only
2783 // log(n) reallocations are performed to insert n elements one at a time. Our
2784 // policy here is to at least double the capacity unless that would exceed
2785 // max_size(). There is also a minimum amount of allocation we'll do if the
2786 // current size is zero or very small.
2787 size_type calcNewCapacityForGrowthBy(size_type n, const char* methodName) const {
2788  SimTK_ERRCHK3_ALWAYS(isGrowthOK(n), methodName,
2789  "Can't grow this Array by %llu element(s) because it would"
2790  " then exceed the max_size of %llu set by its index type %s.",
2791  (unsigned long long)n, ullMaxSize(), indexName());
2792 
2793  // At this point we know that capacity()+n <= max_size().
2794  const size_type mustHave = capacity() + n;
2795 
2796  // Be careful not to overflow size_type as you could if you
2797  // double capacity() rather than halving max_size().
2798  const size_type wantToHave = capacity() <= max_size()/2
2799  ? 2*capacity()
2800  : max_size();
2801 
2802  const size_type newCapacity = std::max(std::max(mustHave,wantToHave),
2803  minAlloc());
2804  return newCapacity;
2805 }
2806 
2807 // Insert an unconstructed gap of size n beginning at position p. The return
2808 // value is a pointer to the first element in the gap. It will be p if no
2809 // reallocation occurred, otherwise it will be pointing into the new data.
2810 // On return size() will be unchanged although allocated() may be bigger.
2811 T* insertGapAt(T* p, size_type n, const char* methodName) {
2812  // Note that p may be null if begin() and end() are also.
2813  SimTK_ERRCHK(begin() <= p && p <= end(), methodName,
2814  "Given insertion point is not valid for this Array.");
2815 
2816  if (n==0) return p; // nothing to do
2817 
2818  SimTK_ERRCHK_ALWAYS(isOwner(), methodName,
2819  "No elements can be inserted into a non-owner array.");
2820 
2821  // Determine the number of elements before the insertion point and
2822  // the number at or afterwards (those must be moved up by one slot).
2823  const size_type before = (size_type)(p-begin()), after = (size_type)(end()-p);
2824 
2825  // Grow the container if necessary. Note that if we have to grow we
2826  // can create the gap at the same time we copy the old elements over
2827  // to the new space.
2828  if (capacity() >= size()+n) {
2829  moveElementsUp(p, n); // leave a gap at p
2830  } else { // need to grow
2831  setAllocated(calcNewCapacityForGrowthBy(n, methodName));
2832  T* newdata = allocN(allocated());
2833  // Move the elements before the insertion point, and destroy source.
2834  moveConstructThenDestructSource(newdata, newdata+before, data());
2835  // Copy the elements at and after the insertion point, leaving a gap
2836  // of n elements.
2837  moveConstructThenDestructSource(newdata+before+n,
2838  newdata+before+n+after,
2839  p); // i.e., pData+before
2840  p = newdata + before; // points into newdata now
2841  freeN(data());
2842  setData(newdata);
2843  }
2844 
2845  return p;
2846 }
2847 
2848 //------------------------------------------------------------------------------
2849 // CTOR DISPATCH
2850 // This is the constructor implementation for when the class that matches
2851 // the alleged InputIterator type turns out to be one of the integral types
2852 // in which case this should be the ctor(n, initValue) constructor.
2853 template <class IntegralType> void
2854 ctorDispatch(IntegralType n, IntegralType v, TrueType isIntegralType) {
2855  new(this) Array_(size_type(n), value_type(v));
2856 }
2857 
2858 // This is the constructor implementation for when the class that matches
2859 // the alleged InputIterator type is NOT an integral type and may very well
2860 // be an iterator. In that case we split into iterators for which we can
2861 // determine the number of elements in advance (forward, bidirectional,
2862 // random access) and input iterators, for which we can't. Note: iterator
2863 // types are arranged hierarchically random->bi->forward->input with each
2864 // deriving from the one on its right, so the forward iterator tag also
2865 // matches bi and random.
2866 template <class InputIterator> void
2867 ctorDispatch(const InputIterator& first, const InputIterator& last1,
2868  FalseType isIntegralType)
2869 { ctorIteratorDispatch(first, last1,
2870  typename std::iterator_traits<InputIterator>::iterator_category()); }
2871 
2872 // This is the slow generic ctor implementation for any iterator that can't
2873 // make it up to forward_iterator capability (that is, an input_iterator).
2874 // The issue here is that we can't advance the iterator to count the number
2875 // of elements before allocating because input_iterators are consumed when
2876 // reference so we can't go back to look. That means we may have to reallocate
2877 // memory log n times as we "push back" these elements onto the array.
2878 template <class InputIterator> void
2879 ctorIteratorDispatch(const InputIterator& first, const InputIterator& last1,
2880  std::input_iterator_tag)
2881 {
2882  InputIterator src = first;
2883  while (src != last1) {
2884  // We can afford to check this always since we are probably doing I/O.
2885  // Throwing an exception in a constructor is tricky, though -- this
2886  // won't go through the Array_ destructor although it will call the
2887  // Base (ArrayView_) destructor. Since we have already allocated
2888  // some space, we must call deallocate() manually.
2889  if (size() == max_size()) {
2890  deallocate();
2891  SimTK_ERRCHK2_ALWAYS(!"too many elements",
2892  "Array_::ctor(InputIterator first, InputIterator last1)",
2893  "There were still source elements available when the array"
2894  " reached its maximum size of %llu as determined by its index"
2895  " type %s.", ullMaxSize(), indexName());
2896  }
2897  push_back(*src++);
2898  }
2899 }
2900 
2901 // This is the faster constructor implementation for iterator types for which
2902 // we can calculate the number of elements in advance. This will be optimal
2903 // for a random access iterator since we can count in constant time, but for
2904 // forward or bidirectional we'll have to advance n times to count and then
2905 // go back again to do the copy constructions.
2906 template <class ForwardIterator> void
2907 ctorIteratorDispatch(const ForwardIterator& first, const ForwardIterator& last1,
2908  std::forward_iterator_tag)
2909 {
2910  typedef typename std::iterator_traits<ForwardIterator>::difference_type
2912  // iterDistance() is constant time for random access iterators, but
2913  // O(last1-first) for forward and bidirectional since it has to increment
2914  // to count how far apart they are.
2915  const difference_type nInput = this->iterDistance(first,last1);
2916 
2917  SimTK_ERRCHK(nInput >= 0,
2918  "Array_(ForwardIterator first, ForwardIterator last1)",
2919  "Iterators were out of order.");
2920 
2921  SimTK_ERRCHK3(this->isSizeOK(nInput),
2922  "Array_(ForwardIterator first, ForwardIterator last1)",
2923  "Source has %llu elements but this array is limited to %llu"
2924  " elements by its index type %s.",
2925  this->ull(nInput), ullMaxSize(), indexName());
2926 
2927  const size_type n = size_type(nInput);
2928  setSize(n);
2929  allocateNoConstruct(n);
2930  copyConstruct(data(), data()+n, first);
2931 }
2932 
2933 //------------------------------------------------------------------------------
2934 // INSERT DISPATCH
2935 // This is the insert() implementation for when the class that matches
2936 // the alleged InputIterator type turns out to be one of the integral types
2937 // in which case this should be the insert(p, n, initValue) constructor.
2938 template <class IntegralType>
2939 T* insertDispatch(T* p, IntegralType n, IntegralType v,
2940  TrueType isIntegralType, const char*)
2941 { return insert(p, size_type(n), value_type(v)); }
2942 
2943 // This is the insert() implementation for when the class that matches
2944 // the alleged InputIterator type is NOT an integral type and may very well
2945 // be an iterator. See ctorDispatch() above for more information.
2946 template <class InputIterator>
2947 T* insertDispatch(T* p, const InputIterator& first, const InputIterator& last1,
2948  FalseType isIntegralType, const char* methodName)
2949 { return insertIteratorDispatch(p, first, last1,
2950  typename std::iterator_traits<InputIterator>::iterator_category(),
2951  methodName); }
2952 
2953 // This is the slow generic insert implementation for any iterator that can't
2954 // make it up to forward_iterator capability (that is, an input_iterator).
2955 // See ctorIteratorDispatch() above for more information.
2956 template <class InputIterator>
2957 T* insertIteratorDispatch(T* p, InputIterator first, InputIterator last1,
2958  std::input_iterator_tag, const char* methodName)
2959 {
2960  size_type nInserted = 0;
2961  while (first != last1) {
2962  // We can afford to check this always since we are probably doing I/O.
2963  SimTK_ERRCHK2_ALWAYS(size() < max_size(), methodName,
2964  "There were still source elements available when the array"
2965  " reached its maximum size of %llu as determined by its index"
2966  " type %s.", ullMaxSize(), indexName());
2967  p = insert(p, *first++); // p may now point to reallocated memory
2968  ++p; ++nInserted;
2969  }
2970  // p now points just after the last inserted element; subtract the
2971  // number inserted to get a pointer to the first inserted element.
2972  return p-nInserted;
2973 }
2974 
2975 // This is the faster insert implementation for iterator types for which
2976 // we can calculate the number of elements in advance. This will be optimal
2977 // for a random access iterator since we can count in constant time, but for
2978 // forward or bidirectional we'll have to advance n times to count and then
2979 // go back again to do the copy constructions.
2980 template <class ForwardIterator>
2981 T* insertIteratorDispatch(T* p, const ForwardIterator& first,
2982  const ForwardIterator& last1,
2983  std::forward_iterator_tag,
2984  const char* methodName)
2985 {
2986  typedef typename std::iterator_traits<ForwardIterator>::difference_type
2988  // iterDistance() is constant time for random access iterators, but
2989  // O(last1-first) for forward and bidirectional since it has to increment
2990  // to count how far apart they are.
2991  const difference_type nInput = this->iterDistance(first,last1);
2992 
2993  SimTK_ERRCHK(nInput >= 0, methodName, "Iterators were out of order.");
2994 
2995  SimTK_ERRCHK3(isGrowthOK(nInput), methodName,
2996  "Source has %llu elements which would make this array exceed the %llu"
2997  " elements allowed by its index type %s.",
2998  this->ull(nInput), ullMaxSize(), indexName());
2999 
3000  const size_type n = size_type(nInput);
3001  p = insertGapAt(p, n, methodName);
3002  copyConstruct(p, p+n, first);
3003  setSize(size()+n);
3004  return p;
3005 }
3006 
3007 //------------------------------------------------------------------------------
3008 // ASSIGN DISPATCH
3009 // This is the assign() implementation for when the class that matches
3010 // the alleged InputIterator type turns out to be one of the integral types
3011 // in which case this should be the assign(n, initValue) constructor.
3012 template <class IntegralType>
3013 void assignDispatch(IntegralType n, IntegralType v, TrueType isIntegralType,
3014  const char* methodName)
3015 { assign(size_type(n), value_type(v)); }
3016 
3017 // This is the assign() implementation for when the class that matches
3018 // the alleged InputIterator type is NOT an integral type and may very well
3019 // be an iterator. See ctorDispatch() above for more information.
3020 template <class InputIterator>
3021 void assignDispatch(const InputIterator& first, const InputIterator& last1,
3022  FalseType isIntegralType, const char* methodName)
3023 { assignIteratorDispatch(first, last1,
3024  typename std::iterator_traits<InputIterator>::iterator_category(),
3025  methodName); }
3026 
3027 // This is the slow generic implementation for a plain input_iterator
3028 // (i.e., not a forward, bidirectional, or random access iterator). These
3029 // have the unfortunate property that we can't count the elements in advance.
3030 template <class InputIterator>
3031 void assignIteratorDispatch(const InputIterator& first,
3032  const InputIterator& last1,
3033  std::input_iterator_tag,
3034  const char* methodName)
3035 {
3036  // TODO: should probably allow this and just blow up when the size()+1st
3037  // element is seen.
3038  SimTK_ERRCHK_ALWAYS(isOwner(), methodName,
3039  "Assignment to a non-owner array can only be done from a source"
3040  " designated with forward iterators or pointers because we"
3041  " must be able to verify that the source and destination sizes"
3042  " are the same.");
3043 
3044  clear(); // TODO: change space allocation here?
3045  InputIterator src = first;
3046  while (src != last1) {
3047  // We can afford to check this always since we are probably doing I/O.
3048  SimTK_ERRCHK2_ALWAYS(size() < max_size(), methodName,
3049  "There were still source elements available when the array"
3050  " reached its maximum size of %llu as determined by its index"
3051  " type %s.", ullMaxSize(), indexName());
3052 
3053  push_back(*src++);
3054  }
3055 }
3056 
3057 // This is the faster implementation that works for forward, bidirectional,
3058 // and random access iterators including ordinary pointers. We can check here that the
3059 // iterators are in the right order, and that the source is not too big to
3060 // fit in this array. Null pointer checks should be done prior to calling,
3061 // however, since iterators in general aren't pointers.
3062 template <class ForwardIterator>
3063 void assignIteratorDispatch(const ForwardIterator& first,
3064  const ForwardIterator& last1,
3065  std::forward_iterator_tag,
3066  const char* methodName)
3067 {
3068  typedef typename std::iterator_traits<ForwardIterator>::difference_type
3069  IterDiffType;
3070  // iterDistance() is constant time for random access iterators, but
3071  // O(last1-first) for forward and bidirectional since it has to increment
3072  // to count how far apart they are.
3073  const IterDiffType nInput = this->iterDistance(first,last1);
3074 
3075  SimTK_ERRCHK(nInput >= 0, methodName, "Iterators were out of order.");
3076 
3077  SimTK_ERRCHK3(this->isSizeOK(nInput), methodName,
3078  "Source has %llu elements but this Array is limited to %llu"
3079  " elements by its index type %s.",
3080  this->ull(nInput), ullMaxSize(), indexName());
3081 
3082  const size_type n = size_type(nInput);
3083  if (isOwner()) {
3084  // This is an owner Array; assignment is considered deallocation
3085  // followed by copy construction.
3086 
3087  clear(); // all elements destructed; allocation unchanged
3088  reallocateIfAdvisable(n); // change allocation if too small or too big
3089  copyConstruct(data(), cdata()+n, first);
3090  setSize(n);
3091  } else {
3092  // This is a non-owner Array. Assignment can occur only if the
3093  // source is the same size as the array, and the semantics are of
3094  // repeated assignment using T::operator=() not destruction followed
3095  // by copy construction.
3096  SimTK_ERRCHK2(n == size(), methodName,
3097  "Source has %llu elements which does not match the size %llu "
3098  "of the non-owner array it is being assigned into.",
3099  this->ull(n), ullSize());
3100 
3101  T* p = begin();
3102  ForwardIterator src = first;
3103  while (src != last1)
3104  *p++ = *src++; // call T's assignment operator
3105  }
3106 }
3107 
3108 // We are going to put a total of n elements into the Array (probably
3109 // because of an assignment or resize) and we want the space allocation
3110 // to be reasonable. That means of course that the allocation must be
3111 // *at least* n, but we also don't want it to be too big. Our policy
3112 // here is that if it is currently less than twice what we need we
3113 // won't reallocate, otherwise we'll shrink the space. When changing
3114 // the size to zero or something very small we'll treat the Array as
3115 // though its current size is minAlloc, meaning we won't reallocate
3116 // if the existing space is less than twice minAlloc.
3117 // nAllocated will be set appropriately; size() is not touched here.
3118 // No constructors or destructors are called.
3119 void reallocateIfAdvisable(size_type n) {
3120  if (allocated() < n || allocated()/2 > std::max(minAlloc(), n))
3121  reallocateNoDestructOrConstruct(n);
3122 }
3123 
3124 
3125 void allocateNoConstruct(size_type n)
3126 { setData(allocN(n)); setAllocated(n); } // size() left unchanged
3127 void deallocateNoDestruct()
3128 { freeN(data()); setData(0); setAllocated(0); } // size() left unchanged
3129 void reallocateNoDestructOrConstruct(size_type n)
3130 { deallocateNoDestruct(); allocateNoConstruct(n); }
3131 
3132 // This sets the smallest allocation we'll do when growing.
3133 size_type minAlloc() const
3134 { return std::min(max_size(), size_type(4)); }
3135 
3136 // Allocate without construction. Returns a null pointer if asked
3137 // to allocate 0 elements. In Debug mode we'll fill memory with
3138 // all 1's as a bug catcher.
3139 static T* allocN(size_type n) {
3140  if (n==0) return 0;
3141  unsigned char* newdata = new unsigned char[n * sizeof(T)];
3142  #ifndef NDEBUG
3143  unsigned char* b=newdata;
3144  const unsigned char* e=newdata+(n*sizeof(T));
3145  while (b != e) *b++ = 0xff;
3146  #endif
3147  return reinterpret_cast<T*>(newdata);
3148 }
3149 
3150 // Free memory without calling T's destructor. Nothing happens if passed
3151 // a null pointer.
3152 static void freeN(T* p) {
3153  delete[] reinterpret_cast<char*>(p);
3154 }
3155 
3156 // default construct one element
3157 static void defaultConstruct(T* p) {new(p) T();}
3158 // default construct range [b,e)
3159 static void defaultConstruct(T* b, const T* e)
3160 { while (b!=e) new(b++) T(); }
3161 
3162 // copy construct range [b,e) with repeats of a given value
3163 static void fillConstruct(T* b, const T* e, const T& v)
3164 { while(b!=e) new(b++) T(v); }
3165 
3166 // copy construct one element from a given value
3167 static void copyConstruct(T* p, const T& v) {new(p) T(v);}
3168 // move construct one element from a given value
3169 static void moveConstruct(T* p, T&& v) {new(p) T(std::move(v));}
3170 
3171 // copy construct range [b,e) from sequence of source values
3172 static void copyConstruct(T* b, const T* e, T* src)
3173 { while(b!=e) new(b++) T(*src++); }
3174 // move construct range [b,e) from sequence of source values
3175 static void moveConstruct(T* b, const T* e, T* src)
3176 { while(b!=e) new(b++) T(std::move(*src++)); }
3177 
3178 // Templatized copy construct will work if the source elements are
3179 // assignment compatible with the destination elements.
3180 template <class InputIterator>
3181 static void copyConstruct(T* b, const T* e, InputIterator src)
3182 { while(b!=e) new(b++) T(*src++); }
3183 
3184 // Copy construct range [b,e] from sequence of source values and
3185 // destruct the source after it is copied. It's better to alternate
3186 // copying and destructing than to do this in two passes since we
3187 // will already have touched the memory.
3188 static void copyConstructThenDestructSource(T* b, const T* e, T* src)
3189 { while(b!=e) {new(b++) T(*src); src++->~T();} }
3190 
3191 // Move construct range [b,e] from sequence of source values and
3192 // destruct the source after it is copied. It's better to alternate
3193 // moving and destructing than to do this in two passes since we
3194 // will already have touched the memory.
3195 static void moveConstructThenDestructSource(T* b, const T* e, T* src)
3196 { while(b!=e) {new(b++) T(std::move(*src)); src++->~T();} }
3197 
3198 // We have an element at from that we would like to move into the currently-
3199 // unconstructed slot at to. Both from and to are expected to be pointing to
3200 // elements within the currently allocated space. From's slot will be left
3201 // unconstructed.
3202 void moveOneElement(T* to, T* from) {
3203  assert(data() <= to && to < data()+allocated());
3204  assert(data() <= from && from < data()+allocated());
3205  moveConstruct(to, std::move(*from));
3206  destruct(from);
3207 }
3208 
3209 
3210 // Move elements from p to end() down by n>0 places to fill an unconstructed
3211 // gap beginning at p-n. Any leftover space at the end will be unconstructed.
3212 void moveElementsDown(T* p, size_type n) {
3213  assert(n > 0);
3214  for (; p != end(); ++p)
3215  moveOneElement(p-n,p);
3216 }
3217 
3218 // Move elements from p to end() up by n>0 places to make an unconstructed gap
3219 // at [p,p+n). Note that this has to be done backwards so that we don't
3220 // write on any elements until after they've been copied.
3221 void moveElementsUp(T* p, size_type n) {
3222  assert(n > 0);
3223  T* src = end(); // points one past source element (begin()-1 not allowed)
3224  while (src != p) {
3225  --src; // now points to source
3226  moveOneElement(src+n, src);;
3227  }
3228 }
3229 
3230 // destruct one element
3231 static void destruct(T* p) {p->~T();}
3232 // destruct range [b,e)
3233 static void destruct(T* b, const T* e)
3234 { while(b!=e) b++->~T(); }
3235 
3236 // Check that growing this array by n elements wouldn't cause it to exceed
3237 // its allowable maximum size.
3238 template <class S>
3239 bool isGrowthOK(S n) const
3240 { return this->isSizeOK(ullCapacity() + this->ull(n)); }
3241 
3242 // The following private methods are protected methods in the ArrayView base
3243 // class, so they should not need repeating here. However, we explicitly
3244 // forward to the Base methods to avoid gcc errors. The gcc complaint
3245 // is due to their not depending on any template parameters; the "this->"
3246 // apparently fixes that problem.
3247 
3248 // These provide direct access to the data members.
3249 packed_size_type psize() const {return this->CBase::psize();}
3250 packed_size_type pallocated() const {return this->CBase::pallocated();}
3251 
3252 void setData(const T* p) {this->CBase::setData(p);}
3253 void setSize(size_type n) {this->CBase::setSize(n);}
3254 void incrSize() {this->CBase::incrSize();}
3255 void decrSize() {this->CBase::decrSize();}
3256 void setAllocated(size_type n) {this->CBase::setAllocated(n);}
3257 // This just cast sizes to unsigned long long so that we can do comparisons
3258 // without getting warnings.
3259 unsigned long long ullSize() const
3260 { return this->CBase::ullSize(); }
3261 unsigned long long ullCapacity() const
3262 { return this->CBase::ullCapacity(); }
3263 unsigned long long ullMaxSize() const
3264 { return this->CBase::ullMaxSize(); }
3265 // This is the index type name and is handy for error messages to explain
3266 // why some size was too big.
3267 const char* indexName() const {return this->CBase::indexName();}
3268 };
3269 
3270 
3271 // This "private" static method is used to implement ArrayView's
3272 // fillArrayViewFromStream() and Array's readArrayFromStream() namespace-scope
3273 // static methods, which are in turn used to implement ArrayView's and
3274 // Array's stream extraction operators ">>". This method has to be in the
3275 // header file so that we don't need to pass streams through the API, but it
3276 // is not intended for use by users and has no Doxygen presence, unlike
3277 // fillArrayFromStream() and readArrayFromStream() and (more commonly)
3278 // the extraction operators.
3279 template <class T, class X> static inline
3280 std::istream& readArrayFromStreamHelper
3281  (std::istream& in, bool isFixedSize, Array_<T,X>& out)
3282 {
3283  // If already failed, bad, or eof, set failed bit and return without
3284  // touching the Array.
3285  if (!in.good()) {in.setstate(std::ios::failbit); return in;}
3286 
3287  // If the passed-in Array isn't an owner, then we have to treat it as
3288  // a fixed size ArrayView regardless of the setting of the isFixedSize
3289  // argument.
3290  if (!out.isOwner())
3291  isFixedSize = true; // might be overriding the argument here
3292 
3293  // numRequired will be ignored unless isFixedSize==true.
3294  const typename Array_<T,X>::size_type
3295  numRequired = isFixedSize ? out.size() : 0;
3296 
3297  if (!isFixedSize)
3298  out.clear(); // We're going to replace the entire contents of the Array.
3299 
3300  // Skip initial whitespace. If that results in eof this may be a successful
3301  // read of a 0-length, unbracketed Array. That is OK for either a
3302  // variable-length Array or a fixed-length ArrayView of length zero.
3303  std::ws(in); if (in.fail()) return in;
3304  if (in.eof()) {
3305  if (isFixedSize && numRequired != 0)
3306  in.setstate(std::ios_base::failbit); // zero elements not OK
3307  return in;
3308  }
3309 
3310  // Here the stream is good and the next character is non-white.
3311  assert(in.good());
3312 
3313  // Use this for raw i/o (peeks and gets).
3314  typename std::iostream::int_type ch;
3315 
3316  #ifndef NDEBUG // avoid unused variable warnings in Release
3317  const typename std::iostream::int_type EOFch =
3318  std::iostream::traits_type::eof();
3319  #endif
3320 
3321  // Now see if the sequence is bare or surrounded by (), [], or {}.
3322  bool lookForCloser = true;
3323  ch = in.peek(); if (in.fail()) return in;
3324  assert(ch != EOFch); // we already checked above
3325 
3326  char openBracket{static_cast<char>(ch)}, closeBracket{};
3327  if (openBracket=='(') {in.get(); closeBracket = ')';}
3328  else if (openBracket=='[') {in.get(); closeBracket = ']';}
3329  else if (openBracket=='{') {in.get(); closeBracket = '}';}
3330  else lookForCloser = false;
3331 
3332  // If lookForCloser is true, then closeBracket contains the terminating
3333  // delimiter, otherwise we're not going to quit until eof.
3334 
3335  // Eat whitespace after the opening bracket to see what's next.
3336  if (in.good()) std::ws(in);
3337 
3338  // If we're at eof now it must be because the open bracket was the
3339  // last non-white character in the stream, which is an error.
3340  if (!in.good()) {
3341  if (in.eof()) {
3342  assert(lookForCloser); // or we haven't read anything that could eof
3343  in.setstate(std::ios::failbit);
3344  }
3345  return in;
3346  }
3347 
3348  // istream is good and next character is non-white; ready to read first
3349  // value or terminator.
3350 
3351  // We need to figure out whether the elements are space- or comma-
3352  // separated and then insist on consistency.
3353  bool commaOK = true, commaRequired = false;
3354  bool terminatorSeen = false;
3355  X nextIndex(0);
3356  while (true) {
3357  char c;
3358 
3359  // Here at the top of this loop, we have already successfully read
3360  // n=nextIndex values of type T. For fixed-size reads, it might be
3361  // the case that n==numRequired already, but we still may need to
3362  // look for a closing bracket before we can declare victory.
3363  // The stream is good() (not at eof) but it might be the case that
3364  // there is nothing but white space left; we don't know yet because
3365  // if we have satisfied the fixed-size count and are not expecting
3366  // a terminator then we should quit without absorbing the trailing
3367  // white space.
3368  assert(in.good());
3369 
3370  // Look for closing bracket before trying to read value.
3371  if (lookForCloser) {
3372  // Eat white space to find the closing bracket.
3373  std::ws(in); if (!in.good()) break; // eof?
3374  ch = in.peek(); assert(ch != EOFch);
3375  if (!in.good()) break;
3376  c = (char)ch;
3377  if (c == closeBracket) {
3378  in.get(); // absorb the closing bracket
3379  terminatorSeen = true;
3380  break;
3381  }
3382  // next char not a closing bracket; fall through
3383  }
3384 
3385  // We didn't look or didn't find a closing bracket. The istream is good
3386  // but we might be looking at white space.
3387 
3388  // If we already got all the elements we want, break for final checks.
3389  if (isFixedSize && (nextIndex == numRequired))
3390  break; // that's a full count.
3391 
3392  // Look for comma before value, except the first time.
3393  if (commaOK && nextIndex != 0) {
3394  // Eat white space to find the comma.
3395  std::ws(in); if (!in.good()) break; // eof?
3396  ch = in.peek(); assert(ch != EOFch);
3397  if (!in.good()) break;
3398  c = (char)ch;
3399  if (c == ',') {
3400  in.get(); // absorb comma
3401  commaRequired = true; // all commas from now on
3402  } else { // next char not a comma
3403  if (commaRequired) // bad, e.g.: v1, v2, v3 v4
3404  { in.setstate(std::ios::failbit); break; }
3405  else commaOK = false; // saw: v1 v2 (no commas now)
3406  }
3407  if (!in.good()) break; // might be eof
3408  }
3409 
3410  // No closing bracket yet; don't have enough elements; skipped comma
3411  // if any; istream is good; might be looking at white space.
3412  assert(in.good());
3413 
3414  // Now read in an element of type T.
3415  // The extractor T::operator>>() will ignore leading white space.
3416  if (!isFixedSize)
3417  out.push_back(); // grow by one (default consructed)
3418  in >> out[nextIndex]; if (in.fail()) break;
3419  ++nextIndex;
3420 
3421  if (!in.good()) break; // might be eof
3422  }
3423 
3424  // We will get here under a number of circumstances:
3425  // - the fail bit is set in the istream, or
3426  // - we reached eof
3427  // - we saw a closing brace
3428  // - we got all the elements we wanted (for a fixed-size read)
3429  // Note that it is possible that we consumed everything except some
3430  // trailing white space (meaning we're not technically at eof), but
3431  // for consistency with built-in operator>>()'s we won't try to absorb
3432  // that trailing white space.
3433 
3434  if (!in.fail()) {
3435  if (lookForCloser && !terminatorSeen)
3436  in.setstate(std::ios::failbit); // missing terminator
3437 
3438  if (isFixedSize && nextIndex != numRequired)
3439  in.setstate(std::ios::failbit); // wrong number of values
3440  }
3441 
3442  return in;
3443 }
3444 
3445 
3446 
3447 //------------------------------------------------------------------------------
3448 // RELATED GLOBAL OPERATORS
3449 //------------------------------------------------------------------------------
3450 // These are logically part of the Array_<T,X> class but are not actually
3451 // class members; that is, they are in the SimTK namespace.
3452 
3453 // Some of the serialization methods could have been member functions but
3454 // then an attempt to explicitly instantiate the whole Array_<T> class for
3455 // some type T would fail if T did not support the requisite I/O operations
3456 // even if those operations were never used. This came up when Chris Bruns was
3457 // trying to wrap Array objects for Python, which requires explicit
3458 // instantiation.
3459 
3467 
3471 template <class T, class X> inline void
3472 writeUnformatted(std::ostream& o, const Array_<T,X>& v) {
3473  for (X i(0); i < v.size(); ++i) {
3474  if (i != 0) o << " ";
3475  writeUnformatted(o, v[i]);
3476  }
3477 }
3478 
3479 
3483 template <class T, class X> inline void
3484 writeFormatted(std::ostream& o, const Array_<T,X>& v) {
3485  o << '(';
3486  for (X i(0); i < v.size(); ++i) {
3487  if (i != 0) o << ',';
3488  writeFormatted(o, v[i]);
3489  }
3490  o << ')';
3491 }
3492 
3499 template <class T, class X> inline
3500 std::ostream&
3501 operator<<(std::ostream& o,
3502  const ArrayViewConst_<T,X>& a)
3503 {
3504  o << '(';
3505  if (!a.empty()) {
3506  o << a.front();
3507  for (const T* p = a.begin()+1; p != a.end(); ++p)
3508  o << ',' << *p;
3509  }
3510  return o << ')';
3511 }
3512 
3513 
3517 template <class T, class X> inline bool
3518 readUnformatted(std::istream& in, Array_<T,X>& v) {
3519  v.clear();
3520  T element;
3521  std::ws(in); // Make sure we're at eof if stream is all whitespace.
3522  while (!in.eof() && readUnformatted(in, element))
3523  v.push_back(element);
3524  return !in.fail(); // eof is expected and ok
3525 }
3526 
3531 template <class T, class X> inline bool
3532 readUnformatted(std::istream& in, ArrayView_<T,X>& v) {
3533  for (X i(0); i < v.size(); ++i)
3534  if (!readUnformatted(in, v[i])) return false;
3535  return true;
3536 }
3537 
3538 
3544 template <class T, class X> inline bool
3545 readFormatted(std::istream& in, Array_<T,X>& v) {
3546  return !readArrayFromStream(in,v).fail();
3547 }
3548 
3554 template <class T, class X> inline bool
3555 readFormatted(std::istream& in, ArrayView_<T,X>& v) {
3556  return !fillArrayViewFromStream(in,v).fail();
3557 }
3558 
3588 template <class T, class X> static inline
3589 std::istream& readArrayFromStream(std::istream& in, Array_<T,X>& out)
3590 { return readArrayFromStreamHelper<T,X>(in, false /*variable sizez*/, out); }
3591 
3592 
3593 
3618 template <class T, class X> static inline
3619 std::istream& fillArrayFromStream(std::istream& in, Array_<T,X>& out)
3620 { return readArrayFromStreamHelper<T,X>(in, true /*fixed size*/, out); }
3621 
3626 template <class T, class X> static inline
3627 std::istream& fillArrayViewFromStream(std::istream& in, ArrayView_<T,X>& out)
3628 { return readArrayFromStreamHelper<T,X>(in, true /*fixed size*/, out); }
3629 
3630 
3631 
3632 
3642 template <class T, class X> inline
3643 std::istream& operator>>(std::istream& in, Array_<T,X>& out)
3644 { return readArrayFromStream<T,X>(in, out); }
3645 
3653 template <class T, class X> inline
3654 std::istream& operator>>(std::istream& in, ArrayView_<T,X>& out)
3655 { return fillArrayViewFromStream<T,X>(in, out); }
3656 
3666 
3669 template <class T1, class X1, class T2, class X2> inline bool
3671  // Avoid warnings in size comparison by using common type.
3672  const ptrdiff_t sz1 = a1.end()-a1.begin();
3673  const ptrdiff_t sz2 = a2.end()-a2.begin();
3674  if (sz1 != sz2) return false;
3675  const T1* p1 = a1.begin();
3676  const T2* p2 = a2.begin();
3677  while (p1 != a1.end())
3678  if (!(*p1++ == *p2++)) return false;
3679  return true;
3680 }
3683 template <class T1, class X1, class T2, class X2> inline bool
3685 { return !(a1 == a2); }
3686 
3691 template <class T1, class X1, class T2, class X2> inline bool
3692 operator<(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2) {
3693  const T1* p1 = a1.begin();
3694  const T2* p2 = a2.begin();
3695  while (p1 != a1.end() && p2 != a2.end()) {
3696  if (!(*p1 == *p2))
3697  return *p1 < *p2; // otherwise p1 > p2
3698  ++p1; ++p2;
3699  }
3700  // All elements were equal until one or both arrays ran out of elements.
3701  // a1 is less than a2 only if a1 ran out and a2 didn't.
3702  return p1 == a1.end() && p2 != a2.end();
3703 }
3706 template <class T1, class X1, class T2, class X2> inline bool
3708 { return !(a1 < a2); }
3712 template <class T1, class X1, class T2, class X2> inline bool
3714 { return a2 < a1; }
3717 template <class T1, class X1, class T2, class X2> inline bool
3718 operator<=(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2)
3719 { return !(a1 > a2); }
3720 
3724 template <class T1, class X1, class T2, class A2> inline bool
3725 operator==(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3726 { return a1 == ArrayViewConst_<T2,size_t>(v2); }
3727 
3731 template <class T1, class A1, class T2, class X2> inline bool
3732 operator==(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3733 { return a2 == v1; }
3734 
3737 template <class T1, class X1, class T2, class A2> inline bool
3738 operator!=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3739 { return !(a1 == v2); }
3742 template <class T1, class A1, class T2, class X2> inline bool
3743 operator!=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3744 { return !(a2 == v1); }
3745 
3751 template <class T1, class X1, class T2, class A2> inline bool
3752 operator<(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3753 { return a1 < ArrayViewConst_<T2,size_t>(v2); }
3754 
3760 template <class T1, class A1, class T2, class X2> inline bool
3761 operator<(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3762 { return ArrayViewConst_<T1,size_t>(v1) < a2; }
3763 
3766 template <class T1, class X1, class T2, class A2> inline bool
3767 operator>=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3768 { return !(a1 < v2); }
3771 template <class T1, class A1, class T2, class X2> inline bool
3772 operator>=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3773 { return !(v1 < a2); }
3774 
3778 template <class T1, class X1, class T2, class A2> inline bool
3779 operator>(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3780 { return v2 < a1; }
3784 template <class T1, class A1, class T2, class X2> inline bool
3785 operator>(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3786 { return a2 < v1; }
3787 
3790 template <class T1, class X1, class T2, class A2> inline bool
3791 operator<=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3792 { return !(a1 > v2); }
3795 template <class T1, class A1, class T2, class X2> inline bool
3796 operator<=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3797 { return !(v1 > a2); }
3798 
3801 } // namespace SimTK
3802 
3803 namespace std {
3807 template <class T, class X> inline void
3809  a1.swap(a2);
3810 }
3811 
3812 } // namespace std
3813 
3814 #endif // SimTK_SimTKCOMMON_ARRAY_H_
const T & front() const
Return a const reference to the first element in this array, which must not be empty.
Definition: Array.h:1114
static size_type max_size()
Definition: Array.h:245
size_type size() const
Return the current number of elements stored in this array.
Definition: Array.h:513
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:3472
T & back()
Return a writable reference to the last element in this array, which must not be empty.
Definition: Array.h:1135
This Array_ helper class is the base class for Array_, extending ArrayViewConst_ to add the ability t...
Definition: Array.h:52
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:3532
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:1956
unsigned char size_type
Definition: Array.h:226
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:935
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:358
static size_type max_size()
Definition: Array.h:205
static size_type max_size()
Definition: Array.h:217
size_type max_size() const
Return the maximum allowable size for this array.
Definition: Array.h:2077
#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:1852
bool empty() const
Return true if there are no elements currently stored in this array.
Definition: Array.h:2080
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:2248
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:3779
T value_type
The type of object stored in this container.
Definition: Array.h:335
void push_back(T &&value)
This is the move form of push_back(), taking an rvalue reference rather than an lvalue reference...
Definition: Array.h:2410
#define SimTK_SIZECHECK(sz, maxsz, where)
Definition: ExceptionMacros.h:146
ArrayView_()
Default constructor allocates no heap space and is very fast.
Definition: Array.h:879
const T & at(index_type i) const
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:562
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:3725
size_type size() const
Return the current number of elements stored in this array.
Definition: Array.h:2075
unsigned long long size_type
Definition: Array.h:234
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: Array.h:863
~ArrayViewConst_()
The destructor just disconnects the array view handle from its data; see disconnect() for more inform...
Definition: Array.h:498
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:2312
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:1673
T * iterator
A writable iterator for this container (same as pointer here).
Definition: Array.h:347
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:1224
const T * data() const
The const version of the data() method is identical to cdata().
Definition: Array.h:2267
signed char difference_type
Definition: Array.h:216
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:607
Array_(Array_ &&src)
Move constructor swaps in the source and leaves the source default constructed.
Definition: Array.h:1662
This is a special type used for causing invocation of a particular constructor or method overload tha...
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:670
const T & back() const
Return a const reference to the last element in this array, which must not be empty.
Definition: Array.h:1128
#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:1818
size_type capacity() const
Return the number of elements this array can currently hold without requiring reallocation.
Definition: Array.h:524
const_reverse_iterator rbegin() const
The const version of rbegin() is the same as crbegin().
Definition: Array.h:662
std::reverse_iterator< iterator > reverse_iterator
Definition: Array.h:1542
const T & operator[](index_type i) const
Select an element by its index, returning a const reference.
Definition: Array.h:2286
T & reference
Definition: Array.h:1538
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:1877
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:176
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:3518
long size_type
Definition: Array.h:160
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:461
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:2091
int difference_type
Definition: Array.h:128
T * iterator
Definition: Array.h:860
Array_(size_type n)
Construct an array containing n default-constructed elements.
Definition: Array.h:1566
char size_type
Definition: Array.h:215
This templatized type is used by the Array_<T,X> classes to obtain the information they need to use t...
Definition: Array.h:50
const T & const_reference
A const value_type reference.
Definition: Array.h:345
static size_type max_size()
Definition: Array.h:228
T * pointer
A writable pointer to a value_type.
Definition: Array.h:339
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:2212
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:1598
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:3743
unsigned long size_type
Definition: Array.h:147
long long difference_type
Definition: Array.h:244
T * pointer
Definition: Array.h:1536
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:535
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:2243
const T * data() const
The const version of the data() method is identical to cdata().
Definition: Array.h:674
STL namespace.
T value_type
Definition: Array.h:854
const T * begin() const
The const version of begin() is the same as cbegin().
Definition: Array.h:1190
const T * end() const
The const version of end() is the same as cend().
Definition: Array.h:1203
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:2308
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:2348
const T & at(index_type i) const
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:1092
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:3713
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:2644
ArrayIndexPackType< size_type >::packed_size_type packed_size_type
Definition: Array.h:867
#define SimTK_ASSERT(cond, msg)
Definition: ExceptionMacros.h:373
const T * begin() const
The const version of begin() is the same as cbegin().
Definition: Array.h:2214
unsigned size_type
Definition: Array.h:127
void pop_back()
Remove the last element from this array, which must not be empty.
Definition: Array.h:2487
ArrayIndexTraits< X >::size_type size_type
Definition: Array.h:1544
T * raw_push_back()
(Deprecated, use emplace_back() instead) This dangerous non-standard method increases the Array&#39;s siz...
Definition: Array.h:2477
const T & front() const
Return a const reference to the first element in this array, which must not be empty.
Definition: Array.h:2323
ArrayView_(std::vector< T, A > &v)
Construct to reference memory owned by a writable std::vector.
Definition: Array.h:889
#define SimTK_ERRCHK3(cond, whereChecked, fmt, a1, a2, a3)
Definition: ExceptionMacros.h:330
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:1636
ArrayIndexTraits< X >::size_type size_type
Definition: Array.h:864
const T & at(index_type i) const
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:2302
ArrayViewConst_(const ArrayViewConst_ &src)
Copy constructor is shallow; the constructed const array object will be referencing the original sour...
Definition: Array.h:384
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:1994
~Array_()
The destructor performs a deallocate() operation which may result in element destruction and freeing ...
Definition: Array.h:1741
short difference_type
Definition: Array.h:193
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:672
T * begin()
Return a writable pointer to the first element of this array if any, otherwise end().
Definition: Array.h:1195
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:1169
static size_type max_size()
Definition: Array.h:236
ArrayViewConst_()
Default constructor allocates no heap space and is very fast.
Definition: Array.h:373
bool isOwner() const
Definition: Array.h:1268
T & reference
A writable value_type reference.
Definition: Array.h:343
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:2510
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:1102
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:2194
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:2352
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:3589
T & operator[](index_type i)
Select an element by its index, returning a writable (lvalue) reference.
Definition: Array.h:1085
X index_type
Definition: Array.h:855
Array_ & operator=(const std::vector< T2, A > &src)
This is assignment from a source std::vector<T2>.
Definition: Array.h:1969
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:923
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:1576
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:1212
This is a compile-time equivalent of "false", used in compile-time condition checking in templatized ...
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:678
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:2016
bool empty() const
Definition: Array.h:1265
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:2545
int difference_type
Definition: Array.h:135
const T * const_iterator
Definition: Array.h:861
const_reverse_iterator rend() const
The const version of rend() is the same as crend().
Definition: Array.h:2251
T & at(index_type i)
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:1098
static const char * name()
The default implementation of name() here returns the raw result from `typeid(T). ...
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:862
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: Array.h:1543
ArrayView_ & operator=(const T &fillValue)
Fill assignment – all elements are set to fillValue.
Definition: Array.h:968
const T * begin() const
The const version of begin() is the same as cbegin().
Definition: Array.h:648
void push_back()
(Deprecated, use emplace_back() instead) This is a non-standard version of push_back() that increases...
Definition: Array.h:2450
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:3619
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:1219
const T & operator[](index_type i) const
Select an element by its index, returning a const reference.
Definition: Array.h:1075
const_reverse_iterator rbegin() const
The const version of rbegin() is the same as crbegin().
Definition: Array.h:2239
An element has (1) a tagword, (2) a map of (name,value) pairs called attributes, and (3) a list of ch...
Definition: Xml.h:1033
static size_type max_size()
Definition: Array.h:183
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:568
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:2632
ArrayIndexTraits< X >::difference_type difference_type
Definition: Array.h:1545
short difference_type
Definition: Array.h:182
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:1013
The Array_<T> container class is a plug-compatible replacement for the C++ standard template library ...
Definition: Array.h:53
T * end()
Return a writable pointer to what would be the element just after the last one in this array...
Definition: Array.h:1208
#define SimTK_ERRCHK_ALWAYS(cond, whereChecked, msg)
Definition: ExceptionMacros.h:281
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:1188
ArrayIndexPackType< size_type >::packed_size_type packed_size_type
Definition: Array.h:1547
ArrayIndexPackType< size_type >::packed_size_type packed_size_type
The integral type we actually use internally to store size_type values.
Definition: Array.h:361
void disconnect()
Forward to base class disconnect() method – clears the handle without doing anything to the data...
Definition: Array.h:901
T & front()
Return a writable reference to the first element in this array, which must not be empty...
Definition: Array.h:1121
signed char difference_type
Definition: Array.h:204
#define SimTK_ERRCHK3_ALWAYS(cond, whereChecked, fmt, a1, a2, a3)
Definition: ExceptionMacros.h:293
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:2264
const T & operator[](index_type i) const
Select an element by its index, returning a const reference.
Definition: Array.h:554
long long size_type
Definition: Array.h:243
const T & const_reference
Definition: Array.h:859
ELEM max(const VectorBase< ELEM > &v)
Definition: VectorMath.h:251
This is a compile-time equivalent of "true", used in compile-time condition checking in templatized i...
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:681
std::reverse_iterator< iterator > reverse_iterator
Definition: Array.h:862
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:1201
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:954
T * data()
Return a writable pointer to the first allocated element of the array, or a null pointer if no space ...
Definition: Array.h:1247
static size_type max_size()
Definition: Array.h:173
const T * const_pointer
Definition: Array.h:1537
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:985
const T * const_pointer
A const pointer to a value_type.
Definition: Array.h:341
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:3707
void reserve(size_type n)
Ensure that this array has enough allocated capacity to hold the indicated number of elements...
Definition: Array.h:2136
T value_type
Definition: Array.h:1534
const_reverse_iterator rbegin() const
The const version of rbegin() is the same as crbegin().
Definition: Array.h:1215
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:3738
const T * data() const
The const version of the data() method is identical to cdata().
Definition: Array.h:1243
const T & const_reference
Definition: Array.h:1539
static size_type max_size()
Definition: Array.h:162
long long difference_type
Definition: Array.h:235
ArrayIndexTraits< X >::difference_type difference_type
Definition: Array.h:865
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:2187
unsigned char size_type
Definition: Array.h:192
#define SimTK_FORCE_INLINE
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:269
std::ostream & operator<<(std::ostream &o, const ContactForce &f)
Definition: CompliantContactSubsystem.h:387
int size_type
Definition: Array.h:134
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:3785
unsigned short size_type
Definition: Array.h:171
std::reverse_iterator< iterator > reverse_iterator
A writable reverse iterator for this container.
Definition: Array.h:351
static size_type max_size()
Definition: Array.h:129
bool empty() const
Return true if there are no elements currently stored in this array.
Definition: Array.h:519
Array_ & operator=(Array_ &&src)
Move assignment operator swaps the contents of this Array_ with the source Array_.
Definition: Array.h:1945
void swap(Array_ &other)
This is a specialized algorithm providing constant time exchange of data with another array that has ...
Definition: Array.h:1983
#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:3484
#define SimTK_ERRCHK(cond, whereChecked, msg)
Definition: ExceptionMacros.h:324
long difference_type
Definition: Array.h:148
T * end()
Return a writable pointer to what would be the element just after the last one in this array...
Definition: Array.h:2232
Array_(std::initializer_list< T > ilist)
Construct an Array_<T> from an std::initializer_list whose elements were convertible to type T...
Definition: Array.h:1628
#define SimTK_ERRCHK2(cond, whereChecked, fmt, a1, a2)
Definition: ExceptionMacros.h:328
const T * end() const
The const version of end() is the same as cend().
Definition: Array.h:2227
This Array_ helper class is the base class for ArrayView_ which is the base class for Array_; here we...
Definition: Array.h:51
T & back()
Return a writable reference to the last element in this array, which must not be empty.
Definition: Array.h:2344
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:585
Array_()
Default constructor allocates no heap space and is very fast.
Definition: Array.h:1560
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:3808
size_type size() const
Definition: Array.h:1263
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:1706
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:3767
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:2256
X index_type
Definition: Array.h:1535
Array_ & deallocate()
Empty this array of its contents, returning the array to its default-constructed, all-zero state...
Definition: Array.h:1753
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:2598
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:654
#define SimTK_INDEXCHECK(ix, ub, where)
Definition: ExceptionMacros.h:145
ArrayViewConst_(const T *first, const T *last1)
Construct an ArrayViewConst_<T> by referencing (sharing) a given range of const data [first...
Definition: Array.h:413
long difference_type
Definition: Array.h:161
const T * end() const
The const version of end() is the same as cend().
Definition: Array.h:650
X index_type
The index type (an extension).
Definition: Array.h:337
T * iterator
Definition: Array.h:1540
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:3670
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:621
ArrayIndexTraits< X >::size_type size_type
An integral type suitable for all indices and sizes for this array.
Definition: Array.h:355
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:1055
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:1654
signed char difference_type
Definition: Array.h:227
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:1106
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:2225
const T * const_pointer
Definition: Array.h:857
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:3654
size_type allocated() const
Definition: Array.h:1267
static size_type max_size()
Definition: Array.h:194
const T * const_iterator
Definition: Array.h:1541
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:118
size_type max_size() const
Definition: Array.h:1264
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:3684
T * begin()
Return a writable pointer to the first element of this array if any, otherwise end().
Definition: Array.h:2219
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:2711
T & reference
Definition: Array.h:858
static size_type max_size()
Definition: Array.h:136
reverse_iterator rend()
Return a writable past-the-end reverse iterator that tests equal to a reverse iterator that has been ...
Definition: Array.h:1232
bool readFormatted(std::istream &in, ArrayView_< T, X > &v)
Specialization of readFormatted() for fixed-length ArrayView_<T,X>; uses fillArrayViewFromStream() to...
Definition: Array.h:3555
const T * const_iterator
A const iterator for this container (same as const_pointer here).
Definition: Array.h:349
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:976
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:2578
void disconnect()
Disconnect this array handle from any data to which it refers, restoring it to the condition it would...
Definition: Array.h:489
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:2361
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:1736
signed char size_type
Definition: Array.h:203
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:2113
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:3772
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:641
T & front()
Return a writable reference to the first element in this array, which must not be empty...
Definition: Array.h:2330
int difference_type
Definition: Array.h:172
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:1155
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:1240
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:949
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:2172
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:1935
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:2399
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:2316
size_type capacity() const
Definition: Array.h:1266
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:3545
std::reverse_iterator< const_iterator > const_reverse_iterator
A const reverse iterator for this container.
Definition: Array.h:353
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:2033
T & operator[](index_type i)
Select an element by its index, returning a writable (lvalue) reference.
Definition: Array.h:2296
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:3732
const_reverse_iterator rend() const
The const version of rend() is the same as crend().
Definition: Array.h:664
~ArrayView_()
The destructor just disconnects the array view handle from its data; see ArrayViewConst_<T,X>::disconnect() for more information.
Definition: Array.h:905
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:659
T * emplace(T *p, Args &&... args)
Insert a new element at a given location within this array, by invoking T&#39;s constructor whose signatu...
Definition: Array.h:2658
size_type capacity() const
Return the number of elements this array can currently hold without requiring reallocation.
Definition: Array.h:2085
T * pointer
Definition: Array.h:856
ArrayView_(T *first, const T *last1)
Construct from a range of writable memory.
Definition: Array.h:885
void assign(const Iter &first, const Iter &last1)
Assign this array from a range [first,last1) given by non-pointer iterators.
Definition: Array.h:1925
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:2050
T * data()
Return a writable pointer to the first allocated element of the array, or a null pointer if no space ...
Definition: Array.h:2271
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:2357
static size_type max_size()
Definition: Array.h:149
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:121
bool isSizeInRange(char sz, char mx)
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:338
static std::istream & readArrayFromStreamHelper(std::istream &in, bool isFixedSize, Array_< T, X > &out)
Definition: Array.h:3281
short size_type
Definition: Array.h:181
const T & back() const
Return a const reference to the last element in this array, which must not be empty.
Definition: Array.h:2337
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:3627
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:115
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:3643
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:577
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:286
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:646
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:529
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:76
ArrayView_(const ArrayView_ &src)
Copy constructor is shallow.
Definition: Array.h:882
void emplace_back(Args &&... args)
This is similar to push_back() but rather than copying, it constructs the element in place at the end...
Definition: Array.h:2426
const_reverse_iterator rend() const
The const version of rend() is the same as crend().
Definition: Array.h:1227
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:2236
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:1608
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:2696
size_type max_size() const
Return the maximum allowable size for this array.
Definition: Array.h:515
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:960