|
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 00254 00256 00259 00261 inline Array(); 00263 inline explicit Array(size_type n, const value_type& value = value_type()); 00265 inline Array(const Array<T>& x); 00267 template<typename InputIterator> 00268 inline Array(InputIterator first, InputIterator last); 00270 inline Array(const ArrayView<const T>& a); 00272 template<int N> 00273 inline Array(const Tuple<T,N>& t); 00275 inline ~Array(); 00277 inline Array& operator=(const Array<T>& a); 00278 00280 00283 00285 inline void assign(size_type n, const value_type& val); 00287 template<typename InputIterator> 00288 inline void assign(InputIterator first, InputIterator last); 00290 inline iterator begin(); 00292 inline iterator end(); 00294 inline const_iterator begin() const; 00296 inline const_iterator end() const; 00298 inline reverse_iterator rbegin(); 00300 inline reverse_iterator rend(); 00302 inline const_reverse_iterator rbegin() const; 00304 inline const_reverse_iterator rend() const; 00306 inline size_type size() const; 00308 inline size_type max_size() const; 00310 inline void resize(size_type new_size, const value_type& x = value_type()); 00312 inline size_type capacity() const; 00314 inline bool empty() const; 00316 inline void reserve(size_type n); 00318 inline reference operator[](size_type i); 00320 inline const_reference operator[](size_type i) const; 00322 inline reference at(size_type i); 00324 inline const_reference at(size_type i) const; 00326 inline reference front(); 00328 inline const_reference front() const; 00330 inline reference back(); 00332 inline const_reference back() const; 00334 inline void push_back(const value_type& x); 00336 inline void pop_back(); 00338 inline iterator insert(iterator position, const value_type& x); 00340 inline void insert(iterator position, size_type n, const value_type& x); 00342 template<typename InputIterator> 00343 inline void insert(iterator position, InputIterator first, InputIterator last); 00345 inline iterator erase(iterator position); 00347 inline iterator erase(iterator first, iterator last); 00349 inline void swap(Array& x); 00351 inline void clear(); 00352 00354 00357 00362 inline Array<T>& append(const T& x); 00363 00367 inline void remove(int i); 00368 00373 inline int length() const; 00374 00376 inline std::string toString() const; 00377 00379 inline static bool hasBoundsChecking(); 00380 00382 inline T* getRawPtr(); 00383 00385 inline const T* getRawPtr() const; 00386 00388 00391 00393 inline Array( const std::vector<T> &v ); 00394 00396 inline std::vector<T> toVector() const; 00397 00399 inline Array& operator=( const std::vector<T> &v ); 00400 00402 00404 00405 00419 inline ArrayView<T> view( size_type offset, size_type size ); 00420 00434 inline ArrayView<const T> view( size_type offset, size_type size ) const; 00435 00439 inline ArrayView<T> operator()( size_type offset, size_type size ); 00440 00444 inline ArrayView<const T> operator()( size_type offset, size_type size ) const; 00445 00450 inline ArrayView<T> operator()(); 00451 00456 inline ArrayView<const T> operator()() const; 00457 00461 inline operator ArrayView<T>(); 00462 00466 inline operator ArrayView<const T>() const; 00467 00469 00470 private: 00471 00472 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00473 RCP<std::vector<T> > vec_; 00474 mutable ArrayRCP<T> extern_arcp_; 00475 mutable ArrayRCP<const T> extern_carcp_; 00476 #else 00477 std::vector<T> vec_; 00478 #endif 00479 00480 inline std::vector<T>& vec( 00481 bool isStructureBeingModified = false, 00482 bool activeIter = false 00483 ); 00484 00485 inline const std::vector<T>& vec() const; 00486 00487 inline typename std::vector<T>::iterator 00488 raw_position( iterator position ); 00489 00490 inline void assertIndex(int i) const; 00491 00492 inline void assertNotNull() const; 00493 00494 }; 00495 00496 00502 template<class T> 00503 ArrayRCP<T> arcp( const RCP<Array<T> > &v ) 00504 { 00505 if ( is_null(v) || !v->size() ) 00506 return null; 00507 return arcpWithEmbeddedObjPostDestroy<T,RCP<Array<T> > >( 00508 &(*v)[0], 0, v->size(), 00509 v, false 00510 ); 00511 } 00512 00513 00519 template<class T> 00520 ArrayRCP<const T> arcp( const RCP<const Array<T> > &v ) 00521 { 00522 if ( is_null(v) || !v->size() ) 00523 return null; 00524 return arcpWithEmbeddedObjPostDestroy<const T,RCP<const Array<T> > >( 00525 &(*v)[0], 0, v->size(), 00526 v, false 00527 ); 00528 } 00529 00530 00536 template<class T> 00537 ArrayRCP<T> arcpFromArray( Array<T> &a ) 00538 { 00539 if (a.size() == 0) 00540 return null; 00541 #ifdef TEUCHOS_DEBUG 00542 return a.begin(); // Catch dangling reference! 00543 #else 00544 return arcp(a.getRawPtr(), 0, a.size(), false); 00545 #endif 00546 } 00547 00548 00554 template<class T> 00555 ArrayRCP<const T> arcpFromArray( const Array<T> &a ) 00556 { 00557 if (a.size() == 0) 00558 return null; 00559 #ifdef TEUCHOS_DEBUG 00560 return a.begin(); // Catch dangling reference! 00561 #else 00562 return arcp(a.getRawPtr(), 0, a.size(), false); 00563 #endif 00564 } 00565 00566 00579 template<typename T> 00580 std::ostream& operator<<(std::ostream& os, const Array<T>& array); 00581 00582 00587 template<typename T> inline 00588 int hashCode(const Array<T>& array); 00589 00590 00597 template<typename T> inline 00598 std::vector<T> createVector( const Array<T> &a ); 00599 00600 00605 template<typename T> 00606 std::string toString(const Array<T>& array); 00607 00608 00660 template<typename T> 00661 Array<T> fromStringToArray(const std::string& arrayStr); 00662 00668 template<typename T> 00669 std::istringstream& operator>> (std::istringstream& in, Array<T>& array){ 00670 array = fromStringToArray<T>(in.str()); 00671 return in; 00672 } 00673 00679 template<typename T> inline 00680 void extractDataFromISS( std::istringstream& iss, T& data ) 00681 { 00682 iss >> data; // Assumes type has operator>>(...) defined! 00683 } 00684 00691 inline 00692 void extractDataFromISS( std::istringstream& iss, std::string& data ) 00693 { 00694 // grab unformatted string. 00695 data = iss.str(); 00696 // remove white space from beginning and end of string. 00697 data = Utils::trimWhiteSpace(data); 00698 } 00699 00709 inline 00710 std::string getArrayTypeNameTraitsFormat(){ 00711 return "Array(*)"; 00712 } 00713 00714 00715 00731 template<typename T> 00732 class TEUCHOS_LIB_DLL_EXPORT TypeNameTraits<Array<T> > { 00733 public: 00734 static std::string name(){ 00735 std::string formatString = getArrayTypeNameTraitsFormat(); 00736 size_t starPos = formatString.find("*"); 00737 std::string prefix = formatString.substr(0,starPos); 00738 std::string postFix = formatString.substr(starPos+1); 00739 return prefix+TypeNameTraits<T>::name()+postFix; 00740 } 00741 static std::string concreteName(const Array<T>&) 00742 { return name(); } 00743 }; 00744 00745 00746 } // namespace Teuchos 00747 00748 00749 // 00750 // Implementation 00751 // 00752 00753 00754 namespace Teuchos { 00755 00756 00757 // All constructors 00758 00759 00760 template<typename T> inline 00761 Array<T>::Array() 00762 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00763 : vec_(rcp(new std::vector<T>())) 00764 #endif 00765 {} 00766 00767 00768 template<typename T> inline 00769 Array<T>::Array(size_type n, const value_type& value) : 00770 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00771 vec_(rcp(new std::vector<T>(n,value))) 00772 #else 00773 vec_(n, value) 00774 #endif 00775 {} 00776 00777 00778 template<typename T> inline 00779 Array<T>::Array(const Array<T>& x) : 00780 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00781 vec_(rcp(new std::vector<T>(*x.vec_))) 00782 #else 00783 vec_(x.vec_) 00784 #endif 00785 {} 00786 00787 00788 template<typename T> template<typename InputIterator> inline 00789 Array<T>::Array(InputIterator first, InputIterator last) : 00790 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00791 vec_(rcp(new std::vector<T>(first, last))) 00792 #else 00793 vec_(first, last) 00794 #endif 00795 {} 00796 00797 00798 template<typename T> inline 00799 Array<T>::~Array() 00800 {} 00801 00802 00803 template<typename T> inline 00804 Array<T>::Array(const ArrayView<const T>& a) 00805 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00806 : vec_(rcp(new std::vector<T>())) 00807 #endif 00808 { 00809 insert(begin(), a.begin(), a.end()); 00810 } 00811 00812 00813 template<typename T> 00814 template<int N> 00815 inline 00816 Array<T>::Array(const Tuple<T,N>& t) 00817 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00818 : vec_(rcp(new std::vector<T>())) 00819 #endif 00820 { 00821 insert(begin(), t.begin(), t.end()); 00822 } 00823 00824 00825 template<typename T> inline 00826 Array<T>& Array<T>::operator=(const Array& a) 00827 { 00828 vec(true) = a.vec(); 00829 return *this; 00830 } 00831 00832 00833 // Other std::vector functions 00834 00835 00836 template<typename T> inline 00837 void Array<T>::assign(size_type n, const value_type& val) 00838 { 00839 vec(true).assign(n,val); 00840 } 00841 00842 00843 template<typename T> template<typename InputIterator> inline 00844 void Array<T>::assign(InputIterator first, InputIterator last) 00845 { 00846 vec(true).assign(first,last); 00847 } 00848 00849 00850 template<typename T> inline 00851 typename Array<T>::iterator 00852 Array<T>::begin() 00853 { 00854 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00855 if (is_null(extern_arcp_)) { 00856 // Here we must use the same RCP to avoid creating two unrelated RCPNodes! 00857 extern_arcp_ = arcp(vec_); // Will be null if vec_ is sized! 00858 } 00859 // Returning a weak pointer will help to catch dangling references but still 00860 // keep the same behavior as optimized code. 00861 return extern_arcp_.create_weak(); 00862 #else 00863 return vec().begin(); 00864 #endif 00865 } 00866 00867 00868 template<typename T> inline 00869 typename Array<T>::iterator 00870 Array<T>::end() 00871 { 00872 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00873 return begin() + size(); 00874 #else 00875 return vec().end(); 00876 #endif 00877 } 00878 00879 00880 template<typename T> inline 00881 typename Array<T>::const_iterator 00882 Array<T>::begin() const 00883 { 00884 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00885 if (is_null(extern_carcp_)) { 00886 extern_carcp_ = const_cast<Array<T>*>(this)->begin(); 00887 } 00888 // Returning a weak pointer will help to catch dangling references but still 00889 // keep the same behavior as optimized code. 00890 return extern_carcp_.create_weak(); 00891 #else 00892 return vec().begin(); 00893 #endif 00894 } 00895 00896 00897 template<typename T> inline 00898 typename Array<T>::const_iterator 00899 Array<T>::end() const 00900 { 00901 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00902 return begin() + size(); 00903 #else 00904 return vec().end(); 00905 #endif 00906 } 00907 00908 00909 template<typename T> inline 00910 typename Array<T>::reverse_iterator 00911 Array<T>::rbegin() 00912 { 00913 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00914 return reverse_iterator(end()); 00915 #else 00916 return vec().rbegin(); 00917 #endif 00918 } 00919 00920 00921 template<typename T> inline 00922 typename Array<T>::reverse_iterator 00923 Array<T>::rend() 00924 { 00925 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00926 return reverse_iterator(begin()); 00927 #else 00928 return vec().rend(); 00929 #endif 00930 } 00931 00932 00933 template<typename T> inline 00934 typename Array<T>::const_reverse_iterator 00935 Array<T>::rbegin() const 00936 { 00937 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00938 return const_reverse_iterator(end()); 00939 #else 00940 return vec().rbegin(); 00941 #endif 00942 } 00943 00944 00945 template<typename T> inline 00946 typename Array<T>::const_reverse_iterator 00947 Array<T>::rend() const 00948 { 00949 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 00950 return const_reverse_iterator(begin()); 00951 #else 00952 return vec().rend(); 00953 #endif 00954 } 00955 00956 00957 template<typename T> inline 00958 typename Array<T>::size_type 00959 Array<T>::size() const 00960 { 00961 return vec().size(); 00962 } 00963 00964 00965 template<typename T> inline 00966 typename Array<T>::size_type 00967 Array<T>::max_size() const 00968 { 00969 return std::numeric_limits<size_type>::max(); 00970 } 00971 00972 00973 template<typename T> inline 00974 void 00975 Array<T>::resize(size_type new_size, const value_type& x) 00976 { 00977 vec(true).resize(new_size,x); 00978 } 00979 00980 00981 template<typename T> inline 00982 typename Array<T>::size_type 00983 Array<T>::capacity() const 00984 { 00985 return vec().capacity(); 00986 } 00987 00988 00989 template<typename T> inline 00990 bool Array<T>::empty() const 00991 { 00992 return vec().empty(); 00993 } 00994 00995 00996 template<typename T> inline 00997 void Array<T>::reserve(size_type n) 00998 { 00999 vec(true).reserve(n); 01000 } 01001 01002 01003 template<typename T> inline 01004 typename Array<T>::reference 01005 Array<T>::operator[](size_type i) 01006 { 01007 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01008 assertIndex(i); 01009 #endif 01010 return vec()[i]; 01011 } 01012 01013 01014 template<typename T> inline 01015 typename Array<T>::const_reference 01016 Array<T>::operator[](size_type i) const 01017 { 01018 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01019 assertIndex(i); 01020 #endif 01021 return vec()[i]; 01022 } 01023 01024 01025 template<typename T> inline 01026 typename Array<T>::reference 01027 Array<T>::at(size_type i) 01028 { 01029 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01030 assertIndex(i); 01031 #endif 01032 return vec().at(i); 01033 } 01034 01035 01036 template<typename T> inline 01037 typename Array<T>::const_reference 01038 Array<T>::at(size_type i) const 01039 { 01040 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01041 assertIndex(i); 01042 #endif 01043 return vec().at(i); 01044 } 01045 01046 01047 template<typename T> inline 01048 typename Array<T>::reference 01049 Array<T>::front() 01050 { 01051 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01052 assertNotNull(); 01053 #endif 01054 return vec().front(); 01055 } 01056 01057 01058 template<typename T> inline 01059 typename Array<T>::const_reference 01060 Array<T>::front() const 01061 { 01062 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01063 assertNotNull(); 01064 #endif 01065 return vec().front(); 01066 } 01067 01068 01069 template<typename T> inline 01070 typename Array<T>::reference 01071 Array<T>::back() 01072 { 01073 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01074 assertNotNull(); 01075 #endif 01076 return vec().back(); 01077 } 01078 01079 01080 template<typename T> inline 01081 typename Array<T>::const_reference 01082 Array<T>::back() const 01083 { 01084 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01085 assertNotNull(); 01086 #endif 01087 return vec().back(); 01088 } 01089 01090 01091 template<typename T> inline 01092 void Array<T>::push_back(const value_type& x) 01093 { 01094 vec(true).push_back(x); 01095 } 01096 01097 01098 template<typename T> inline 01099 void Array<T>::pop_back() 01100 { 01101 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01102 assertNotNull(); 01103 #endif 01104 vec(true).pop_back(); 01105 } 01106 01107 01108 // 2009/11/13:: rabartl: After moving to a full RCPNode tracing and lookup 01109 // model, I had to how modifying functions like insert(...) and erase(...) 01110 // work which have active iterators controled by the client and yet need to 01111 // allow the structure of the container change. The way these troublesome 01112 // functions work is that first the raw std::vector iterator is extracted. 01113 // The function vec(true, true) then deletes the strong iterators but there is 01114 // still a weak ArrayRCP object that is owned by the client which is being 01115 // passed into this function. The issue is that the design of ArrayRCP is 01116 // such that the RCPNode object is not removed but instead remains in order to 01117 // perform runtime checking. 01118 01119 01120 template<typename T> inline 01121 typename Array<T>::iterator 01122 Array<T>::insert(iterator position, const value_type& x) 01123 { 01124 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01125 // Assert a valid iterator and get vector iterator 01126 const typename std::vector<T>::iterator raw_poss = raw_position(position); 01127 const difference_type i = position - begin(); 01128 vec(true, true).insert(raw_poss, x); 01129 return begin() + i; 01130 #else 01131 return vec_.insert(position, x); 01132 #endif 01133 } 01134 01135 01136 template<typename T> inline 01137 void Array<T>::insert(iterator position, size_type n, const value_type& x) 01138 { 01139 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01140 const typename std::vector<T>::iterator raw_poss = raw_position(position); 01141 vec(true, true).insert(raw_poss, n, x); 01142 #else 01143 return vec_.insert(position, n, x); 01144 #endif 01145 } 01146 01147 01148 template<typename T> template<typename InputIterator> inline 01149 void Array<T>::insert(iterator position, InputIterator first, InputIterator last) 01150 { 01151 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01152 const typename std::vector<T>::iterator raw_poss = raw_position(position); 01153 vec(true, true).insert(raw_poss, first, last); 01154 #else 01155 return vec_.insert(position, first, last); 01156 #endif 01157 } 01158 01159 01160 template<typename T> inline 01161 typename Array<T>::iterator 01162 Array<T>::erase(iterator position) 01163 { 01164 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01165 assertNotNull(); 01166 // Assert a valid iterator and get vector iterator 01167 const typename std::vector<T>::iterator raw_poss = raw_position(position); 01168 const difference_type i = position - begin(); 01169 vec(true, true).erase(raw_poss); 01170 return begin() + i; 01171 #else 01172 return vec_.erase(position); 01173 #endif 01174 } 01175 01176 01177 template<typename T> inline 01178 typename Array<T>::iterator 01179 Array<T>::erase(iterator first, iterator last) 01180 { 01181 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01182 if (empty()) { 01183 TEUCHOS_ASSERT(first == begin()); 01184 TEUCHOS_ASSERT(last == end()); 01185 return end(); 01186 } 01187 assertNotNull(); 01188 // Assert a valid iterator and get vector iterator 01189 const typename std::vector<T>::iterator raw_first = raw_position(first); 01190 const typename std::vector<T>::iterator raw_last = raw_position(last); 01191 const difference_type i = first - begin(); 01192 vec(true,true).erase(raw_first,raw_last); 01193 return begin() + i; 01194 #else 01195 return vec_.erase(first,last); 01196 #endif 01197 } 01198 01199 01200 template<typename T> inline 01201 void Array<T>::swap(Array& x) 01202 { 01203 vec(true).swap(x.vec()); 01204 } 01205 01206 01207 template<typename T> inline 01208 void Array<T>::clear() 01209 { 01210 vec(true).clear(); 01211 } 01212 01213 01214 // Non-standard functions 01215 01216 01217 template<typename T> inline 01218 Array<T>& Array<T>::append(const T& x) 01219 { 01220 this->push_back(x); 01221 return *this; 01222 } 01223 01224 01225 template<typename T> inline 01226 void Array<T>::remove(int i) 01227 { 01228 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01229 assertIndex(i); 01230 #endif 01231 // Erase the i-th element of this array. 01232 this->erase( this->begin() + i ); 01233 } 01234 01235 01236 template<typename T> inline 01237 int Array<T>::length() const 01238 { 01239 return this->size(); 01240 } 01241 01242 01243 template<typename T> inline 01244 std::string Array<T>::toString() const 01245 { 01246 return (*this)().toString(); // Use ArrayView<T>::toString() 01247 } 01248 01249 01250 template<typename T> inline 01251 bool Array<T>::hasBoundsChecking() 01252 { 01253 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01254 return true; 01255 #else 01256 return false; 01257 #endif 01258 } 01259 01260 01261 template<typename T> inline 01262 T* Array<T>::getRawPtr() 01263 { 01264 return ( size() ? &(*this)[0] : 0 ); 01265 } 01266 01267 01268 template<typename T> inline 01269 const T* Array<T>::getRawPtr() const 01270 { 01271 return ( size() ? &(*this)[0] : 0 ); 01272 } 01273 01274 01275 // Conversions to and from std::vector 01276 01277 01278 template<typename T> inline 01279 Array<T>::Array( const std::vector<T> &v ) : 01280 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01281 vec_(new std::vector<T>(v)) 01282 #else 01283 vec_(v) 01284 #endif 01285 {} 01286 01287 01288 template<typename T> inline 01289 std::vector<T> Array<T>::toVector() const 01290 { 01291 if (!size()) 01292 return std::vector<T>(); 01293 std::vector<T> v(begin(),end()); 01294 return v; 01295 } 01296 01297 01298 template<typename T> inline 01299 Array<T>& Array<T>::operator=( const std::vector<T> &v ) 01300 { 01301 vec(true) = v; 01302 return *this; 01303 } 01304 01305 01306 // Views 01307 01308 01309 template<typename T> inline 01310 ArrayView<T> Array<T>::view( size_type offset, size_type size_in ) 01311 { 01312 if (size_in) { 01313 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01314 return ArrayView<T>(this->begin().persistingView(offset, size_in)); 01315 #else 01316 return arrayView( &vec()[offset], size_in ); 01317 #endif 01318 } 01319 return Teuchos::null; 01320 } 01321 01322 01323 template<typename T> inline 01324 ArrayView<const T> Array<T>::view( size_type offset, size_type size_in ) const 01325 { 01326 if (size_in) { 01327 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01328 return ArrayView<const T>(this->begin().persistingView(offset, size_in)); 01329 #else 01330 return arrayView( &vec()[offset], size_in ); 01331 #endif 01332 } 01333 return Teuchos::null; 01334 // NOTE: Above, we use a different implementation to call the const version 01335 // of begin() instead of the non-const version. This sets up a different 01336 // ArrayRCP object that gets checked. 01337 } 01338 01339 01340 template<typename T> inline 01341 ArrayView<T> Array<T>::operator()( size_type offset, size_type size_in ) 01342 { 01343 return view(offset, size_in); 01344 } 01345 01346 01347 template<typename T> inline 01348 ArrayView<const T> Array<T>::operator()( size_type offset, size_type size_in ) const 01349 { 01350 return view(offset, size_in); 01351 } 01352 01353 01354 template<typename T> inline 01355 ArrayView<T> Array<T>::operator()() 01356 { 01357 if (!size()) 01358 return null; 01359 return this->view(0, size()); 01360 } 01361 01362 01363 template<typename T> inline 01364 ArrayView<const T> Array<T>::operator()() const 01365 { 01366 if (!size()) 01367 return null; 01368 return this->view(0, size()); 01369 } 01370 01371 01372 template<typename T> inline 01373 Array<T>::operator ArrayView<T>() 01374 { 01375 return this->operator()(); 01376 } 01377 01378 01379 template<typename T> inline 01380 Array<T>::operator ArrayView<const T>() const 01381 { 01382 return this->operator()(); 01383 } 01384 01385 01386 // private 01387 01388 01389 template<typename T> 01390 std::vector<T>& 01391 Array<T>::vec( bool isStructureBeingModified, bool activeIter ) 01392 { 01393 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01394 (void)activeIter; 01395 if (isStructureBeingModified) { 01396 // Give up my ArrayRCPs used for iterator access since the array we be 01397 // getting modifed! Any clients that have views through weak pointers 01398 // better not touch them! 01399 extern_arcp_ = null; 01400 extern_carcp_ = null; 01401 } 01402 return *vec_; 01403 #else 01404 // get rid of "unused parameter" warnings 01405 (void)isStructureBeingModified; 01406 (void)activeIter; 01407 return vec_; 01408 #endif 01409 } 01410 01411 01412 template<typename T> inline 01413 const std::vector<T>& 01414 Array<T>::vec() const 01415 { 01416 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01417 return *vec_; 01418 #else 01419 return vec_; 01420 #endif 01421 } 01422 01423 01424 template<typename T> inline 01425 typename std::vector<T>::iterator 01426 Array<T>::raw_position( iterator position ) 01427 { 01428 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK 01429 const iterator first = this->begin(); 01430 const iterator last = this->end(); 01431 TEUCHOS_TEST_FOR_EXCEPTION( 01432 !(first <= position && position <= last), DanglingReferenceError, 01433 "Error, this iterator is no longer valid for this Aray!" 01434 ); 01435 // Note, above operator<=(...) functions will throw 01436 // IncompatibleIteratorsError if the iterators do not share the same 01437 // RCP_node object! 01438 return vec_->begin() + (position - this->begin()); 01439 #else 01440 return position; 01441 #endif 01442 } 01443 01444 01445 template<typename T> inline 01446 void Array<T>::assertIndex(int i) const 01447 { 01448 TEUCHOS_TEST_FOR_EXCEPTION( 01449 !( 0 <= i && i < length() ), RangeError, 01450 "Array<T>::assertIndex(i): i="<<i<<" out of range [0, "<< length() << ")" 01451 ); 01452 } 01453 01454 01455 template<typename T> inline 01456 void Array<T>::assertNotNull() const 01457 { 01458 TEUCHOS_TEST_FOR_EXCEPTION( 01459 !size(), NullReferenceError, 01460 typeName(*this)<<"::assertNotNull(): " 01461 "Error, the array has size zero!" 01462 ); 01463 } 01464 01465 01466 } // namespace Teuchos 01467 01468 01469 // Nonmember functions 01470 01471 01472 template<typename T> inline 01473 bool Teuchos::operator==( const Array<T> &a1, const Array<T> &a2 ) 01474 { return (a1.vec() == a2.vec()); } 01475 01476 01477 template<typename T> inline 01478 bool Teuchos::operator!=( const Array<T> &a1, const Array<T> &a2 ) 01479 { return (a1.vec() != a2.vec()); } 01480 01481 01482 template<typename T> inline 01483 void Teuchos::swap( Array<T> &a1, Array<T> &a2 ) 01484 { a1.swap(a2); } 01485 01486 01487 template<typename T> inline 01488 bool Teuchos::operator<( const Array<T> &a1, const Array<T> &a2 ) 01489 { return (a1.vec() < a2.vec()); } 01490 01491 01492 template<typename T> inline 01493 bool Teuchos::operator<=( const Array<T> &a1, const Array<T> &a2 ) 01494 { return (a1.vec() <= a2.vec()); } 01495 01496 01497 template<typename T> inline 01498 bool Teuchos::operator>( const Array<T> &a1, const Array<T> &a2 ) 01499 { return (a1.vec() > a2.vec()); } 01500 01501 01502 template<typename T> inline 01503 bool Teuchos::operator>=( const Array<T> &a1, const Array<T> &a2 ) 01504 { return (a1.vec() >= a2.vec()); } 01505 01506 01507 template<typename T> inline 01508 std::ostream& Teuchos::operator<<( 01509 std::ostream& os, const Array<T>& array 01510 ) 01511 { 01512 return os << Teuchos::toString(array); 01513 } 01514 01515 01516 template<typename T> inline 01517 int Teuchos::hashCode(const Array<T>& array) 01518 { 01519 int rtn = hashCode(array.length()); 01520 for (int i=0; i<array.length(); i++) 01521 { 01522 rtn += hashCode(array[i]); 01523 } 01524 return rtn; 01525 } 01526 01527 01528 template<typename T> inline 01529 std::vector<T> Teuchos::createVector( const Array<T> &a ) 01530 { 01531 return a.toVector(); 01532 } 01533 01534 01535 template<typename T> inline 01536 std::string Teuchos::toString(const Array<T>& array) 01537 { 01538 return array.toString(); 01539 } 01540 01541 01542 template<typename T> 01543 Teuchos::Array<T> 01544 Teuchos::fromStringToArray(const std::string& arrayStr) 01545 { 01546 const std::string str = Utils::trimWhiteSpace(arrayStr); 01547 std::istringstream iss(str); 01548 TEUCHOS_TEST_FOR_EXCEPTION( 01549 ( str[0]!='{' || str[str.length()-1] != '}' ) 01550 ,InvalidArrayStringRepresentation 01551 ,"Error, the std::string:\n" 01552 "----------\n" 01553 <<str<< 01554 "\n----------\n" 01555 "is not a valid array represntation!" 01556 ); 01557 char c; 01558 c = iss.get(); // Read initial '{' 01559 TEUCHOS_TEST_FOR_EXCEPT(c!='{'); // Should not throw! 01560 // Now we are ready to begin reading the entries of the array! 01561 Array<T> a; 01562 while( !iss.eof() ) { 01563 // Get the basic entry std::string 01564 std::string entryStr; 01565 std::getline(iss,entryStr,','); // Get next entry up to ,! 01566 // ToDo: Above, we might have to be careful to look for the opening and 01567 // closing of parentheses in order not to pick up an internal ',' in the 01568 // middle of an entry (for a std::complex number for instance). The above 01569 // implementation assumes that there will be no commas in the middle of 01570 // the std::string representation of an entry. This is certainly true for 01571 // the types bool, int, float, and double. 01572 // 01573 // Trim whitespace from beginning and end 01574 entryStr = Utils::trimWhiteSpace(entryStr); 01575 TEUCHOS_TEST_FOR_EXCEPTION( 01576 0 == entryStr.length(), 01577 InvalidArrayStringRepresentation, 01578 "Error, the std::string:\n" 01579 "----------\n" 01580 <<str<< 01581 "\n----------\n" 01582 "is not a valid array represntation because it has an empty array entry!" 01583 ); 01584 // Remove the final '}' if this is the last entry and we did not 01585 // actually terminate the above getline(...) on ',' 01586 bool found_end = false; 01587 if(entryStr[entryStr.length()-1]=='}') { 01588 entryStr = entryStr.substr(0,entryStr.length()-1); 01589 found_end = true; 01590 if( entryStr.length()==0 && a.size()==0 ) 01591 return a; // This is the empty array "{}" (with any spaces in it!) 01592 } 01593 // Finally we can convert the entry and add it to the array! 01594 std::istringstream entryiss(entryStr); 01595 T entry; 01596 Teuchos::extractDataFromISS( entryiss, entry ); 01597 // ToDo: We may need to define a traits class to allow us to specialized 01598 // how conversion from a std::string to a object is done! 01599 a.push_back(entry); 01600 // At the end of the loop body here, if we have reached the last '}' 01601 // then the input stream iss should be empty and iss.eof() should be 01602 // true, so the loop should terminate. We put an std::exception test here 01603 // just in case something has gone wrong. 01604 TEUCHOS_TEST_FOR_EXCEPTION( 01605 found_end && !iss.eof() 01606 ,InvalidArrayStringRepresentation 01607 ,"Error, the std::string:\n" 01608 "----------\n" 01609 <<str<< 01610 "\n----------\n" 01611 "is not a valid array represntation!" 01612 ); 01613 } 01614 return a; 01615 } 01616 01617 01618 #endif // TEUCHOS_ARRAY_H
1.7.6.1