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