|
Teuchos - Trilinos Tools Package Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Teuchos: Common Tools Package 00005 // Copyright (2004) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // This library is free software; you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as 00012 // published by the Free Software Foundation; either version 2.1 of the 00013 // License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, but 00016 // WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00023 // USA 00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00025 // 00026 // *********************************************************************** 00027 // @HEADER 00028 00029 #ifndef TEUCHOS_ARRAY_H 00030 #define TEUCHOS_ARRAY_H 00031 00036 #include "Teuchos_ConfigDefs.hpp" 00037 #include "Teuchos_TestForException.hpp" 00038 #include "Teuchos_TypeNameTraits.hpp" 00039 #include "Teuchos_ArrayRCP.hpp" 00040 #include "Teuchos_Tuple.hpp" 00041 #include "Teuchos_Utils.hpp" 00042 #include "Teuchos_Assert.hpp" 00043 00044 00045 namespace Teuchos { 00046 00047 00052 class InvalidArrayStringRepresentation : public std::logic_error 00053 {public:InvalidArrayStringRepresentation(const std::string& what_arg) : std::logic_error(what_arg) {}}; 00054 00055 00056 template<typename T> class Array; 00057 00058 00059 // 2007/11/30: rabartl: Below, I had to move the initial declaration of these 00060 // non-member template functions outside of the Array class since the Sun 00061 // compiler on sass9000 would not accept this. However, this did work on a 00062 // number of other compilers such a g++, Intel C++ etc. The old in-class 00063 // non-member friend definition is clearly ISO 98 C++ as shown in Item 46 of 00064 // "Effective C++: Third Edition". This is not the end of the world but this 00065 // is something to remember for this platform. 00066 00067 00072 template<typename T> inline 00073 bool operator==( const Array<T> &a1, const Array<T> &a2 ); 00074 00075 00080 template<typename T> inline 00081 bool operator!=( const Array<T> &a1, const Array<T> &a2 ); 00082 00083 00088 template<typename T> inline 00089 void swap( Array<T> &a1, Array<T> &a2 ); 00090 00091 00096 template<typename T> inline 00097 bool operator<( const Array<T> &a1, const Array<T> &a2 ); 00098 00099 00104 template<typename T> inline 00105 bool operator<=( const Array<T> &a1, const Array<T> &a2 ); 00106 00107 00112 template<typename T> inline 00113 bool operator>( const Array<T> &a1, const Array<T> &a2 ); 00114 00115 00120 template<typename T> inline 00121 bool operator>=( const Array<T> &a1, const Array<T> &a2 ); 00122 00123 00161 template<typename T> 00162 class Array 00163 { 00164 public: 00165 00166 // 2007/11/30: rabartl: Below, note that the only reason that these 00167 // functions are declared as friends is so that the compiler will do 00168 // automatic type conversions as described in "Effective C++: Third Edition" 00169 // Item 46. 00170 00172 template<typename T2> 00173 friend bool Teuchos::operator==( const Array<T2> &a1, const Array<T2> &a2 ); 00174 00176 template<typename T2> 00177 friend bool Teuchos::operator!=( const Array<T2> &a1, const Array<T2> &a2 ); 00178 00180 template<typename T2> 00181 friend void swap( Array<T2> &a1, Array<T2> &a2 ); 00182 00184 template<typename T2> 00185 friend bool Teuchos::operator<( const Array<T2> &a1, const Array<T2> &a2 ); 00186 00188 template<typename T2> 00189 friend bool Teuchos::operator<=( const Array<T2> &a1, const Array<T2> &a2 ); 00190 00192 template<typename T2> 00193 friend bool Teuchos::operator>( const Array<T2> &a1, const Array<T2> &a2 ); 00194 00196 template<typename T2> 00197 friend bool Teuchos::operator>=( const Array<T2> &a1, const Array<T2> &a2 ); 00198 00201 00203 typedef Teuchos_Ordinal Ordinal; 00205 typedef Ordinal size_type; 00207 typedef Ordinal difference_type; 00209 typedef typename std::vector<T>::value_type value_type; 00211 typedef typename std::vector<T>::pointer pointer; 00213 typedef typename std::vector<T>::const_pointer const_pointer; 00215 typedef typename std::vector<T>::reference reference; 00217 typedef typename std::vector<T>::const_reference const_reference; 00219 typedef typename std::vector<T>::allocator_type allocator_type; 00220 00221 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00222 00223 typedef ArrayRCP<T> iterator; 00225 typedef ArrayRCP<const T> const_iterator; 00227 typedef std::reverse_iterator<iterator> reverse_iterator; 00229 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00230 #else 00231 00232 typedef typename std::vector<T>::iterator iterator; 00234 typedef typename std::vector<T>::const_iterator const_iterator; 00236 typedef typename std::vector<T>::reverse_iterator reverse_iterator; 00238 typedef typename std::vector<T>::const_reverse_iterator const_reverse_iterator; 00239 #endif 00240 00241 00243 00246 00248 inline Array(); 00250 inline explicit Array(size_type n, const value_type& value = value_type()); 00252 inline Array(const Array<T>& x); 00254 template<typename InputIterator> 00255 inline Array(InputIterator first, InputIterator last); 00257 inline Array(const ArrayView<const T>& a); 00259 template<int N> 00260 inline Array(const Tuple<T,N>& t); 00262 inline ~Array(); 00264 inline Array& operator=(const Array<T>& a); 00265 00267 00270 00272 inline void assign(size_type n, const value_type& val); 00274 template<typename InputIterator> 00275 inline void assign(InputIterator first, InputIterator last); 00277 inline iterator begin(); 00279 inline iterator end(); 00281 inline const_iterator begin() const; 00283 inline const_iterator end() const; 00285 inline reverse_iterator rbegin(); 00287 inline reverse_iterator rend(); 00289 inline const_reverse_iterator rbegin() const; 00291 inline const_reverse_iterator rend() const; 00293 inline size_type size() const; 00295 inline size_type max_size() const; 00297 inline void resize(size_type new_size, const value_type& x = value_type()); 00299 inline size_type capacity() const; 00301 inline bool empty() const; 00303 inline void reserve(size_type n); 00305 inline reference operator[](size_type i); 00307 inline const_reference operator[](size_type i) const; 00309 inline reference at(size_type i); 00311 inline const_reference at(size_type i) const; 00313 inline reference front(); 00315 inline const_reference front() const; 00317 inline reference back(); 00319 inline const_reference back() const; 00321 inline void push_back(const value_type& x); 00323 inline void pop_back(); 00325 inline iterator insert(iterator position, const value_type& x); 00327 inline void insert(iterator position, size_type n, const value_type& x); 00329 template<typename InputIterator> 00330 inline void insert(iterator position, InputIterator first, InputIterator last); 00332 inline iterator erase(iterator position); 00334 inline iterator erase(iterator first, iterator last); 00336 inline void swap(Array& x); 00338 inline void clear(); 00339 00341 00344 00349 inline Array<T>& append(const T& x); 00350 00354 inline void remove(int i); 00355 00360 inline int length() const; 00361 00363 inline std::string toString() const; 00364 00366 inline static bool hasBoundsChecking(); 00367 00369 inline T* getRawPtr(); 00370 00372 inline const T* getRawPtr() const; 00373 00375 00378 00380 inline Array( const std::vector<T> &v ); 00381 00383 inline std::vector<T> toVector() const; 00384 00386 inline Array& operator=( const std::vector<T> &v ); 00387 00389 00391 00392 00404 inline ArrayView<T> view( size_type offset, size_type size ); 00405 00417 inline ArrayView<const T> view( size_type offset, size_type size ) const; 00418 00422 inline ArrayView<T> operator()( size_type offset, size_type size ); 00423 00427 inline ArrayView<const T> operator()( size_type offset, size_type size ) const; 00428 00433 inline ArrayView<T> operator()(); 00434 00439 inline ArrayView<const T> operator()() const; 00440 00444 inline operator ArrayView<T>(); 00445 00449 inline operator ArrayView<const T>() const; 00450 00452 00453 private: 00454 00455 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00456 RCP<std::vector<T> > vec_; 00457 mutable ArrayRCP<T> extern_arcp_; 00458 mutable ArrayRCP<const T> extern_carcp_; 00459 #else 00460 std::vector<T> vec_; 00461 #endif 00462 00463 inline std::vector<T>& vec( 00464 bool isStructureBeingModified = false, 00465 bool activeIter = false 00466 ); 00467 00468 inline const std::vector<T>& vec() const; 00469 00470 inline typename std::vector<T>::iterator 00471 raw_position( iterator position ); 00472 00473 inline void assertIndex(int i) const; 00474 00475 inline void assertNotNull() const; 00476 00477 }; 00478 00479 00485 template<class T> 00486 ArrayRCP<T> arcp( const RCP<Array<T> > &v ) 00487 { 00488 if ( is_null(v) || !v->size() ) 00489 return null; 00490 return arcpWithEmbeddedObjPostDestroy<T,RCP<Array<T> > >( 00491 &(*v)[0], 0, v->size(), 00492 v, false 00493 ); 00494 } 00495 00496 00502 template<class T> 00503 ArrayRCP<const T> arcp( const RCP<const Array<T> > &v ) 00504 { 00505 if ( is_null(v) || !v->size() ) 00506 return null; 00507 return arcpWithEmbeddedObjPostDestroy<const T,RCP<const Array<T> > >( 00508 &(*v)[0], 0, v->size(), 00509 v, false 00510 ); 00511 } 00512 00513 00519 template<class T> 00520 ArrayRCP<T> arcpFromArray( Array<T> &a ) 00521 { 00522 if (a.size() == 0) 00523 return null; 00524 #ifdef TEUCHOS_DEBUG 00525 return a.begin(); // Catch dangling reference! 00526 #else 00527 return arcp(a.getRawPtr(), 0, a.size(), false); 00528 #endif 00529 } 00530 00531 00537 template<class T> 00538 ArrayRCP<const T> arcpFromArray( const Array<T> &a ) 00539 { 00540 if (a.size() == 0) 00541 return null; 00542 #ifdef TEUCHOS_DEBUG 00543 return a.begin(); // Catch dangling reference! 00544 #else 00545 return arcp(a.getRawPtr(), 0, a.size(), false); 00546 #endif 00547 } 00548 00549 00562 template<typename T> 00563 std::ostream& operator<<(std::ostream& os, const Array<T>& array); 00564 00565 00570 template<typename T> inline 00571 int hashCode(const Array<T>& array); 00572 00573 00580 template<typename T> inline 00581 std::vector<T> createVector( const Array<T> &a ); 00582 00583 00588 template<typename T> 00589 std::string toString(const Array<T>& array); 00590 00591 00643 template<typename T> 00644 Array<T> fromStringToArray(const std::string& arrayStr); 00645 00651 template<typename T> inline 00652 void extractDataFromISS( std::istringstream& iss, T& data ) 00653 { 00654 iss >> data; // Assumes type has operator>>(...) defined! 00655 } 00656 00663 inline 00664 void extractDataFromISS( std::istringstream& iss, std::string& data ) 00665 { 00666 // grab unformatted string. 00667 data = iss.str(); 00668 // remove white space from beginning and end of string. 00669 data = Utils::trimWhiteSpace(data); 00670 } 00671 00672 00686 template<typename T> 00687 class TEUCHOS_LIB_DLL_EXPORT TypeNameTraits<Array<T> > { 00688 public: 00689 static std::string name() 00690 { return "Array<"+TypeNameTraits<T>::name()+">"; } 00691 static std::string concreteName(const Array<T>&) 00692 { return name(); } 00693 }; 00694 00695 00696 } // namespace Teuchos 00697 00698 00699 // 00700 // Implementation 00701 // 00702 00703 00704 namespace Teuchos { 00705 00706 00707 // All constructors 00708 00709 00710 template<typename T> inline 00711 Array<T>::Array() 00712 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00713 : vec_(rcp(new std::vector<T>())) 00714 #endif 00715 {} 00716 00717 00718 template<typename T> inline 00719 Array<T>::Array(size_type n, const value_type& value) : 00720 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00721 vec_(rcp(new std::vector<T>(n,value))) 00722 #else 00723 vec_(n, value) 00724 #endif 00725 {} 00726 00727 00728 template<typename T> inline 00729 Array<T>::Array(const Array<T>& x) : 00730 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00731 vec_(rcp(new std::vector<T>(*x.vec_))) 00732 #else 00733 vec_(x.vec_) 00734 #endif 00735 {} 00736 00737 00738 template<typename T> template<typename InputIterator> inline 00739 Array<T>::Array(InputIterator first, InputIterator last) : 00740 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00741 vec_(rcp(new std::vector<T>(first, last))) 00742 #else 00743 vec_(first, last) 00744 #endif 00745 {} 00746 00747 00748 template<typename T> inline 00749 Array<T>::~Array() 00750 {} 00751 00752 00753 template<typename T> inline 00754 Array<T>::Array(const ArrayView<const T>& a) 00755 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00756 : vec_(rcp(new std::vector<T>())) 00757 #endif 00758 { 00759 insert(begin(), a.begin(), a.end()); 00760 } 00761 00762 00763 template<typename T> 00764 template<int N> 00765 inline 00766 Array<T>::Array(const Tuple<T,N>& t) 00767 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00768 : vec_(rcp(new std::vector<T>())) 00769 #endif 00770 { 00771 insert(begin(), t.begin(), t.end()); 00772 } 00773 00774 00775 template<typename T> inline 00776 Array<T>& Array<T>::operator=(const Array& a) 00777 { 00778 vec(true) = a.vec(); 00779 return *this; 00780 } 00781 00782 00783 // Other std::vector functions 00784 00785 00786 template<typename T> inline 00787 void Array<T>::assign(size_type n, const value_type& val) 00788 { 00789 vec(true).assign(n,val); 00790 } 00791 00792 00793 template<typename T> template<typename InputIterator> inline 00794 void Array<T>::assign(InputIterator first, InputIterator last) 00795 { 00796 vec(true).assign(first,last); 00797 } 00798 00799 00800 template<typename T> inline 00801 typename Array<T>::iterator 00802 Array<T>::begin() 00803 { 00804 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00805 if (is_null(extern_arcp_)) { 00806 // Here we must use the same RCP to avoid creating two unrelated RCPNodes! 00807 extern_arcp_ = arcp(vec_); // Will be null if vec_ is sized! 00808 } 00809 // Returning a weak pointer will help to catch dangling references but still 00810 // keep the same behavior as optimized code. 00811 return extern_arcp_.create_weak(); 00812 #else 00813 return vec().begin(); 00814 #endif 00815 } 00816 00817 00818 template<typename T> inline 00819 typename Array<T>::iterator 00820 Array<T>::end() 00821 { 00822 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00823 return begin() + size(); 00824 #else 00825 return vec().end(); 00826 #endif 00827 } 00828 00829 00830 template<typename T> inline 00831 typename Array<T>::const_iterator 00832 Array<T>::begin() const 00833 { 00834 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00835 if (is_null(extern_carcp_)) { 00836 extern_carcp_ = const_cast<Array<T>*>(this)->begin(); 00837 } 00838 // Returning a weak pointer will help to catch dangling references but still 00839 // keep the same behavior as optimized code. 00840 return extern_carcp_.create_weak(); 00841 #else 00842 return vec().begin(); 00843 #endif 00844 } 00845 00846 00847 template<typename T> inline 00848 typename Array<T>::const_iterator 00849 Array<T>::end() const 00850 { 00851 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00852 return begin() + size(); 00853 #else 00854 return vec().end(); 00855 #endif 00856 } 00857 00858 00859 template<typename T> inline 00860 typename Array<T>::reverse_iterator 00861 Array<T>::rbegin() 00862 { 00863 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00864 return reverse_iterator(end()); 00865 #else 00866 return vec().rbegin(); 00867 #endif 00868 } 00869 00870 00871 template<typename T> inline 00872 typename Array<T>::reverse_iterator 00873 Array<T>::rend() 00874 { 00875 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00876 return reverse_iterator(begin()); 00877 #else 00878 return vec().rend(); 00879 #endif 00880 } 00881 00882 00883 template<typename T> inline 00884 typename Array<T>::const_reverse_iterator 00885 Array<T>::rbegin() const 00886 { 00887 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00888 return const_reverse_iterator(end()); 00889 #else 00890 return vec().rbegin(); 00891 #endif 00892 } 00893 00894 00895 template<typename T> inline 00896 typename Array<T>::const_reverse_iterator 00897 Array<T>::rend() const 00898 { 00899 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00900 return const_reverse_iterator(begin()); 00901 #else 00902 return vec().rend(); 00903 #endif 00904 } 00905 00906 00907 template<typename T> inline 00908 typename Array<T>::size_type 00909 Array<T>::size() const 00910 { 00911 return vec().size(); 00912 } 00913 00914 00915 template<typename T> inline 00916 typename Array<T>::size_type 00917 Array<T>::max_size() const 00918 { 00919 return std::numeric_limits<size_type>::max(); 00920 } 00921 00922 00923 template<typename T> inline 00924 void 00925 Array<T>::resize(size_type new_size, const value_type& x) 00926 { 00927 vec(true).resize(new_size,x); 00928 } 00929 00930 00931 template<typename T> inline 00932 typename Array<T>::size_type 00933 Array<T>::capacity() const 00934 { 00935 return vec().capacity(); 00936 } 00937 00938 00939 template<typename T> inline 00940 bool Array<T>::empty() const 00941 { 00942 return vec().empty(); 00943 } 00944 00945 00946 template<typename T> inline 00947 void Array<T>::reserve(size_type n) 00948 { 00949 vec(true).reserve(n); 00950 } 00951 00952 00953 template<typename T> inline 00954 typename Array<T>::reference 00955 Array<T>::operator[](size_type i) 00956 { 00957 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00958 assertIndex(i); 00959 #endif 00960 return vec()[i]; 00961 } 00962 00963 00964 template<typename T> inline 00965 typename Array<T>::const_reference 00966 Array<T>::operator[](size_type i) const 00967 { 00968 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00969 assertIndex(i); 00970 #endif 00971 return vec()[i]; 00972 } 00973 00974 00975 template<typename T> inline 00976 typename Array<T>::reference 00977 Array<T>::at(size_type i) 00978 { 00979 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00980 assertIndex(i); 00981 #endif 00982 return vec().at(i); 00983 } 00984 00985 00986 template<typename T> inline 00987 typename Array<T>::const_reference 00988 Array<T>::at(size_type i) const 00989 { 00990 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00991 assertIndex(i); 00992 #endif 00993 return vec().at(i); 00994 } 00995 00996 00997 template<typename T> inline 00998 typename Array<T>::reference 00999 Array<T>::front() 01000 { 01001 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01002 assertNotNull(); 01003 #endif 01004 return vec().front(); 01005 } 01006 01007 01008 template<typename T> inline 01009 typename Array<T>::const_reference 01010 Array<T>::front() const 01011 { 01012 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01013 assertNotNull(); 01014 #endif 01015 return vec().front(); 01016 } 01017 01018 01019 template<typename T> inline 01020 typename Array<T>::reference 01021 Array<T>::back() 01022 { 01023 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01024 assertNotNull(); 01025 #endif 01026 return vec().back(); 01027 } 01028 01029 01030 template<typename T> inline 01031 typename Array<T>::const_reference 01032 Array<T>::back() const 01033 { 01034 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01035 assertNotNull(); 01036 #endif 01037 return vec().back(); 01038 } 01039 01040 01041 template<typename T> inline 01042 void Array<T>::push_back(const value_type& x) 01043 { 01044 vec(true).push_back(x); 01045 } 01046 01047 01048 template<typename T> inline 01049 void Array<T>::pop_back() 01050 { 01051 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01052 assertNotNull(); 01053 #endif 01054 vec(true).pop_back(); 01055 } 01056 01057 01058 // 2009/11/13:: rabartl: After moving to a full RCPNode tracing and lookup 01059 // model, I had to how modifying functions like insert(...) and erase(...) 01060 // work which have active iterators controled by the client and yet need to 01061 // allow the structure of the container change. The way these troublesome 01062 // functions work is that first the raw std::vector iterator is extracted. 01063 // The function vec(true, true) then deletes the strong iterators but there is 01064 // still a weak ArrayRCP object that is owned by the client which is being 01065 // passed into this function. The issue is that the design of ArrayRCP is 01066 // such that the RCPNode object is not removed but instead remains in order to 01067 // perform runtime checking. 01068 01069 01070 template<typename T> inline 01071 typename Array<T>::iterator 01072 Array<T>::insert(iterator position, const value_type& x) 01073 { 01074 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01075 // Assert a valid iterator and get vector iterator 01076 const typename std::vector<T>::iterator raw_poss = raw_position(position); 01077 const difference_type i = position - begin(); 01078 vec(true, true).insert(raw_poss, x); 01079 return begin() + i; 01080 #else 01081 return vec_.insert(position, x); 01082 #endif 01083 } 01084 01085 01086 template<typename T> inline 01087 void Array<T>::insert(iterator position, size_type n, const value_type& x) 01088 { 01089 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01090 const typename std::vector<T>::iterator raw_poss = raw_position(position); 01091 vec(true, true).insert(raw_poss, n, x); 01092 #else 01093 return vec_.insert(position, n, x); 01094 #endif 01095 } 01096 01097 01098 template<typename T> template<typename InputIterator> inline 01099 void Array<T>::insert(iterator position, InputIterator first, InputIterator last) 01100 { 01101 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01102 const typename std::vector<T>::iterator raw_poss = raw_position(position); 01103 vec(true, true).insert(raw_poss, first, last); 01104 #else 01105 return vec_.insert(position, first, last); 01106 #endif 01107 } 01108 01109 01110 template<typename T> inline 01111 typename Array<T>::iterator 01112 Array<T>::erase(iterator position) 01113 { 01114 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01115 assertNotNull(); 01116 // Assert a valid iterator and get vector iterator 01117 const typename std::vector<T>::iterator raw_poss = raw_position(position); 01118 const difference_type i = position - begin(); 01119 vec(true, true).erase(raw_poss); 01120 return begin() + i; 01121 #else 01122 return vec_.erase(position); 01123 #endif 01124 } 01125 01126 01127 template<typename T> inline 01128 typename Array<T>::iterator 01129 Array<T>::erase(iterator first, iterator last) 01130 { 01131 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01132 assertNotNull(); 01133 // Assert a valid iterator and get vector iterator 01134 const typename std::vector<T>::iterator raw_first = raw_position(first); 01135 const typename std::vector<T>::iterator raw_last = raw_position(last); 01136 const difference_type i = first - begin(); 01137 vec(true,true).erase(raw_first,raw_last); 01138 return begin() + i; 01139 #else 01140 return vec_.erase(first,last); 01141 #endif 01142 } 01143 01144 01145 template<typename T> inline 01146 void Array<T>::swap(Array& x) 01147 { 01148 vec(true).swap(x.vec()); 01149 } 01150 01151 01152 template<typename T> inline 01153 void Array<T>::clear() 01154 { 01155 vec(true).clear(); 01156 } 01157 01158 01159 // Non-standard functions 01160 01161 01162 template<typename T> inline 01163 Array<T>& Array<T>::append(const T& x) 01164 { 01165 this->push_back(x); 01166 return *this; 01167 } 01168 01169 01170 template<typename T> inline 01171 void Array<T>::remove(int i) 01172 { 01173 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01174 assertIndex(i); 01175 #endif 01176 // Erase the i-th element of this array. 01177 this->erase( this->begin() + i ); 01178 } 01179 01180 01181 template<typename T> inline 01182 int Array<T>::length() const 01183 { 01184 return this->size(); 01185 } 01186 01187 01188 template<typename T> inline 01189 std::string Array<T>::toString() const 01190 { 01191 return (*this)().toString(); 01192 } 01193 01194 01195 template<typename T> inline 01196 bool Array<T>::hasBoundsChecking() 01197 { 01198 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01199 return true; 01200 #else 01201 return false; 01202 #endif 01203 } 01204 01205 01206 template<typename T> inline 01207 T* Array<T>::getRawPtr() 01208 { 01209 return ( size() ? &(*this)[0] : 0 ); 01210 } 01211 01212 01213 template<typename T> inline 01214 const T* Array<T>::getRawPtr() const 01215 { 01216 return ( size() ? &(*this)[0] : 0 ); 01217 } 01218 01219 01220 // Conversions to and from std::vector 01221 01222 01223 template<typename T> inline 01224 Array<T>::Array( const std::vector<T> &v ) : 01225 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01226 vec_(new std::vector<T>(v)) 01227 #else 01228 vec_(v) 01229 #endif 01230 {} 01231 01232 01233 template<typename T> inline 01234 std::vector<T> Array<T>::toVector() const 01235 { 01236 if (!size()) 01237 return std::vector<T>(); 01238 std::vector<T> v(begin(),end()); 01239 return v; 01240 } 01241 01242 01243 template<typename T> inline 01244 Array<T>& Array<T>::operator=( const std::vector<T> &v ) 01245 { 01246 vec(true) = v; 01247 return *this; 01248 } 01249 01250 01251 // Views 01252 01253 01254 template<typename T> inline 01255 ArrayView<T> Array<T>::view( size_type offset, size_type size_in ) 01256 { 01257 if (size_in) { 01258 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01259 return ArrayView<T>(this->begin().persistingView(offset, size_in)); 01260 #else 01261 return arrayView( &vec()[offset], size_in ); 01262 #endif 01263 } 01264 return Teuchos::null; 01265 } 01266 01267 01268 template<typename T> inline 01269 ArrayView<const T> Array<T>::view( size_type offset, size_type size_in ) const 01270 { 01271 if (size_in) { 01272 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01273 return ArrayView<const T>(this->begin().persistingView(offset, size_in)); 01274 #else 01275 return arrayView( &vec()[offset], size_in ); 01276 #endif 01277 } 01278 return Teuchos::null; 01279 // NOTE: Above, we use a different implementation to call the const version 01280 // of begin() instead of the non-const version. This sets up a different 01281 // ArrayRCP object that gets checked. 01282 } 01283 01284 01285 template<typename T> inline 01286 ArrayView<T> Array<T>::operator()( size_type offset, size_type size_in ) 01287 { 01288 return view(offset, size_in); 01289 } 01290 01291 01292 template<typename T> inline 01293 ArrayView<const T> Array<T>::operator()( size_type offset, size_type size_in ) const 01294 { 01295 return view(offset, size_in); 01296 } 01297 01298 01299 template<typename T> inline 01300 ArrayView<T> Array<T>::operator()() 01301 { 01302 if (!size()) 01303 return null; 01304 return this->view(0, size()); 01305 } 01306 01307 01308 template<typename T> inline 01309 ArrayView<const T> Array<T>::operator()() const 01310 { 01311 if (!size()) 01312 return null; 01313 return this->view(0, size()); 01314 } 01315 01316 01317 template<typename T> inline 01318 Array<T>::operator ArrayView<T>() 01319 { 01320 return this->operator()(); 01321 } 01322 01323 01324 template<typename T> inline 01325 Array<T>::operator ArrayView<const T>() const 01326 { 01327 return this->operator()(); 01328 } 01329 01330 01331 // private 01332 01333 01334 template<typename T> 01335 std::vector<T>& 01336 Array<T>::vec( bool isStructureBeingModified, bool activeIter ) 01337 { 01338 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01339 (void)activeIter; 01340 if (isStructureBeingModified) { 01341 // Give up my ArrayRCPs used for iterator access since the array we be 01342 // getting modifed! Any clients that have views through weak pointers 01343 // better not touch them! 01344 extern_arcp_ = null; 01345 extern_carcp_ = null; 01346 } 01347 return *vec_; 01348 #else 01349 // get rid of "unused parameter" warnings 01350 (void)isStructureBeingModified; 01351 (void)activeIter; 01352 return vec_; 01353 #endif 01354 } 01355 01356 01357 template<typename T> inline 01358 const std::vector<T>& 01359 Array<T>::vec() const 01360 { 01361 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01362 return *vec_; 01363 #else 01364 return vec_; 01365 #endif 01366 } 01367 01368 01369 template<typename T> inline 01370 typename std::vector<T>::iterator 01371 Array<T>::raw_position( iterator position ) 01372 { 01373 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01374 const iterator first = this->begin(); 01375 const iterator last = this->end(); 01376 TEST_FOR_EXCEPTION( 01377 !(first <= position && position <= last), DanglingReferenceError, 01378 "Error, this iterator is no longer valid for this Aray!" 01379 ); 01380 // Note, above operator<=(...) functions will throw 01381 // IncompatibleIteratorsError if the iterators do not share the same 01382 // RCP_node object! 01383 return vec_->begin() + (position - this->begin()); 01384 #else 01385 return position; 01386 #endif 01387 } 01388 01389 01390 template<typename T> inline 01391 void Array<T>::assertIndex(int i) const 01392 { 01393 TEST_FOR_EXCEPTION( 01394 !( 0 <= i && i < length() ), RangeError, 01395 "Array<T>::assertIndex(i): i="<<i<<" out of range [0, "<< length() << ")" 01396 ); 01397 } 01398 01399 01400 template<typename T> inline 01401 void Array<T>::assertNotNull() const 01402 { 01403 TEST_FOR_EXCEPTION( 01404 !size(), NullReferenceError, 01405 typeName(*this)<<"::assertNotNull(): " 01406 "Error, the array has size zero!" 01407 ); 01408 } 01409 01410 01411 } // namespace Teuchos 01412 01413 01414 // Nonmember functions 01415 01416 01417 template<typename T> inline 01418 bool Teuchos::operator==( const Array<T> &a1, const Array<T> &a2 ) 01419 { return (a1.vec() == a2.vec()); } 01420 01421 01422 template<typename T> inline 01423 bool Teuchos::operator!=( const Array<T> &a1, const Array<T> &a2 ) 01424 { return (a1.vec() != a2.vec()); } 01425 01426 01427 template<typename T> inline 01428 void Teuchos::swap( Array<T> &a1, Array<T> &a2 ) 01429 { a1.swap(a2); } 01430 01431 01432 template<typename T> inline 01433 bool Teuchos::operator<( const Array<T> &a1, const Array<T> &a2 ) 01434 { return (a1.vec() < a2.vec()); } 01435 01436 01437 template<typename T> inline 01438 bool Teuchos::operator<=( const Array<T> &a1, const Array<T> &a2 ) 01439 { return (a1.vec() <= a2.vec()); } 01440 01441 01442 template<typename T> inline 01443 bool Teuchos::operator>( const Array<T> &a1, const Array<T> &a2 ) 01444 { return (a1.vec() > a2.vec()); } 01445 01446 01447 template<typename T> inline 01448 bool Teuchos::operator>=( const Array<T> &a1, const Array<T> &a2 ) 01449 { return (a1.vec() >= a2.vec()); } 01450 01451 01452 template<typename T> inline 01453 std::ostream& Teuchos::operator<<( 01454 std::ostream& os, const Array<T>& array 01455 ) 01456 { 01457 return os << Teuchos::toString(array); 01458 } 01459 01460 01461 template<typename T> inline 01462 int Teuchos::hashCode(const Array<T>& array) 01463 { 01464 int rtn = hashCode(array.length()); 01465 for (int i=0; i<array.length(); i++) 01466 { 01467 rtn += hashCode(array[i]); 01468 } 01469 return rtn; 01470 } 01471 01472 01473 template<typename T> inline 01474 std::vector<T> Teuchos::createVector( const Array<T> &a ) 01475 { 01476 return a.toVector(); 01477 } 01478 01479 01480 template<typename T> inline 01481 std::string Teuchos::toString(const Array<T>& array) 01482 { 01483 return array.toString(); 01484 } 01485 01486 01487 template<typename T> 01488 Teuchos::Array<T> 01489 Teuchos::fromStringToArray(const std::string& arrayStr) 01490 { 01491 const std::string str = Utils::trimWhiteSpace(arrayStr); 01492 std::istringstream iss(str); 01493 TEST_FOR_EXCEPTION( 01494 ( str[0]!='{' || str[str.length()-1] != '}' ) 01495 ,InvalidArrayStringRepresentation 01496 ,"Error, the std::string:\n" 01497 "----------\n" 01498 <<str<< 01499 "\n----------\n" 01500 "is not a valid array represntation!" 01501 ); 01502 char c; 01503 c = iss.get(); // Read initial '{' 01504 TEST_FOR_EXCEPT(c!='{'); // Should not throw! 01505 // Now we are ready to begin reading the entries of the array! 01506 Array<T> a; 01507 while( !iss.eof() ) { 01508 // Get the basic entry std::string 01509 std::string entryStr; 01510 std::getline(iss,entryStr,','); // Get next entry up to ,! 01511 // ToDo: Above, we might have to be careful to look for the opening and 01512 // closing of parentheses in order not to pick up an internal ',' in the 01513 // middle of an entry (for a std::complex number for instance). The above 01514 // implementation assumes that there will be no commas in the middle of 01515 // the std::string representation of an entry. This is certainly true for 01516 // the types bool, int, float, and double. 01517 // 01518 // Trim whitespace from beginning and end 01519 entryStr = Utils::trimWhiteSpace(entryStr); 01520 // Remove the final '}' if this is the last entry and we did not 01521 // actually terminate the above getline(...) on ',' 01522 bool found_end = false; 01523 if(entryStr[entryStr.length()-1]=='}') { 01524 entryStr = entryStr.substr(0,entryStr.length()-1); 01525 found_end = true; 01526 if( entryStr.length()==0 && a.size()==0 ) 01527 return a; // This is the empty array "{}" (with any spaces in it!) 01528 } 01529 TEST_FOR_EXCEPTION( 01530 0 == entryStr.length() 01531 ,InvalidArrayStringRepresentation 01532 ,"Error, the std::string:\n" 01533 "----------\n" 01534 <<str<< 01535 "\n----------\n" 01536 "is not a valid array represntation!" 01537 ); 01538 // Finally we can convert the entry and add it to the array! 01539 std::istringstream entryiss(entryStr); 01540 T entry; 01541 Teuchos::extractDataFromISS( entryiss, entry ); 01542 // ToDo: We may need to define a traits class to allow us to specialized 01543 // how conversion from a std::string to a object is done! 01544 a.push_back(entry); 01545 // At the end of the loop body here, if we have reached the last '}' 01546 // then the input stream iss should be empty and iss.eof() should be 01547 // true, so the loop should terminate. We put an std::exception test here 01548 // just in case something has gone wrong. 01549 TEST_FOR_EXCEPTION( 01550 found_end && !iss.eof() 01551 ,InvalidArrayStringRepresentation 01552 ,"Error, the std::string:\n" 01553 "----------\n" 01554 <<str<< 01555 "\n----------\n" 01556 "is not a valid array represntation!" 01557 ); 01558 } 01559 return a; 01560 } 01561 01562 01563 #endif // TEUCHOS_ARRAY_H
1.7.4