Teuchos - Trilinos Tools Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Teuchos_Array.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Teuchos: Common Tools Package
4 //
5 // Copyright 2004 NTESS and the Teuchos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef TEUCHOS_ARRAY_H
11 #define TEUCHOS_ARRAY_H
12 
17 #include "Teuchos_ConfigDefs.hpp"
18 #include "Teuchos_Assert.hpp"
20 #include "Teuchos_ArrayRCP.hpp"
21 #include "Teuchos_Tuple.hpp"
22 #include "Teuchos_Utils.hpp"
23 #include "Teuchos_Assert.hpp"
24 
25 #if defined(HAVE_TEUCHOSCORE_CXX11) && defined(HAVE_TEUCHOS_ARRAY_BOUNDSCHECK) && defined(HAVE_TEUCHOS_THREAD_SAFE) && !defined(REMOVE_THREAD_PROTECTION_FOR_ARRAY)
26 #include <mutex>
27 #define USE_MUTEX_LOCK_FOR_ARRAY
28 #endif
29 
30 namespace Teuchos {
31 
36 class InvalidArrayStringRepresentation : public std::logic_error
37 {public:InvalidArrayStringRepresentation(const std::string& what_arg) : std::logic_error(what_arg) {}};
38 
39 
40 template<typename T> class Array;
41 
42 
43 // 2007/11/30: rabartl: Below, I had to move the initial declaration of these
44 // non-member template functions outside of the Array class since the Sun
45 // compiler on sass9000 would not accept this. However, this did work on a
46 // number of other compilers such a g++, Intel C++ etc. The old in-class
47 // non-member friend definition is clearly ISO 98 C++ as shown in Item 46 of
48 // "Effective C++: Third Edition". This is not the end of the world but this
49 // is something to remember for this platform.
50 
51 
56 template<typename T> inline
57 bool operator==( const Array<T> &a1, const Array<T> &a2 );
58 
59 
64 template<typename T> inline
65 bool operator!=( const Array<T> &a1, const Array<T> &a2 );
66 
67 
72 template<typename T> inline
73 void swap( Array<T> &a1, Array<T> &a2 );
74 
75 
80 template<typename T> inline
81 bool operator<( const Array<T> &a1, const Array<T> &a2 );
82 
83 
88 template<typename T> inline
89 bool operator<=( const Array<T> &a1, const Array<T> &a2 );
90 
91 
96 template<typename T> inline
97 bool operator>( const Array<T> &a1, const Array<T> &a2 );
98 
99 
104 template<typename T> inline
105 bool operator>=( const Array<T> &a1, const Array<T> &a2 );
106 
107 
161 template<typename T>
162 class Array
163 {
164 public:
165 
166  // 2007/11/30: rabartl: Below, note that the only reason that these
167  // functions are declared as friends is so that the compiler will do
168  // automatic type conversions as described in "Effective C++: Third Edition"
169  // Item 46.
170 
172  template<typename T2>
173  friend bool Teuchos::operator==( const Array<T2> &a1, const Array<T2> &a2 );
174 
176  template<typename T2>
177  friend bool Teuchos::operator!=( const Array<T2> &a1, const Array<T2> &a2 );
178 
180  template<typename T2>
181  friend void swap( Array<T2> &a1, Array<T2> &a2 );
182 
184  template<typename T2>
185  friend bool Teuchos::operator<( const Array<T2> &a1, const Array<T2> &a2 );
186 
188  template<typename T2>
189  friend bool Teuchos::operator<=( const Array<T2> &a1, const Array<T2> &a2 );
190 
192  template<typename T2>
193  friend bool Teuchos::operator>( const Array<T2> &a1, const Array<T2> &a2 );
194 
196  template<typename T2>
197  friend bool Teuchos::operator>=( const Array<T2> &a1, const Array<T2> &a2 );
198 
201 
203  typedef Teuchos_Ordinal Ordinal;
209  typedef typename std::vector<T>::value_type value_type;
211  typedef typename std::vector<T>::pointer pointer;
213  typedef typename std::vector<T>::const_pointer const_pointer;
215  typedef typename std::vector<T>::reference reference;
217  typedef typename std::vector<T>::const_reference const_reference;
219  typedef typename std::vector<T>::allocator_type allocator_type;
220 
221 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
222  typedef ArrayRCP<T> iterator;
227  typedef std::reverse_iterator<iterator> reverse_iterator;
229  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
230 #else
231  typedef typename std::vector<T>::iterator iterator;
234  typedef typename std::vector<T>::const_iterator const_iterator;
236  typedef typename std::vector<T>::reverse_iterator reverse_iterator;
238  typedef typename std::vector<T>::const_reverse_iterator const_reverse_iterator;
239 #endif
240 
242 
244 
246  inline Array();
247 
249  inline explicit Array(size_type n, const value_type& value = value_type());
250 
252  inline Array(const Array<T>& x);
253 
255  template<typename InputIterator>
256  inline Array(InputIterator first, InputIterator last);
257 
259  inline Array(const ArrayView<const T>& a);
260 
262  template<int N>
263  inline Array(const Tuple<T,N>& t);
264 
266  inline Array(std::initializer_list<T> list);
267 
269  inline ~Array();
270 
272  inline Array& operator=(const Array<T>& a);
273 
275 
281 
283  inline void assign(size_type n, const value_type& val);
285  template<typename InputIterator>
286  inline void assign(InputIterator first, InputIterator last);
288  inline iterator begin();
290  inline iterator end();
292  inline const_iterator begin() const;
294  inline const_iterator end() const;
296  inline reverse_iterator rbegin();
298  inline reverse_iterator rend();
300  inline const_reverse_iterator rbegin() const;
302  inline const_reverse_iterator rend() const;
304  inline size_type size() const;
306  inline size_type max_size() const;
308  inline void resize(size_type new_size, const value_type& x = value_type());
310  inline size_type capacity() const;
312  inline bool empty() const;
314  inline void reserve(size_type n);
316  inline reference operator[](size_type i);
318  inline const_reference operator[](size_type i) const;
320  inline reference at(size_type i);
322  inline const_reference at(size_type i) const;
324  inline reference front();
326  inline const_reference front() const;
328  inline reference back();
330  inline const_reference back() const;
332  inline void push_back(const value_type& x);
334  inline void pop_back();
336  inline iterator insert(iterator position, const value_type& x);
338  inline void insert(iterator position, size_type n, const value_type& x);
340  template<typename InputIterator>
341  inline void insert(iterator position, InputIterator first, InputIterator last);
343  inline iterator erase(iterator position);
345  inline iterator erase(iterator first, iterator last);
347  inline void swap(Array& x);
349  inline void clear();
350 
352 
354 
359  inline Array<T>& append(const T& x);
360 
364  inline void remove(int i);
365 
370  inline int length() const;
371 
373  inline std::string toString() const;
374 
376  inline static bool hasBoundsChecking();
377 
379  inline T* getRawPtr();
380 
384  inline T* data();
385 
387  inline const T* getRawPtr() const;
388 
392  inline const T* data() const;
393 
395 
397 
399  inline Array( const std::vector<T> &v );
400 
402  inline std::vector<T> toVector() const;
403 
405  inline Array& operator=( const std::vector<T> &v );
406 
408 
410 
411 
425  inline ArrayView<T> view( size_type offset, size_type size );
426 
440  inline ArrayView<const T> view( size_type offset, size_type size ) const;
441 
445  inline ArrayView<T> operator()( size_type offset, size_type size );
446 
450  inline ArrayView<const T> operator()( size_type offset, size_type size ) const;
451 
456  inline ArrayView<T> operator()();
457 
462  inline ArrayView<const T> operator()() const;
463 
467  inline operator ArrayView<T>();
468 
472  inline operator ArrayView<const T>() const;
473 
475 
476 private:
477 
478 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
479  RCP<std::vector<T> > vec_;
480  mutable ArrayRCP<T> extern_arcp_;
481  mutable ArrayRCP<const T> extern_carcp_;
482 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
483  mutable std::mutex mutex_lock; // this mutex provides thread safe debugging for the vec_, extern_arcp_, extern_carcp_
484 #endif
485 #else
486  std::vector<T> vec_;
487 #endif
488 
489  inline std::vector<T>& vec(
490  bool isStructureBeingModified = false,
491  bool activeIter = false
492  );
493 
494  inline const std::vector<T>& vec() const;
495 
496  inline typename std::vector<T>::iterator
497  raw_position( iterator position );
498 
499  inline void assertIndex(size_type i) const;
500 
501  inline void assertNotNull() const;
502 
503 };
504 
505 
511 template<class T>
513 {
514  if ( is_null(v) || !v->size() )
515  return null;
516  return arcpWithEmbeddedObjPostDestroy<T,RCP<Array<T> > >(
517  &(*v)[0], 0, v->size(),
518  v, false
519  );
520 }
521 
522 
528 template<class T>
529 ArrayRCP<const T> arcp( const RCP<const Array<T> > &v )
530 {
531  if ( is_null(v) || !v->size() )
532  return null;
533  return arcpWithEmbeddedObjPostDestroy<const T,RCP<const Array<T> > >(
534  &(*v)[0], 0, v->size(),
535  v, false
536  );
537 }
538 
539 
545 template<class T>
547 {
548  if (a.size() == 0)
549  return null;
550 #ifdef TEUCHOS_DEBUG
551  return a.begin(); // Catch dangling reference!
552 #else
553  return arcp(a.getRawPtr(), 0, a.size(), false);
554 #endif
555 }
556 
557 
563 template<class T>
565 {
566  if (a.size() == 0)
567  return null;
568 #ifdef TEUCHOS_DEBUG
569  return a.begin(); // Catch dangling reference!
570 #else
571  return arcp(a.getRawPtr(), 0, a.size(), false);
572 #endif
573 }
574 
575 
588 template<typename T>
589 std::ostream& operator<<(std::ostream& os, const Array<T>& array);
590 
591 
596 template<typename T> inline
597 int hashCode(const Array<T>& array);
598 
599 
606 template<typename T> inline
607 std::vector<T> createVector( const Array<T> &a );
608 
609 
614 template<typename T>
615 std::string toString(const Array<T>& array);
616 
617 
669 template<typename T>
670 Array<T> fromStringToArray(const std::string& arrayStr);
671 
677 template<typename T>
678 std::istringstream& operator>> (std::istringstream& in, Array<T>& array){
679  array = fromStringToArray<T>(in.str());
680  return in;
681 }
682 
688 template<typename T> inline
689 void extractDataFromISS( std::istringstream& iss, T& data )
690 {
691  iss >> data; // Assumes type has operator>>(...) defined!
692 }
693 
700 inline
701 void extractDataFromISS( std::istringstream& iss, std::string& data )
702 {
703  // grab unformatted string.
704  data = iss.str();
705  // remove white space from beginning and end of string.
706  data = Utils::trimWhiteSpace(data);
707 }
708 
718 inline
720  return "Array(*)";
721 }
722 
723 
724 
740 template<typename T>
741 class TEUCHOSCORE_LIB_DLL_EXPORT TypeNameTraits<Array<T> > {
742 public:
743  static std::string name(){
744  std::string formatString = getArrayTypeNameTraitsFormat();
745  size_t starPos = formatString.find("*");
746  std::string prefix = formatString.substr(0,starPos);
747  std::string postFix = formatString.substr(starPos+1);
748  return prefix+TypeNameTraits<T>::name()+postFix;
749  }
750  static std::string concreteName(const Array<T>&)
751  { return name(); }
752 };
753 
754 
755 } // namespace Teuchos
756 
757 
758 //
759 // Implementation
760 //
761 
762 
763 namespace Teuchos {
764 
765 
766 // All constructors
767 
768 
769 template<typename T> inline
771 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
772  : vec_(rcp(new std::vector<T>()))
773 #endif
774 {}
775 
776 
777 template<typename T> inline
779 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
780  vec_(rcp(new std::vector<T>(n,value)))
781 #else
782  vec_(n, value)
783 #endif
784 {}
785 
786 
787 template<typename T> inline
789 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
790  vec_(rcp(new std::vector<T>(*x.vec_)))
791 #else
792  vec_(x.vec_)
793 #endif
794 {}
795 
796 
797 template<typename T> template<typename InputIterator> inline
798 Array<T>::Array(InputIterator first, InputIterator last) :
799 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
800  vec_(rcp(new std::vector<T>(first, last)))
801 #else
802  vec_(first, last)
803 #endif
804 {}
805 
806 
807 template<typename T> inline
809 {}
810 
811 
812 template<typename T> inline
814 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
815  : vec_(rcp(new std::vector<T>()))
816 #endif
817 {
818  insert(begin(), a.begin(), a.end());
819 }
820 
821 
822 template<typename T>
823 template<int N>
824 inline
826 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
827  : vec_(rcp(new std::vector<T>()))
828 #endif
829 {
830  insert(begin(), t.begin(), t.end());
831 }
832 
833 template<typename T> inline
834 Array<T>::Array(std::initializer_list<T> a)
835 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
836  : vec_(rcp(new std::vector<T>(a)))
837 #else
838  : vec_(a)
839 #endif
840 {}
841 
842 template<typename T> inline
844 {
845 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
846  std::lock_guard<std::mutex> lockGuard(mutex_lock);
847 #endif
848  vec(true) = a.vec();
849  return *this;
850 }
851 
852 
853 // Other std::vector functions
854 
855 
856 template<typename T> inline
858 {
859 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
860  std::lock_guard<std::mutex> lockGuard(mutex_lock);
861 #endif
862  vec(true).assign(n,val);
863 }
864 
865 
866 template<typename T> template<typename InputIterator> inline
867 void Array<T>::assign(InputIterator first, InputIterator last)
868 {
869 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
870  std::lock_guard<std::mutex> lockGuard(mutex_lock);
871 #endif
872  vec(true).assign(first,last);
873 }
874 
875 
876 template<typename T> inline
877 typename Array<T>::iterator
879 {
880 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
881 
882 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
883  std::lock_guard<std::mutex> lockGuard(mutex_lock);
884 #endif
885 
886  if (is_null(extern_arcp_)) {
887  // Here we must use the same RCP to avoid creating two unrelated RCPNodes!
888  extern_arcp_ = arcp(vec_); // Will be null if vec_ is sized!
889  }
890  // Returning a weak pointer will help to catch dangling references but still
891  // keep the same behavior as optimized code.
892 
893  return extern_arcp_.create_weak();
894 #else
895  return vec().begin();
896 #endif
897 }
898 
899 
900 template<typename T> inline
901 typename Array<T>::iterator
903 {
904 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
905  return begin() + size();
906 #else
907  return vec().end();
908 #endif
909 }
910 
911 template<typename T> inline
914 {
915 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
916 
917 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
918  std::lock_guard<std::mutex> lockGuard(mutex_lock);
919 #endif
920  if (is_null(extern_carcp_)) {
921  // Note that this used to call the non-const begin() function above
922  // I've moved that code here to make the mutex locking more transparent and
923  // prevent the need to structure something awkward to avoid double locks
924  // The original line of code was this:
925  // extern_carcp_ = const_cast<Array<T>*>(this)->begin();
926  // Now replaced by the following code which mirrors the above begin() call
927  if (is_null(extern_arcp_)) {
928  extern_arcp_ = arcp(vec_);
929  }
930  // note that we call create_weak() twice, first on the non-const and then
931  // below on the const - this preserves the original design exactly
932  extern_carcp_ = extern_arcp_.create_weak();
933  }
934 
935  // Returning a weak pointer will help to catch dangling references but still
936  // keep the same behavior as optimized code.
937  return extern_carcp_.create_weak();
938 #else
939  return vec().begin();
940 #endif
941 }
942 
943 
944 template<typename T> inline
947 {
948 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
949  return begin() + size();
950 #else
951  return vec().end();
952 #endif
953 }
954 
955 
956 template<typename T> inline
959 {
960 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
961  return reverse_iterator(end());
962 #else
963  return vec().rbegin();
964 #endif
965 }
966 
967 
968 template<typename T> inline
971 {
972 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
973  return reverse_iterator(begin());
974 #else
975  return vec().rend();
976 #endif
977 }
978 
979 
980 template<typename T> inline
983 {
984 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
985  return const_reverse_iterator(end());
986 #else
987  return vec().rbegin();
988 #endif
989 }
990 
991 
992 template<typename T> inline
995 {
996 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
997  return const_reverse_iterator(begin());
998 #else
999  return vec().rend();
1000 #endif
1001 }
1002 
1003 
1004 template<typename T> inline
1005 typename Array<T>::size_type
1007 {
1008  return vec().size();
1009 }
1010 
1011 
1012 template<typename T> inline
1013 typename Array<T>::size_type
1015 {
1016  return std::numeric_limits<size_type>::max();
1017 }
1018 
1019 
1020 template<typename T> inline
1021 void
1023 {
1024 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1025  std::lock_guard<std::mutex> lockGuard(mutex_lock);
1026 #endif
1027  vec(true).resize(new_size,x);
1028 }
1029 
1030 
1031 template<typename T> inline
1032 typename Array<T>::size_type
1034 {
1035  return vec().capacity();
1036 }
1037 
1038 
1039 template<typename T> inline
1040 bool Array<T>::empty() const
1041 {
1042  return vec().empty();
1043 }
1044 
1045 
1046 template<typename T> inline
1048 {
1049 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1050  std::lock_guard<std::mutex> lockGuard(mutex_lock);
1051 #endif
1052  vec(true).reserve(n);
1053 }
1054 
1055 
1056 template<typename T> inline
1057 typename Array<T>::reference
1059 {
1060 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1061  assertIndex(i);
1062 #endif
1063  return vec()[i];
1064 }
1065 
1066 
1067 template<typename T> inline
1070 {
1071 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1072  assertIndex(i);
1073 #endif
1074  return vec()[i];
1075 }
1076 
1077 
1078 template<typename T> inline
1079 typename Array<T>::reference
1081 {
1082 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1083  assertIndex(i);
1084 #endif
1085  return vec().at(i);
1086 }
1087 
1088 
1089 template<typename T> inline
1092 {
1093 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1094  assertIndex(i);
1095 #endif
1096  return vec().at(i);
1097 }
1098 
1099 
1100 template<typename T> inline
1101 typename Array<T>::reference
1103 {
1104 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1105  assertNotNull();
1106 #endif
1107  return vec().front();
1108 }
1109 
1110 
1111 template<typename T> inline
1114 {
1115 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1116  assertNotNull();
1117 #endif
1118  return vec().front();
1119 }
1120 
1121 
1122 template<typename T> inline
1123 typename Array<T>::reference
1125 {
1126 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1127  assertNotNull();
1128 #endif
1129  return vec().back();
1130 }
1131 
1132 
1133 template<typename T> inline
1136 {
1137 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1138  assertNotNull();
1139 #endif
1140  return vec().back();
1141 }
1142 
1143 
1144 template<typename T> inline
1146 {
1147 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1148  std::lock_guard<std::mutex> lockGuard(mutex_lock);
1149 #endif
1150  vec(true).push_back(x);
1151 }
1152 
1153 
1154 template<typename T> inline
1156 {
1157 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1158  assertNotNull();
1159 #endif
1160 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1161  std::lock_guard<std::mutex> lockGuard(mutex_lock);
1162 #endif
1163  vec(true).pop_back();
1164 }
1165 
1166 
1167 // 2009/11/13:: rabartl: After moving to a full RCPNode tracing and lookup
1168 // model, I had to how modifying functions like insert(...) and erase(...)
1169 // work which have active iterators controled by the client and yet need to
1170 // allow the structure of the container change. The way these troublesome
1171 // functions work is that first the raw std::vector iterator is extracted.
1172 // The function vec(true, true) then deletes the strong iterators but there is
1173 // still a weak ArrayRCP object that is owned by the client which is being
1174 // passed into this function. The issue is that the design of ArrayRCP is
1175 // such that the RCPNode object is not removed but instead remains in order to
1176 // perform runtime checking.
1177 
1178 
1179 template<typename T> inline
1180 typename Array<T>::iterator
1182 {
1183 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1184  // Assert a valid iterator and get vector iterator
1185  const typename std::vector<T>::iterator raw_poss = raw_position(position);
1186  const difference_type i = position - begin();
1187 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1188  {
1189  std::lock_guard<std::mutex> lockGuard(mutex_lock);
1190 #endif
1191  vec(true, true).insert(raw_poss, x);
1192 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1193  } // must unlock mutex_lock before calling begin() which will lock again
1194 #endif
1195  return begin() + i;
1196 #else
1197  return vec_.insert(position, x);
1198 #endif
1199 }
1200 
1201 
1202 template<typename T> inline
1203 void Array<T>::insert(iterator position, size_type n, const value_type& x)
1204 {
1205 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1206  const typename std::vector<T>::iterator raw_poss = raw_position(position);
1207 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1208  std::lock_guard<std::mutex> lockGuard(mutex_lock);
1209 #endif
1210  vec(true, true).insert(raw_poss, n, x);
1211 #else
1212  vec_.insert(position, n, x);
1213 #endif
1214 }
1215 
1216 
1217 template<typename T> template<typename InputIterator> inline
1218 void Array<T>::insert(iterator position, InputIterator first, InputIterator last)
1219 {
1220 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1221  const typename std::vector<T>::iterator raw_poss = raw_position(position);
1222 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1223  std::lock_guard<std::mutex> lockGuard(mutex_lock);
1224 #endif
1225  vec(true, true).insert(raw_poss, first, last);
1226 #else
1227  vec_.insert(position, first, last);
1228 #endif
1229 }
1230 
1231 
1232 template<typename T> inline
1233 typename Array<T>::iterator
1235 {
1236 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1237  assertNotNull();
1238  // Assert a valid iterator and get vector iterator
1239  const typename std::vector<T>::iterator raw_poss = raw_position(position);
1240  const difference_type i = position - begin();
1241 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1242  {
1243  std::lock_guard<std::mutex> lockGuard(mutex_lock);
1244 #endif
1245  vec(true, true).erase(raw_poss);
1246 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1247  } // must unlock mutex_lock before call begin() or dead lock on second call
1248 #endif
1249  return begin() + i;
1250 #else
1251  return vec_.erase(position);
1252 #endif
1253 }
1254 
1255 
1256 template<typename T> inline
1257 typename Array<T>::iterator
1259 {
1260 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1261  if (empty()) {
1262  TEUCHOS_ASSERT(first == begin());
1263  TEUCHOS_ASSERT(last == end());
1264  return end();
1265  }
1266  assertNotNull();
1267  // Assert a valid iterator and get vector iterator
1268  const typename std::vector<T>::iterator raw_first = raw_position(first);
1269  const typename std::vector<T>::iterator raw_last = raw_position(last);
1270  const difference_type i = first - begin();
1271 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1272  {
1273  std::lock_guard<std::mutex> lockGuard(mutex_lock);
1274 #endif
1275  vec(true,true).erase(raw_first,raw_last);
1276 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1277  } // must unlock mutex_lock before call begin() or dead lock on second call
1278 #endif
1279  return begin() + i;
1280 #else
1281  return vec_.erase(first,last);
1282 #endif
1283 }
1284 
1285 
1286 template<typename T> inline
1288 {
1289 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1290  std::lock_guard<std::mutex> lockGuard(mutex_lock);
1291 #endif
1292  vec(true).swap(x.vec());
1293 }
1294 
1295 
1296 template<typename T> inline
1298 {
1299 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1300  std::lock_guard<std::mutex> lockGuard(mutex_lock);
1301 #endif
1302  vec(true).clear();
1303 }
1304 
1305 
1306 // Non-standard functions
1307 
1308 
1309 template<typename T> inline
1311 {
1312  this->push_back(x);
1313  return *this;
1314 }
1315 
1316 
1317 template<typename T> inline
1318 void Array<T>::remove(int i)
1319 {
1320 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1321  assertIndex(i);
1322 #endif
1323  // Erase the i-th element of this array.
1324  this->erase( this->begin() + i );
1325 }
1326 
1327 
1328 template<typename T> inline
1329 int Array<T>::length() const
1330 {
1331  return static_cast<int> (this->size ());
1332 }
1333 
1334 
1335 template<typename T> inline
1336 std::string Array<T>::toString() const
1337 {
1338  return (*this)().toString(); // Use ArrayView<T>::toString()
1339 }
1340 
1341 
1342 template<typename T> inline
1344 {
1345 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1346  return true;
1347 #else
1348  return false;
1349 #endif
1350 }
1351 
1352 
1353 template<typename T> inline
1355 {
1356  return ( size() ? &(*this)[0] : nullptr );
1357 }
1358 
1359 template<typename T> inline
1361 {
1362  return ( size() ? &(*this)[0] : nullptr );
1363 }
1364 
1365 template<typename T> inline
1366 const T* Array<T>::getRawPtr() const
1367 {
1368  return ( size() ? &(*this)[0] : nullptr );
1369 }
1370 
1371 template<typename T> inline
1372 const T* Array<T>::data() const
1373 {
1374  return ( size() ? &(*this)[0] : nullptr );
1375 }
1376 
1377 // Conversions to and from std::vector
1378 
1379 
1380 template<typename T> inline
1381 Array<T>::Array( const std::vector<T> &v ) :
1382 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1383  vec_(new std::vector<T>(v))
1384 #else
1385  vec_(v)
1386 #endif
1387 {}
1388 
1389 
1390 template<typename T> inline
1391 std::vector<T> Array<T>::toVector() const
1392 {
1393  if (!size())
1394  return std::vector<T>();
1395  std::vector<T> v(begin(),end());
1396  return v;
1397 }
1398 
1399 
1400 template<typename T> inline
1401 Array<T>& Array<T>::operator=( const std::vector<T> &v )
1402 {
1403 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1404  std::lock_guard<std::mutex> lockGuard(mutex_lock);
1405 #endif
1406  vec(true) = v;
1407  return *this;
1408 }
1409 
1410 
1411 // Views
1412 
1413 
1414 template<typename T> inline
1416 {
1417  if (size_in) {
1418 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1419  return ArrayView<T>(this->begin().persistingView(offset, size_in));
1420 #else
1421  return arrayView( &vec()[offset], size_in );
1422 #endif
1423  }
1424  return Teuchos::null;
1425 }
1426 
1427 
1428 template<typename T> inline
1430 {
1431  if (size_in) {
1432 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1433  return ArrayView<const T>(this->begin().persistingView(offset, size_in));
1434 #else
1435  return arrayView( &vec()[offset], size_in );
1436 #endif
1437  }
1438  return Teuchos::null;
1439  // NOTE: Above, we use a different implementation to call the const version
1440  // of begin() instead of the non-const version. This sets up a different
1441  // ArrayRCP object that gets checked.
1442 }
1443 
1444 
1445 template<typename T> inline
1447 {
1448  return view(offset, size_in);
1449 }
1450 
1451 
1452 template<typename T> inline
1454 {
1455  return view(offset, size_in);
1456 }
1457 
1458 
1459 template<typename T> inline
1461 {
1462  if (!size())
1463  return null;
1464  return this->view(0, size());
1465 }
1466 
1467 
1468 template<typename T> inline
1470 {
1471  if (!size())
1472  return null;
1473  return this->view(0, size());
1474 }
1475 
1476 
1477 template<typename T> inline
1479 {
1480  return this->operator()();
1481 }
1482 
1483 
1484 template<typename T> inline
1486 {
1487  return this->operator()();
1488 }
1489 
1490 
1491 // private
1492 
1493 
1494 template<typename T>
1495 std::vector<T>&
1496 Array<T>::vec( bool isStructureBeingModified, bool activeIter )
1497 {
1498 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1499  (void)activeIter;
1500  if (isStructureBeingModified) {
1501  // Give up my ArrayRCPs used for iterator access since the array we be
1502  // getting modifed! Any clients that have views through weak pointers
1503  // better not touch them!
1504 
1505  // Note that in debug mode these are mutex protected - the mutex should
1506  // always be locked when this function is called with
1507  // isStructureBeingModified true
1508  extern_arcp_ = null;
1509  extern_carcp_ = null;
1510  }
1511  return *vec_;
1512 #else
1513  // get rid of "unused parameter" warnings
1514  (void)isStructureBeingModified;
1515  (void)activeIter;
1516  return vec_;
1517 #endif
1518 }
1519 
1520 
1521 template<typename T> inline
1522 const std::vector<T>&
1523 Array<T>::vec() const
1524 {
1525 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1526  return *vec_;
1527 #else
1528  return vec_;
1529 #endif
1530 }
1531 
1532 
1533 template<typename T> inline
1534 typename std::vector<T>::iterator
1535 Array<T>::raw_position( iterator position )
1536 {
1537 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1538  const iterator first = this->begin();
1539  const iterator last = this->end();
1541  !(first <= position && position <= last), DanglingReferenceError,
1542  "Error, this iterator is no longer valid for this Aray!"
1543  );
1544  // Note, above operator<=(...) functions will throw
1545  // IncompatibleIteratorsError if the iterators do not share the same
1546  // RCP_node object!
1547  return vec_->begin() + (position - this->begin());
1548 #else
1549  return position;
1550 #endif
1551 }
1552 
1553 
1554 template<typename T> inline
1555 void Array<T>::assertIndex(size_type i) const
1556 {
1558  !( 0 <= i && i < size() ), RangeError,
1559  "Array<T>::assertIndex(i): i="<<i<<" out of range [0, "<< size() << ")"
1560  );
1561 }
1562 
1563 
1564 template<typename T> inline
1565 void Array<T>::assertNotNull() const
1566 {
1568  !size(), NullReferenceError,
1569  typeName(*this)<<"::assertNotNull(): "
1570  "Error, the array has size zero!"
1571  );
1572 }
1573 
1574 
1575 } // namespace Teuchos
1576 
1577 
1578 // Nonmember functions
1579 
1580 
1581 template<typename T> inline
1582 bool Teuchos::operator==( const Array<T> &a1, const Array<T> &a2 )
1583 { return (a1.vec() == a2.vec()); }
1584 
1585 
1586 template<typename T> inline
1587 bool Teuchos::operator!=( const Array<T> &a1, const Array<T> &a2 )
1588 { return (a1.vec() != a2.vec()); }
1589 
1590 
1591 template<typename T> inline
1592 void Teuchos::swap( Array<T> &a1, Array<T> &a2 )
1593 { a1.swap(a2); }
1594 
1595 
1596 template<typename T> inline
1597 bool Teuchos::operator<( const Array<T> &a1, const Array<T> &a2 )
1598 { return (a1.vec() < a2.vec()); }
1599 
1600 
1601 template<typename T> inline
1602 bool Teuchos::operator<=( const Array<T> &a1, const Array<T> &a2 )
1603 { return (a1.vec() <= a2.vec()); }
1604 
1605 
1606 template<typename T> inline
1607 bool Teuchos::operator>( const Array<T> &a1, const Array<T> &a2 )
1608 { return (a1.vec() > a2.vec()); }
1609 
1610 
1611 template<typename T> inline
1612 bool Teuchos::operator>=( const Array<T> &a1, const Array<T> &a2 )
1613 { return (a1.vec() >= a2.vec()); }
1614 
1615 
1616 template<typename T> inline
1617 std::ostream& Teuchos::operator<<(
1618  std::ostream& os, const Array<T>& array
1619  )
1620 {
1621  return os << Teuchos::toString(array);
1622 }
1623 
1624 
1625 template<typename T> inline
1626 int Teuchos::hashCode(const Array<T>& array)
1627 {
1628  int rtn = hashCode(array.length());
1629  for (int i=0; i<array.length(); i++)
1630  {
1631  rtn += hashCode(array[i]);
1632  }
1633  if (rtn < 0)
1634  {
1635  /* Convert the largest -ve int to zero and -1 to
1636  * std::numeric_limits<int>::max()
1637  * */
1638  size_t maxIntBeforeWrap = std::numeric_limits<int>::max();
1639  maxIntBeforeWrap ++;
1640  rtn += maxIntBeforeWrap;
1641  }
1642  return rtn;
1643 }
1644 
1645 
1646 template<typename T> inline
1647 std::vector<T> Teuchos::createVector( const Array<T> &a )
1648 {
1649  return a.toVector();
1650 }
1651 
1652 
1653 template<typename T> inline
1654 std::string Teuchos::toString(const Array<T>& array)
1655 {
1656  return array.toString();
1657 }
1658 
1659 
1660 template<typename T>
1662 Teuchos::fromStringToArray(const std::string& arrayStr)
1663 {
1664  const std::string str = Utils::trimWhiteSpace(arrayStr);
1665  std::istringstream iss(str);
1667  ( str[0]!='{' || str[str.length()-1] != '}' )
1668  ,InvalidArrayStringRepresentation
1669  ,"Error, the std::string:\n"
1670  "----------\n"
1671  <<str<<
1672  "\n----------\n"
1673  "is not a valid array represntation!"
1674  );
1675  char c;
1676  c = iss.get(); // Read initial '{'
1677  TEUCHOS_TEST_FOR_EXCEPT(c!='{'); // Should not throw!
1678  // Now we are ready to begin reading the entries of the array!
1679  Array<T> a;
1680  while( !iss.eof() ) {
1681  // Get the basic entry std::string
1682  std::string entryStr;
1683  std::getline(iss,entryStr,','); // Get next entry up to ,!
1684  // ToDo: Above, we might have to be careful to look for the opening and
1685  // closing of parentheses in order not to pick up an internal ',' in the
1686  // middle of an entry (for a std::complex number for instance). The above
1687  // implementation assumes that there will be no commas in the middle of
1688  // the std::string representation of an entry. This is certainly true for
1689  // the types bool, int, float, and double.
1690  //
1691  // Trim whitespace from beginning and end
1692  entryStr = Utils::trimWhiteSpace(entryStr);
1694  0 == entryStr.length(),
1695  InvalidArrayStringRepresentation,
1696  "Error, the std::string:\n"
1697  "----------\n"
1698  <<str<<
1699  "\n----------\n"
1700  "is not a valid array represntation because it has an empty array entry!"
1701  );
1702  // Remove the final '}' if this is the last entry and we did not
1703  // actually terminate the above getline(...) on ','
1704  bool found_end = false;
1705  if(entryStr[entryStr.length()-1]=='}') {
1706  entryStr = entryStr.substr(0,entryStr.length()-1);
1707  found_end = true;
1708  if( entryStr.length()==0 && a.size()==0 )
1709  return a; // This is the empty array "{}" (with any spaces in it!)
1710  }
1711  // Finally we can convert the entry and add it to the array!
1712  std::istringstream entryiss(entryStr);
1713  T entry;
1714  Teuchos::extractDataFromISS( entryiss, entry );
1715  // ToDo: We may need to define a traits class to allow us to specialized
1716  // how conversion from a std::string to a object is done!
1717  a.push_back(entry);
1718  // At the end of the loop body here, if we have reached the last '}'
1719  // then the input stream iss should be empty and iss.eof() should be
1720  // true, so the loop should terminate. We put an std::exception test here
1721  // just in case something has gone wrong.
1723  found_end && !iss.eof()
1724  ,InvalidArrayStringRepresentation
1725  ,"Error, the std::string:\n"
1726  "----------\n"
1727  <<str<<
1728  "\n----------\n"
1729  "is not a valid array represntation!"
1730  );
1731  }
1732  return a;
1733 }
1734 
1735 
1736 #endif // TEUCHOS_ARRAY_H
reverse_iterator rend()
void remove(int i)
Remove the i-th element from the array, with optional boundschecking.
void reserve(size_type n)
int hashCode(const Array< T > &array)
Return the hash code.
Array< T > & append(const T &x)
Add a new entry at the end of the array.
Partial specialization of ArrayRCP for const T.
static bool hasBoundsChecking()
Return true if Array has been compiled with boundschecking on.
iterator begin() const
Return an iterator to beginning of the array of data.
bool empty() const
ArrayView< T > view(size_type offset, size_type size)
Return non-const view of a contiguous range of elements.
bool is_null(const std::shared_ptr< T > &p)
Returns true if p.get()==NULL.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
std::vector< T >::value_type value_type
The type of an entry of the Array; for compatibility with std::vector.
void extractDataFromISS(std::istringstream &iss, std::string &data)
Extracts std::string data from an istringstream object.
Teuchos header file which uses auto-configuration information to include necessary C++ headers...
iterator erase(iterator position)
ArrayRCP< T > arcp(const RCP< Array< T > > &v)
Wrap an RCP&lt;Array&lt;T&gt; &gt; object as an ArrayRCP&lt;T&gt; object.
Array & operator=(const Array< T > &a)
Assignment operator (does a deep copy).
T * getRawPtr()
Return a raw pointer to beginning of array or NULL if unsized.
std::vector< T >::const_pointer const_pointer
The type of a const pointer to T; for compatibility with std::vector.
ArrayRCP< T > arcpFromArray(Array< T > &a)
Wrap an Array&lt;T&gt; object as a non-owning ArrayRCP&lt;T&gt; object.
ArrayRCP< const T > arcp(const RCP< const Array< T > > &v)
Wrap a RCP&lt;const Array&lt;T&gt; &gt; object as an ArrayRCP&lt;const T&gt; object.
static std::string trimWhiteSpace(const std::string &str)
Trim whitespace from beginning and end of std::string.
Statically sized simple array (tuple) class.
Ordinal size_type
The type of Array sizes and capacities.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
reference front()
Ordinal difference_type
The type of the difference between two size_type values.
std::string toString() const
Convert an Array to an std::string
T * data()
Return a raw pointer to beginning of array.
ArrayRCP< const T > arcpFromArray(const Array< T > &a)
Wrap a const Array&lt;T&gt; object as a non-owning ArrayRCP&lt;T&gt; object.
std::string getArrayTypeNameTraitsFormat()
Get the format that is used for the specialization of the TypeName traits class for Array...
friend void swap(Array< T2 > &a1, Array< T2 > &a2)
void resize(size_type new_size, const value_type &x=value_type())
Teuchos_Ordinal Ordinal
The type of indices.
std::vector< T >::reference reference
The type of a reference to T; for compatibility with std::vector.
std::vector< T >::pointer pointer
The type of a pointer to T; for compatibility with std::vector.
std::vector< T >::const_iterator const_iterator
The type of a const forward iterator.
reverse_iterator rbegin()
std::vector< T >::const_reference const_reference
The type of a const reference to T; for compatibility with std::vector.
reference back()
void push_back(const value_type &x)
Nonowning array view.
Default traits class that just returns typeid(T).name().
void extractDataFromISS(std::istringstream &iss, T &data)
Extracts data from an istringstream object.
std::vector< T >::const_reverse_iterator const_reverse_iterator
The type of a const reverse iterator.
iterator end() const
Return an iterator to past the end of the array of data.
int length() const
Return number of elements in the array.
size_type size() const
std::vector< T >::allocator_type allocator_type
The allocator type; for compatibility with std::vector.
std::vector< T > toVector() const
Explicit copy conversion to an std::vector.
ArrayView< T > operator()()
Return an non-const ArrayView of *this.
reference at(size_type i)
Smart reference counting pointer class for automatic garbage collection.
friend bool Teuchos::operator!=(const Array< T2 > &a1, const Array< T2 > &a2)
reference operator[](size_type i)
Partial specialization of ArrayView for const T.
#define TEUCHOS_ASSERT(assertion_test)
This macro is throws when an assert fails.
void assign(size_type n, const value_type &val)
Array()
Default constructor; creates an empty Array.
size_type max_size() const
std::vector< T >::iterator iterator
The type of a forward iterator.
A utilities class for Teuchos.
iterator insert(iterator position, const value_type &x)
iterator begin()
Defines basic traits returning the name of a type in a portable and readable way. ...
std::vector< T >::reverse_iterator reverse_iterator
The type of a reverse iterator.
size_type capacity() const
~Array()
Destructor.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
This macro is designed to be a short version of TEUCHOS_TEST_FOR_EXCEPTION() that is easier to call...
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.
Reference-counted smart pointer for managing arrays.
Replacement for std::vector that is compatible with the Teuchos Memory Management classes...