|
Teuchos Package Browser (Single Doxygen Collection)
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 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // *********************************************************************** 00040 // @HEADER 00041 00042 #ifndef TEUCHOS_ARRAY_H 00043 #define TEUCHOS_ARRAY_H 00044 00049 #include "Teuchos_ConfigDefs.hpp" 00050 #include "Teuchos_Assert.hpp" 00051 #include "Teuchos_TypeNameTraits.hpp" 00052 #include "Teuchos_ArrayRCP.hpp" 00053 #include "Teuchos_Tuple.hpp" 00054 #include "Teuchos_Utils.hpp" 00055 #include "Teuchos_Assert.hpp" 00056 00057 00058 namespace Teuchos { 00059 00060 00065 class InvalidArrayStringRepresentation : public std::logic_error 00066 {public:InvalidArrayStringRepresentation(const std::string& what_arg) : std::logic_error(what_arg) {}}; 00067 00068 00069 template<typename T> class Array; 00070 00071 00072 // 2007/11/30: rabartl: Below, I had to move the initial declaration of these 00073 // non-member template functions outside of the Array class since the Sun 00074 // compiler on sass9000 would not accept this. However, this did work on a 00075 // number of other compilers such a g++, Intel C++ etc. The old in-class 00076 // non-member friend definition is clearly ISO 98 C++ as shown in Item 46 of 00077 // "Effective C++: Third Edition". This is not the end of the world but this 00078 // is something to remember for this platform. 00079 00080 00085 template<typename T> inline 00086 bool operator==( const Array<T> &a1, const Array<T> &a2 ); 00087 00088 00093 template<typename T> inline 00094 bool operator!=( const Array<T> &a1, const Array<T> &a2 ); 00095 00096 00101 template<typename T> inline 00102 void swap( Array<T> &a1, Array<T> &a2 ); 00103 00104 00109 template<typename T> inline 00110 bool operator<( const Array<T> &a1, const Array<T> &a2 ); 00111 00112 00117 template<typename T> inline 00118 bool operator<=( const Array<T> &a1, const Array<T> &a2 ); 00119 00120 00125 template<typename T> inline 00126 bool operator>( const Array<T> &a1, const Array<T> &a2 ); 00127 00128 00133 template<typename T> inline 00134 bool operator>=( const Array<T> &a1, const Array<T> &a2 ); 00135 00136 00174 template<typename T> 00175 class Array 00176 { 00177 public: 00178 00179 // 2007/11/30: rabartl: Below, note that the only reason that these 00180 // functions are declared as friends is so that the compiler will do 00181 // automatic type conversions as described in "Effective C++: Third Edition" 00182 // Item 46. 00183 00185 template<typename T2> 00186 friend bool Teuchos::operator==( const Array<T2> &a1, const Array<T2> &a2 ); 00187 00189 template<typename T2> 00190 friend bool Teuchos::operator!=( const Array<T2> &a1, const Array<T2> &a2 ); 00191 00193 template<typename T2> 00194 friend void swap( Array<T2> &a1, Array<T2> &a2 ); 00195 00197 template<typename T2> 00198 friend bool Teuchos::operator<( const Array<T2> &a1, const Array<T2> &a2 ); 00199 00201 template<typename T2> 00202 friend bool Teuchos::operator<=( const Array<T2> &a1, const Array<T2> &a2 ); 00203 00205 template<typename T2> 00206 friend bool Teuchos::operator>( const Array<T2> &a1, const Array<T2> &a2 ); 00207 00209 template<typename T2> 00210 friend bool Teuchos::operator>=( const Array<T2> &a1, const Array<T2> &a2 ); 00211 00214 00216 typedef Teuchos_Ordinal Ordinal; 00218 typedef Ordinal size_type; 00220 typedef Ordinal difference_type; 00222 typedef typename std::vector<T>::value_type value_type; 00224 typedef typename std::vector<T>::pointer pointer; 00226 typedef typename std::vector<T>::const_pointer const_pointer; 00228 typedef typename std::vector<T>::reference reference; 00230 typedef typename std::vector<T>::const_reference const_reference; 00232 typedef typename std::vector<T>::allocator_type allocator_type; 00233 00234 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00235 00236 typedef ArrayRCP<T> iterator; 00238 typedef ArrayRCP<const T> const_iterator; 00240 typedef std::reverse_iterator<iterator> reverse_iterator; 00242 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00243 #else 00244 00245 typedef typename std::vector<T>::iterator iterator; 00247 typedef typename std::vector<T>::const_iterator const_iterator; 00249 typedef typename std::vector<T>::reverse_iterator reverse_iterator; 00251 typedef typename std::vector<T>::const_reverse_iterator const_reverse_iterator; 00252 #endif 00253 00255 00257 00259 inline Array(); 00260 00262 inline explicit Array(size_type n, const value_type& value = value_type()); 00263 00265 inline Array(const Array<T>& x); 00266 00268 template<typename InputIterator> 00269 inline Array(InputIterator first, InputIterator last); 00270 00272 inline Array(const ArrayView<const T>& a); 00273 00275 template<int N> 00276 inline Array(const Tuple<T,N>& t); 00277 00279 inline ~Array(); 00280 00282 inline Array& operator=(const Array<T>& a); 00283 00285 00286 00287 00288 00289 00290 00291 00293 inline void assign(size_type n, const value_type& val); 00295 template<typename InputIterator> 00296 inline void assign(InputIterator first, InputIterator last); 00298 inline iterator begin(); 00300 inline iterator end(); 00302 inline const_iterator begin() const; 00304 inline const_iterator end() const; 00306 inline reverse_iterator rbegin(); 00308 inline reverse_iterator rend(); 00310 inline const_reverse_iterator rbegin() const; 00312 inline const_reverse_iterator rend() const; 00314 inline size_type size() const; 00316 inline size_type max_size() const; 00318 inline void resize(size_type new_size, const value_type& x = value_type()); 00320 inline size_type capacity() const; 00322 inline bool empty() const; 00324 inline void reserve(size_type n); 00326 inline reference operator[](size_type i); 00328 inline const_reference operator[](size_type i) const; 00330 inline reference at(size_type i); 00332 inline const_reference at(size_type i) const; 00334 inline reference front(); 00336 inline const_reference front() const; 00338 inline reference back(); 00340 inline const_reference back() const; 00342 inline void push_back(const value_type& x); 00344 inline void pop_back(); 00346 inline iterator insert(iterator position, const value_type& x); 00348 inline void insert(iterator position, size_type n, const value_type& x); 00350 template<typename InputIterator> 00351 inline void insert(iterator position, InputIterator first, InputIterator last); 00353 inline iterator erase(iterator position); 00355 inline iterator erase(iterator first, iterator last); 00357 inline void swap(Array& x); 00359 inline void clear(); 00360 00362 00364 00369 inline Array<T>& append(const T& x); 00370 00374 inline void remove(int i); 00375 00380 inline int length() const; 00381 00383 inline std::string toString() const; 00384 00386 inline static bool hasBoundsChecking(); 00387 00389 inline T* getRawPtr(); 00390 00392 inline const T* getRawPtr() const; 00393 00395 00397 00399 inline Array( const std::vector<T> &v ); 00400 00402 inline std::vector<T> toVector() const; 00403 00405 inline Array& operator=( const std::vector<T> &v ); 00406 00408 00410 00411 00425 inline ArrayView<T> view( size_type offset, size_type size ); 00426 00440 inline ArrayView<const T> view( size_type offset, size_type size ) const; 00441 00445 inline ArrayView<T> operator()( size_type offset, size_type size ); 00446 00450 inline ArrayView<const T> operator()( size_type offset, size_type size ) const; 00451 00456 inline ArrayView<T> operator()(); 00457 00462 inline ArrayView<const T> operator()() const; 00463 00467 inline operator ArrayView<T>(); 00468 00472 inline operator ArrayView<const T>() const; 00473 00475 00476 private: 00477 00478 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00479 RCP<std::vector<T> > vec_; 00480 mutable ArrayRCP<T> extern_arcp_; 00481 mutable ArrayRCP<const T> extern_carcp_; 00482 #else 00483 std::vector<T> vec_; 00484 #endif 00485 00486 inline std::vector<T>& vec( 00487 bool isStructureBeingModified = false, 00488 bool activeIter = false 00489 ); 00490 00491 inline const std::vector<T>& vec() const; 00492 00493 inline typename std::vector<T>::iterator 00494 raw_position( iterator position ); 00495 00496 inline void assertIndex(size_type i) const; 00497 00498 inline void assertNotNull() const; 00499 00500 }; 00501 00502 00508 template<class T> 00509 ArrayRCP<T> arcp( const RCP<Array<T> > &v ) 00510 { 00511 if ( is_null(v) || !v->size() ) 00512 return null; 00513 return arcpWithEmbeddedObjPostDestroy<T,RCP<Array<T> > >( 00514 &(*v)[0], 0, v->size(), 00515 v, false 00516 ); 00517 } 00518 00519 00525 template<class T> 00526 ArrayRCP<const T> arcp( const RCP<const Array<T> > &v ) 00527 { 00528 if ( is_null(v) || !v->size() ) 00529 return null; 00530 return arcpWithEmbeddedObjPostDestroy<const T,RCP<const Array<T> > >( 00531 &(*v)[0], 0, v->size(), 00532 v, false 00533 ); 00534 } 00535 00536 00542 template<class T> 00543 ArrayRCP<T> arcpFromArray( Array<T> &a ) 00544 { 00545 if (a.size() == 0) 00546 return null; 00547 #ifdef TEUCHOS_DEBUG 00548 return a.begin(); // Catch dangling reference! 00549 #else 00550 return arcp(a.getRawPtr(), 0, a.size(), false); 00551 #endif 00552 } 00553 00554 00560 template<class T> 00561 ArrayRCP<const T> arcpFromArray( const Array<T> &a ) 00562 { 00563 if (a.size() == 0) 00564 return null; 00565 #ifdef TEUCHOS_DEBUG 00566 return a.begin(); // Catch dangling reference! 00567 #else 00568 return arcp(a.getRawPtr(), 0, a.size(), false); 00569 #endif 00570 } 00571 00572 00585 template<typename T> 00586 std::ostream& operator<<(std::ostream& os, const Array<T>& array); 00587 00588 00593 template<typename T> inline 00594 int hashCode(const Array<T>& array); 00595 00596 00603 template<typename T> inline 00604 std::vector<T> createVector( const Array<T> &a ); 00605 00606 00611 template<typename T> 00612 std::string toString(const Array<T>& array); 00613 00614 00666 template<typename T> 00667 Array<T> fromStringToArray(const std::string& arrayStr); 00668 00674 template<typename T> 00675 std::istringstream& operator>> (std::istringstream& in, Array<T>& array){ 00676 array = fromStringToArray<T>(in.str()); 00677 return in; 00678 } 00679 00685 template<typename T> inline 00686 void extractDataFromISS( std::istringstream& iss, T& data ) 00687 { 00688 iss >> data; // Assumes type has operator>>(...) defined! 00689 } 00690 00697 inline 00698 void extractDataFromISS( std::istringstream& iss, std::string& data ) 00699 { 00700 // grab unformatted string. 00701 data = iss.str(); 00702 // remove white space from beginning and end of string. 00703 data = Utils::trimWhiteSpace(data); 00704 } 00705 00715 inline 00716 std::string getArrayTypeNameTraitsFormat(){ 00717 return "Array(*)"; 00718 } 00719 00720 00721 00737 template<typename T> 00738 class TEUCHOSCORE_LIB_DLL_EXPORT TypeNameTraits<Array<T> > { 00739 public: 00740 static std::string name(){ 00741 std::string formatString = getArrayTypeNameTraitsFormat(); 00742 size_t starPos = formatString.find("*"); 00743 std::string prefix = formatString.substr(0,starPos); 00744 std::string postFix = formatString.substr(starPos+1); 00745 return prefix+TypeNameTraits<T>::name()+postFix; 00746 } 00747 static std::string concreteName(const Array<T>&) 00748 { return name(); } 00749 }; 00750 00751 00752 } // namespace Teuchos 00753 00754 00755 // 00756 // Implementation 00757 // 00758 00759 00760 namespace Teuchos { 00761 00762 00763 // All constructors 00764 00765 00766 template<typename T> inline 00767 Array<T>::Array() 00768 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00769 : vec_(rcp(new std::vector<T>())) 00770 #endif 00771 {} 00772 00773 00774 template<typename T> inline 00775 Array<T>::Array(size_type n, const value_type& value) : 00776 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00777 vec_(rcp(new std::vector<T>(n,value))) 00778 #else 00779 vec_(n, value) 00780 #endif 00781 {} 00782 00783 00784 template<typename T> inline 00785 Array<T>::Array(const Array<T>& x) : 00786 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00787 vec_(rcp(new std::vector<T>(*x.vec_))) 00788 #else 00789 vec_(x.vec_) 00790 #endif 00791 {} 00792 00793 00794 template<typename T> template<typename InputIterator> inline 00795 Array<T>::Array(InputIterator first, InputIterator last) : 00796 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00797 vec_(rcp(new std::vector<T>(first, last))) 00798 #else 00799 vec_(first, last) 00800 #endif 00801 {} 00802 00803 00804 template<typename T> inline 00805 Array<T>::~Array() 00806 {} 00807 00808 00809 template<typename T> inline 00810 Array<T>::Array(const ArrayView<const T>& a) 00811 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00812 : vec_(rcp(new std::vector<T>())) 00813 #endif 00814 { 00815 insert(begin(), a.begin(), a.end()); 00816 } 00817 00818 00819 template<typename T> 00820 template<int N> 00821 inline 00822 Array<T>::Array(const Tuple<T,N>& t) 00823 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00824 : vec_(rcp(new std::vector<T>())) 00825 #endif 00826 { 00827 insert(begin(), t.begin(), t.end()); 00828 } 00829 00830 00831 template<typename T> inline 00832 Array<T>& Array<T>::operator=(const Array& a) 00833 { 00834 vec(true) = a.vec(); 00835 return *this; 00836 } 00837 00838 00839 // Other std::vector functions 00840 00841 00842 template<typename T> inline 00843 void Array<T>::assign(size_type n, const value_type& val) 00844 { 00845 vec(true).assign(n,val); 00846 } 00847 00848 00849 template<typename T> template<typename InputIterator> inline 00850 void Array<T>::assign(InputIterator first, InputIterator last) 00851 { 00852 vec(true).assign(first,last); 00853 } 00854 00855 00856 template<typename T> inline 00857 typename Array<T>::iterator 00858 Array<T>::begin() 00859 { 00860 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00861 if (is_null(extern_arcp_)) { 00862 // Here we must use the same RCP to avoid creating two unrelated RCPNodes! 00863 extern_arcp_ = arcp(vec_); // Will be null if vec_ is sized! 00864 } 00865 // Returning a weak pointer will help to catch dangling references but still 00866 // keep the same behavior as optimized code. 00867 return extern_arcp_.create_weak(); 00868 #else 00869 return vec().begin(); 00870 #endif 00871 } 00872 00873 00874 template<typename T> inline 00875 typename Array<T>::iterator 00876 Array<T>::end() 00877 { 00878 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00879 return begin() + size(); 00880 #else 00881 return vec().end(); 00882 #endif 00883 } 00884 00885 00886 template<typename T> inline 00887 typename Array<T>::const_iterator 00888 Array<T>::begin() const 00889 { 00890 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00891 if (is_null(extern_carcp_)) { 00892 extern_carcp_ = const_cast<Array<T>*>(this)->begin(); 00893 } 00894 // Returning a weak pointer will help to catch dangling references but still 00895 // keep the same behavior as optimized code. 00896 return extern_carcp_.create_weak(); 00897 #else 00898 return vec().begin(); 00899 #endif 00900 } 00901 00902 00903 template<typename T> inline 00904 typename Array<T>::const_iterator 00905 Array<T>::end() const 00906 { 00907 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00908 return begin() + size(); 00909 #else 00910 return vec().end(); 00911 #endif 00912 } 00913 00914 00915 template<typename T> inline 00916 typename Array<T>::reverse_iterator 00917 Array<T>::rbegin() 00918 { 00919 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00920 return reverse_iterator(end()); 00921 #else 00922 return vec().rbegin(); 00923 #endif 00924 } 00925 00926 00927 template<typename T> inline 00928 typename Array<T>::reverse_iterator 00929 Array<T>::rend() 00930 { 00931 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00932 return reverse_iterator(begin()); 00933 #else 00934 return vec().rend(); 00935 #endif 00936 } 00937 00938 00939 template<typename T> inline 00940 typename Array<T>::const_reverse_iterator 00941 Array<T>::rbegin() const 00942 { 00943 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00944 return const_reverse_iterator(end()); 00945 #else 00946 return vec().rbegin(); 00947 #endif 00948 } 00949 00950 00951 template<typename T> inline 00952 typename Array<T>::const_reverse_iterator 00953 Array<T>::rend() const 00954 { 00955 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00956 return const_reverse_iterator(begin()); 00957 #else 00958 return vec().rend(); 00959 #endif 00960 } 00961 00962 00963 template<typename T> inline 00964 typename Array<T>::size_type 00965 Array<T>::size() const 00966 { 00967 return vec().size(); 00968 } 00969 00970 00971 template<typename T> inline 00972 typename Array<T>::size_type 00973 Array<T>::max_size() const 00974 { 00975 return std::numeric_limits<size_type>::max(); 00976 } 00977 00978 00979 template<typename T> inline 00980 void 00981 Array<T>::resize(size_type new_size, const value_type& x) 00982 { 00983 vec(true).resize(new_size,x); 00984 } 00985 00986 00987 template<typename T> inline 00988 typename Array<T>::size_type 00989 Array<T>::capacity() const 00990 { 00991 return vec().capacity(); 00992 } 00993 00994 00995 template<typename T> inline 00996 bool Array<T>::empty() const 00997 { 00998 return vec().empty(); 00999 } 01000 01001 01002 template<typename T> inline 01003 void Array<T>::reserve(size_type n) 01004 { 01005 vec(true).reserve(n); 01006 } 01007 01008 01009 template<typename T> inline 01010 typename Array<T>::reference 01011 Array<T>::operator[](size_type i) 01012 { 01013 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01014 assertIndex(i); 01015 #endif 01016 return vec()[i]; 01017 } 01018 01019 01020 template<typename T> inline 01021 typename Array<T>::const_reference 01022 Array<T>::operator[](size_type i) const 01023 { 01024 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01025 assertIndex(i); 01026 #endif 01027 return vec()[i]; 01028 } 01029 01030 01031 template<typename T> inline 01032 typename Array<T>::reference 01033 Array<T>::at(size_type i) 01034 { 01035 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01036 assertIndex(i); 01037 #endif 01038 return vec().at(i); 01039 } 01040 01041 01042 template<typename T> inline 01043 typename Array<T>::const_reference 01044 Array<T>::at(size_type i) const 01045 { 01046 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01047 assertIndex(i); 01048 #endif 01049 return vec().at(i); 01050 } 01051 01052 01053 template<typename T> inline 01054 typename Array<T>::reference 01055 Array<T>::front() 01056 { 01057 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01058 assertNotNull(); 01059 #endif 01060 return vec().front(); 01061 } 01062 01063 01064 template<typename T> inline 01065 typename Array<T>::const_reference 01066 Array<T>::front() const 01067 { 01068 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01069 assertNotNull(); 01070 #endif 01071 return vec().front(); 01072 } 01073 01074 01075 template<typename T> inline 01076 typename Array<T>::reference 01077 Array<T>::back() 01078 { 01079 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01080 assertNotNull(); 01081 #endif 01082 return vec().back(); 01083 } 01084 01085 01086 template<typename T> inline 01087 typename Array<T>::const_reference 01088 Array<T>::back() const 01089 { 01090 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01091 assertNotNull(); 01092 #endif 01093 return vec().back(); 01094 } 01095 01096 01097 template<typename T> inline 01098 void Array<T>::push_back(const value_type& x) 01099 { 01100 vec(true).push_back(x); 01101 } 01102 01103 01104 template<typename T> inline 01105 void Array<T>::pop_back() 01106 { 01107 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01108 assertNotNull(); 01109 #endif 01110 vec(true).pop_back(); 01111 } 01112 01113 01114 // 2009/11/13:: rabartl: After moving to a full RCPNode tracing and lookup 01115 // model, I had to how modifying functions like insert(...) and erase(...) 01116 // work which have active iterators controled by the client and yet need to 01117 // allow the structure of the container change. The way these troublesome 01118 // functions work is that first the raw std::vector iterator is extracted. 01119 // The function vec(true, true) then deletes the strong iterators but there is 01120 // still a weak ArrayRCP object that is owned by the client which is being 01121 // passed into this function. The issue is that the design of ArrayRCP is 01122 // such that the RCPNode object is not removed but instead remains in order to 01123 // perform runtime checking. 01124 01125 01126 template<typename T> inline 01127 typename Array<T>::iterator 01128 Array<T>::insert(iterator position, const value_type& x) 01129 { 01130 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01131 // Assert a valid iterator and get vector iterator 01132 const typename std::vector<T>::iterator raw_poss = raw_position(position); 01133 const difference_type i = position - begin(); 01134 vec(true, true).insert(raw_poss, x); 01135 return begin() + i; 01136 #else 01137 return vec_.insert(position, x); 01138 #endif 01139 } 01140 01141 01142 template<typename T> inline 01143 void Array<T>::insert(iterator position, size_type n, const value_type& x) 01144 { 01145 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01146 const typename std::vector<T>::iterator raw_poss = raw_position(position); 01147 vec(true, true).insert(raw_poss, n, x); 01148 #else 01149 vec_.insert(position, n, x); 01150 #endif 01151 } 01152 01153 01154 template<typename T> template<typename InputIterator> inline 01155 void Array<T>::insert(iterator position, InputIterator first, InputIterator last) 01156 { 01157 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01158 const typename std::vector<T>::iterator raw_poss = raw_position(position); 01159 vec(true, true).insert(raw_poss, first, last); 01160 #else 01161 vec_.insert(position, first, last); 01162 #endif 01163 } 01164 01165 01166 template<typename T> inline 01167 typename Array<T>::iterator 01168 Array<T>::erase(iterator position) 01169 { 01170 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01171 assertNotNull(); 01172 // Assert a valid iterator and get vector iterator 01173 const typename std::vector<T>::iterator raw_poss = raw_position(position); 01174 const difference_type i = position - begin(); 01175 vec(true, true).erase(raw_poss); 01176 return begin() + i; 01177 #else 01178 return vec_.erase(position); 01179 #endif 01180 } 01181 01182 01183 template<typename T> inline 01184 typename Array<T>::iterator 01185 Array<T>::erase(iterator first, iterator last) 01186 { 01187 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01188 if (empty()) { 01189 TEUCHOS_ASSERT(first == begin()); 01190 TEUCHOS_ASSERT(last == end()); 01191 return end(); 01192 } 01193 assertNotNull(); 01194 // Assert a valid iterator and get vector iterator 01195 const typename std::vector<T>::iterator raw_first = raw_position(first); 01196 const typename std::vector<T>::iterator raw_last = raw_position(last); 01197 const difference_type i = first - begin(); 01198 vec(true,true).erase(raw_first,raw_last); 01199 return begin() + i; 01200 #else 01201 return vec_.erase(first,last); 01202 #endif 01203 } 01204 01205 01206 template<typename T> inline 01207 void Array<T>::swap(Array& x) 01208 { 01209 vec(true).swap(x.vec()); 01210 } 01211 01212 01213 template<typename T> inline 01214 void Array<T>::clear() 01215 { 01216 vec(true).clear(); 01217 } 01218 01219 01220 // Non-standard functions 01221 01222 01223 template<typename T> inline 01224 Array<T>& Array<T>::append(const T& x) 01225 { 01226 this->push_back(x); 01227 return *this; 01228 } 01229 01230 01231 template<typename T> inline 01232 void Array<T>::remove(int i) 01233 { 01234 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01235 assertIndex(i); 01236 #endif 01237 // Erase the i-th element of this array. 01238 this->erase( this->begin() + i ); 01239 } 01240 01241 01242 template<typename T> inline 01243 int Array<T>::length() const 01244 { 01245 return static_cast<int> (this->size ()); 01246 } 01247 01248 01249 template<typename T> inline 01250 std::string Array<T>::toString() const 01251 { 01252 return (*this)().toString(); // Use ArrayView<T>::toString() 01253 } 01254 01255 01256 template<typename T> inline 01257 bool Array<T>::hasBoundsChecking() 01258 { 01259 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01260 return true; 01261 #else 01262 return false; 01263 #endif 01264 } 01265 01266 01267 template<typename T> inline 01268 T* Array<T>::getRawPtr() 01269 { 01270 return ( size() ? &(*this)[0] : 0 ); 01271 } 01272 01273 01274 template<typename T> inline 01275 const T* Array<T>::getRawPtr() const 01276 { 01277 return ( size() ? &(*this)[0] : 0 ); 01278 } 01279 01280 01281 // Conversions to and from std::vector 01282 01283 01284 template<typename T> inline 01285 Array<T>::Array( const std::vector<T> &v ) : 01286 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01287 vec_(new std::vector<T>(v)) 01288 #else 01289 vec_(v) 01290 #endif 01291 {} 01292 01293 01294 template<typename T> inline 01295 std::vector<T> Array<T>::toVector() const 01296 { 01297 if (!size()) 01298 return std::vector<T>(); 01299 std::vector<T> v(begin(),end()); 01300 return v; 01301 } 01302 01303 01304 template<typename T> inline 01305 Array<T>& Array<T>::operator=( const std::vector<T> &v ) 01306 { 01307 vec(true) = v; 01308 return *this; 01309 } 01310 01311 01312 // Views 01313 01314 01315 template<typename T> inline 01316 ArrayView<T> Array<T>::view( size_type offset, size_type size_in ) 01317 { 01318 if (size_in) { 01319 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01320 return ArrayView<T>(this->begin().persistingView(offset, size_in)); 01321 #else 01322 return arrayView( &vec()[offset], size_in ); 01323 #endif 01324 } 01325 return Teuchos::null; 01326 } 01327 01328 01329 template<typename T> inline 01330 ArrayView<const T> Array<T>::view( size_type offset, size_type size_in ) const 01331 { 01332 if (size_in) { 01333 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01334 return ArrayView<const T>(this->begin().persistingView(offset, size_in)); 01335 #else 01336 return arrayView( &vec()[offset], size_in ); 01337 #endif 01338 } 01339 return Teuchos::null; 01340 // NOTE: Above, we use a different implementation to call the const version 01341 // of begin() instead of the non-const version. This sets up a different 01342 // ArrayRCP object that gets checked. 01343 } 01344 01345 01346 template<typename T> inline 01347 ArrayView<T> Array<T>::operator()( size_type offset, size_type size_in ) 01348 { 01349 return view(offset, size_in); 01350 } 01351 01352 01353 template<typename T> inline 01354 ArrayView<const T> Array<T>::operator()( size_type offset, size_type size_in ) const 01355 { 01356 return view(offset, size_in); 01357 } 01358 01359 01360 template<typename T> inline 01361 ArrayView<T> Array<T>::operator()() 01362 { 01363 if (!size()) 01364 return null; 01365 return this->view(0, size()); 01366 } 01367 01368 01369 template<typename T> inline 01370 ArrayView<const T> Array<T>::operator()() const 01371 { 01372 if (!size()) 01373 return null; 01374 return this->view(0, size()); 01375 } 01376 01377 01378 template<typename T> inline 01379 Array<T>::operator ArrayView<T>() 01380 { 01381 return this->operator()(); 01382 } 01383 01384 01385 template<typename T> inline 01386 Array<T>::operator ArrayView<const T>() const 01387 { 01388 return this->operator()(); 01389 } 01390 01391 01392 // private 01393 01394 01395 template<typename T> 01396 std::vector<T>& 01397 Array<T>::vec( bool isStructureBeingModified, bool activeIter ) 01398 { 01399 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01400 (void)activeIter; 01401 if (isStructureBeingModified) { 01402 // Give up my ArrayRCPs used for iterator access since the array we be 01403 // getting modifed! Any clients that have views through weak pointers 01404 // better not touch them! 01405 extern_arcp_ = null; 01406 extern_carcp_ = null; 01407 } 01408 return *vec_; 01409 #else 01410 // get rid of "unused parameter" warnings 01411 (void)isStructureBeingModified; 01412 (void)activeIter; 01413 return vec_; 01414 #endif 01415 } 01416 01417 01418 template<typename T> inline 01419 const std::vector<T>& 01420 Array<T>::vec() const 01421 { 01422 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01423 return *vec_; 01424 #else 01425 return vec_; 01426 #endif 01427 } 01428 01429 01430 template<typename T> inline 01431 typename std::vector<T>::iterator 01432 Array<T>::raw_position( iterator position ) 01433 { 01434 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01435 const iterator first = this->begin(); 01436 const iterator last = this->end(); 01437 TEUCHOS_TEST_FOR_EXCEPTION( 01438 !(first <= position && position <= last), DanglingReferenceError, 01439 "Error, this iterator is no longer valid for this Aray!" 01440 ); 01441 // Note, above operator<=(...) functions will throw 01442 // IncompatibleIteratorsError if the iterators do not share the same 01443 // RCP_node object! 01444 return vec_->begin() + (position - this->begin()); 01445 #else 01446 return position; 01447 #endif 01448 } 01449 01450 01451 template<typename T> inline 01452 void Array<T>::assertIndex(size_type i) const 01453 { 01454 TEUCHOS_TEST_FOR_EXCEPTION( 01455 !( 0 <= i && i < size() ), RangeError, 01456 "Array<T>::assertIndex(i): i="<<i<<" out of range [0, "<< size() << ")" 01457 ); 01458 } 01459 01460 01461 template<typename T> inline 01462 void Array<T>::assertNotNull() const 01463 { 01464 TEUCHOS_TEST_FOR_EXCEPTION( 01465 !size(), NullReferenceError, 01466 typeName(*this)<<"::assertNotNull(): " 01467 "Error, the array has size zero!" 01468 ); 01469 } 01470 01471 01472 } // namespace Teuchos 01473 01474 01475 // Nonmember functions 01476 01477 01478 template<typename T> inline 01479 bool Teuchos::operator==( const Array<T> &a1, const Array<T> &a2 ) 01480 { return (a1.vec() == a2.vec()); } 01481 01482 01483 template<typename T> inline 01484 bool Teuchos::operator!=( const Array<T> &a1, const Array<T> &a2 ) 01485 { return (a1.vec() != a2.vec()); } 01486 01487 01488 template<typename T> inline 01489 void Teuchos::swap( Array<T> &a1, Array<T> &a2 ) 01490 { a1.swap(a2); } 01491 01492 01493 template<typename T> inline 01494 bool Teuchos::operator<( const Array<T> &a1, const Array<T> &a2 ) 01495 { return (a1.vec() < a2.vec()); } 01496 01497 01498 template<typename T> inline 01499 bool Teuchos::operator<=( const Array<T> &a1, const Array<T> &a2 ) 01500 { return (a1.vec() <= a2.vec()); } 01501 01502 01503 template<typename T> inline 01504 bool Teuchos::operator>( const Array<T> &a1, const Array<T> &a2 ) 01505 { return (a1.vec() > a2.vec()); } 01506 01507 01508 template<typename T> inline 01509 bool Teuchos::operator>=( const Array<T> &a1, const Array<T> &a2 ) 01510 { return (a1.vec() >= a2.vec()); } 01511 01512 01513 template<typename T> inline 01514 std::ostream& Teuchos::operator<<( 01515 std::ostream& os, const Array<T>& array 01516 ) 01517 { 01518 return os << Teuchos::toString(array); 01519 } 01520 01521 01522 template<typename T> inline 01523 int Teuchos::hashCode(const Array<T>& array) 01524 { 01525 int rtn = hashCode(array.length()); 01526 for (int i=0; i<array.length(); i++) 01527 { 01528 rtn += hashCode(array[i]); 01529 } 01530 if (rtn < 0) 01531 { 01532 /* Convert the largest -ve int to zero and -1 to 01533 * std::numeric_limits<int>::max() 01534 * */ 01535 size_t maxIntBeforeWrap = std::numeric_limits<int>::max(); 01536 maxIntBeforeWrap ++; 01537 rtn += maxIntBeforeWrap; 01538 } 01539 return rtn; 01540 } 01541 01542 01543 template<typename T> inline 01544 std::vector<T> Teuchos::createVector( const Array<T> &a ) 01545 { 01546 return a.toVector(); 01547 } 01548 01549 01550 template<typename T> inline 01551 std::string Teuchos::toString(const Array<T>& array) 01552 { 01553 return array.toString(); 01554 } 01555 01556 01557 template<typename T> 01558 Teuchos::Array<T> 01559 Teuchos::fromStringToArray(const std::string& arrayStr) 01560 { 01561 const std::string str = Utils::trimWhiteSpace(arrayStr); 01562 std::istringstream iss(str); 01563 TEUCHOS_TEST_FOR_EXCEPTION( 01564 ( str[0]!='{' || str[str.length()-1] != '}' ) 01565 ,InvalidArrayStringRepresentation 01566 ,"Error, the std::string:\n" 01567 "----------\n" 01568 <<str<< 01569 "\n----------\n" 01570 "is not a valid array represntation!" 01571 ); 01572 char c; 01573 c = iss.get(); // Read initial '{' 01574 TEUCHOS_TEST_FOR_EXCEPT(c!='{'); // Should not throw! 01575 // Now we are ready to begin reading the entries of the array! 01576 Array<T> a; 01577 while( !iss.eof() ) { 01578 // Get the basic entry std::string 01579 std::string entryStr; 01580 std::getline(iss,entryStr,','); // Get next entry up to ,! 01581 // ToDo: Above, we might have to be careful to look for the opening and 01582 // closing of parentheses in order not to pick up an internal ',' in the 01583 // middle of an entry (for a std::complex number for instance). The above 01584 // implementation assumes that there will be no commas in the middle of 01585 // the std::string representation of an entry. This is certainly true for 01586 // the types bool, int, float, and double. 01587 // 01588 // Trim whitespace from beginning and end 01589 entryStr = Utils::trimWhiteSpace(entryStr); 01590 TEUCHOS_TEST_FOR_EXCEPTION( 01591 0 == entryStr.length(), 01592 InvalidArrayStringRepresentation, 01593 "Error, the std::string:\n" 01594 "----------\n" 01595 <<str<< 01596 "\n----------\n" 01597 "is not a valid array represntation because it has an empty array entry!" 01598 ); 01599 // Remove the final '}' if this is the last entry and we did not 01600 // actually terminate the above getline(...) on ',' 01601 bool found_end = false; 01602 if(entryStr[entryStr.length()-1]=='}') { 01603 entryStr = entryStr.substr(0,entryStr.length()-1); 01604 found_end = true; 01605 if( entryStr.length()==0 && a.size()==0 ) 01606 return a; // This is the empty array "{}" (with any spaces in it!) 01607 } 01608 // Finally we can convert the entry and add it to the array! 01609 std::istringstream entryiss(entryStr); 01610 T entry; 01611 Teuchos::extractDataFromISS( entryiss, entry ); 01612 // ToDo: We may need to define a traits class to allow us to specialized 01613 // how conversion from a std::string to a object is done! 01614 a.push_back(entry); 01615 // At the end of the loop body here, if we have reached the last '}' 01616 // then the input stream iss should be empty and iss.eof() should be 01617 // true, so the loop should terminate. We put an std::exception test here 01618 // just in case something has gone wrong. 01619 TEUCHOS_TEST_FOR_EXCEPTION( 01620 found_end && !iss.eof() 01621 ,InvalidArrayStringRepresentation 01622 ,"Error, the std::string:\n" 01623 "----------\n" 01624 <<str<< 01625 "\n----------\n" 01626 "is not a valid array represntation!" 01627 ); 01628 } 01629 return a; 01630 } 01631 01632 01633 #endif // TEUCHOS_ARRAY_H
1.7.6.1