Teuchos_Array.hpp

Go to the documentation of this file.
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 typename std::vector<T>::value_type value_type;
00205   typedef typename std::vector<T>::pointer pointer;
00207   typedef typename std::vector<T>::const_pointer const_pointer;
00209   typedef typename std::vector<T>::reference reference;
00211   typedef typename std::vector<T>::const_reference const_reference;
00212 
00214   typedef Teuchos_Index Ordinal;
00215 
00216 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00217 
00218   typedef ArrayRCP<T> iterator;
00220   typedef ArrayRCP<const T> const_iterator;
00222   typedef std::reverse_iterator<iterator> reverse_iterator;
00224   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00225 #else
00226 
00227   typedef typename std::vector<T>::iterator iterator;
00229   typedef typename std::vector<T>::const_iterator const_iterator;
00231   typedef typename std::vector<T>::reverse_iterator reverse_iterator;
00233   typedef typename std::vector<T>::const_reverse_iterator const_reverse_iterator;
00234 #endif
00235 
00237   typedef typename std::vector<T>::size_type size_type;
00239   typedef typename std::vector<T>::difference_type difference_type;
00241   typedef typename std::vector<T>::allocator_type allocator_type;
00242 
00244 
00247 
00248 
00250   Array();
00252   explicit Array(Ordinal n, const value_type& value = value_type());
00254   Array(const Array<T>& x);
00256   template<typename InputIterator>
00257   Array(InputIterator first, InputIterator last);
00259   Array(const ArrayView<const T>& a);
00261   template<int N>
00262   Array(const Tuple<T,N>& t);
00264   ~Array();
00266   Array& operator=(const Array<T>& a);
00267 
00269 
00272 
00274   void assign(Ordinal n, const value_type& val);
00276   template<typename InputIterator>
00277   void assign(InputIterator first, InputIterator last);
00279   iterator begin();
00281   iterator end();
00283   const_iterator begin() const;
00285   const_iterator end() const;
00287   reverse_iterator rbegin();
00289   reverse_iterator rend();
00291   const_reverse_iterator rbegin() const;
00293   const_reverse_iterator rend() const;
00295   size_type size() const;
00297   size_type max_size() const;
00299   void resize(Ordinal new_size, const value_type& x = value_type());
00301   size_type capacity() const;
00303   bool empty() const;
00305   void reserve(Ordinal n);
00307   reference operator[](Ordinal i);
00309   const_reference operator[](Ordinal i) const;
00311   reference at(Ordinal i);
00313   const_reference at(Ordinal i) const;
00315   reference front();
00317   const_reference front() const;
00319   reference back();
00321   const_reference back() const;
00323   void push_back(const value_type& x);
00325   void pop_back();
00327   iterator insert(iterator position, const value_type& x);
00329   void insert(iterator position, Ordinal n, const value_type& x);
00331   template<typename InputIterator>
00332   void insert(iterator position, InputIterator first, InputIterator last);
00334   iterator erase(iterator position);
00336   iterator erase(iterator first, iterator last);
00338   void swap(Array& x);
00340   void clear();
00341 
00343 
00346 
00351   Array<T>& append(const T& x);
00352 
00356   void remove(int i);
00357 
00362   inline int length() const;
00363 
00365   inline std::string toString() const;
00366 
00368   inline static bool hasBoundsChecking();
00369 
00371   inline T* getRawPtr();
00372 
00374   inline const T* getRawPtr() const;
00375 
00377 
00380 
00382   Array( const std::vector<T> &v );
00383 
00385   std::vector<T> toVector() const;
00386 
00388   Array& operator=( const std::vector<T> &v );
00389 
00391 
00393 
00394 
00406   ArrayView<T> view( Ordinal offset, Ordinal size );
00407 
00419   ArrayView<const T> view( Ordinal offset, Ordinal size ) const;
00420 
00424   ArrayView<T> operator()( Ordinal offset, Ordinal size );
00425 
00429   ArrayView<const T> operator()( Ordinal offset, Ordinal size ) const;
00430 
00435   ArrayView<T> operator()();
00436 
00441   ArrayView<const T> operator()() const;
00442 
00446   operator ArrayView<T>();
00447 
00451   operator ArrayView<const T>() const;
00452 
00454 
00455 private:
00456 
00457 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00458   RCP<std::vector<T> > vec_;
00459   mutable ArrayRCP<T> extern_arcp_;
00460   mutable ArrayRCP<const T> extern_carcp_;
00461 #else
00462   std::vector<T> vec_;
00463 #endif
00464 
00465   inline std::vector<T>& vec(
00466     bool isStructureBeingModified = false,
00467     bool activeIter = false
00468     );
00469 
00470   inline const std::vector<T>& vec() const;
00471 
00472   inline typename std::vector<T>::iterator
00473   raw_position( iterator position );
00474   
00475   inline void assertIndex(int i) const;
00476 
00477   inline void assertNotNull() const;
00478 
00479 };
00480 
00481 
00487 template<class T>
00488 ArrayRCP<T> arcp( const RCP<Array<T> > &v )
00489 {
00490   if ( is_null(v) || !v->size() )
00491     return null;
00492   return arcpWithEmbeddedObjPostDestroy<T,RCP<Array<T> > >(
00493     &(*v)[0], 0, v->size(),
00494     v, false
00495     );
00496 }
00497 
00498 
00504 template<class T>
00505 ArrayRCP<const T> arcp( const RCP<const Array<T> > &v )
00506 {
00507   if ( is_null(v) || !v->size() )
00508     return null;
00509   return arcpWithEmbeddedObjPostDestroy<const T,RCP<const Array<T> > >(
00510     &(*v)[0], 0, v->size(),
00511     v, false
00512     );
00513 }
00514 
00515 
00528 template<typename T>
00529 std::ostream& operator<<(std::ostream& os, const Array<T>& array);
00530 
00531 
00536 template<typename T> inline
00537 int hashCode(const Array<T>& array);
00538 
00539 
00546 template<typename T> inline
00547 std::vector<T> createVector( const Array<T> &a );
00548 
00549 
00554 template<typename T>
00555 std::string toString(const Array<T>& array);
00556 
00557 
00609 template<typename T>
00610 Array<T> fromStringToArray(const std::string& arrayStr);
00611 
00617 template<typename T> inline
00618 void extractDataFromISS( std::istringstream& iss, T& data )
00619 {
00620   iss >> data; // Assumes type has operator>>(...) defined!
00621 }
00622 
00629 inline
00630 void extractDataFromISS( std::istringstream& iss, std::string& data )
00631 {
00632   // grab unformatted string.
00633   data = iss.str();
00634   // remove white space from beginning and end of string.
00635   data = Utils::trimWhiteSpace(data);
00636 }
00637 
00638 } // namespace Teuchos
00639 
00640 
00641 //
00642 // Implementation
00643 //
00644 
00645 
00646 namespace Teuchos {
00647 
00648 
00649 // All constructors
00650 
00651 
00652 template<typename T> inline
00653 Array<T>::Array()
00654 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00655   : vec_(rcp(new std::vector<T>()))
00656 #endif
00657 {}
00658 
00659 
00660 template<typename T> inline
00661 Array<T>::Array(Ordinal n, const value_type& value) :
00662 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00663   vec_(rcp(new std::vector<T>(n,value)))
00664 #else
00665   vec_(n,value)
00666 #endif
00667 {}
00668 
00669 
00670 template<typename T> inline
00671 Array<T>::Array(const Array<T>& x) :
00672 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00673   vec_(rcp(new std::vector<T>(*x.vec_)))
00674 #else
00675   vec_(x.vec_)
00676 #endif
00677 {}
00678 
00679 
00680 template<typename T> template<typename InputIterator> inline
00681 Array<T>::Array(InputIterator first, InputIterator last) :
00682 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00683   vec_(rcp(new std::vector<T>(first,last)))
00684 #else
00685   vec_(first,last)
00686 #endif
00687 {}
00688 
00689 
00690 template<typename T> inline
00691 Array<T>::~Array()
00692 {
00693 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00694   const std::string errorMsg = 
00695     "Error, there must be some client with a dangling reference to this array "
00696     "object!  This could be a dangling iterator or a dangling view of something "
00697     "else.";
00698   TEST_FOR_EXCEPTION( extern_arcp_.count() > 1, DanglingReferenceError, errorMsg );
00699   extern_arcp_ = null;
00700   TEST_FOR_EXCEPTION( extern_carcp_.count() > 1, DanglingReferenceError, errorMsg );
00701   extern_carcp_ = null;
00702   TEST_FOR_EXCEPTION( vec_.count() > 1, DanglingReferenceError, errorMsg );
00703 #endif
00704 }
00705 
00706 
00707 template<typename T> inline
00708 Array<T>::Array(const ArrayView<const T>& a)
00709 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00710   : vec_(rcp(new std::vector<T>()))
00711 #endif
00712 {
00713   insert(begin(),a.begin(),a.end());
00714 }
00715 
00716 
00717 template<typename T>
00718 template<int N>
00719 inline
00720 Array<T>::Array(const Tuple<T,N>& t)
00721 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00722   : vec_(rcp(new std::vector<T>()))
00723 #endif
00724 {
00725   insert(begin(),t.begin(),t.end());
00726 }
00727 
00728 
00729 template<typename T> inline
00730 Array<T>& Array<T>::operator=(const Array& a)
00731 {
00732   vec(true) = a.vec();
00733   return *this;
00734 }
00735 
00736 
00737 // Other std::vector functions
00738 
00739 
00740 template<typename T> inline
00741 void Array<T>::assign(Ordinal n, const value_type& val)
00742 {
00743   vec(true).assign(n,val);
00744 }
00745 
00746 
00747 template<typename T> template<typename InputIterator> inline
00748 void Array<T>::assign(InputIterator first, InputIterator last)
00749 {
00750   vec(true).assign(first,last);
00751 }
00752 
00753 
00754 template<typename T> inline
00755 typename Array<T>::iterator
00756 Array<T>::begin()
00757 {
00758 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00759   if (is_null(extern_arcp_))
00760     extern_arcp_ = arcp(vec_);
00761   return extern_arcp_;
00762 #else
00763   return vec().begin();
00764 #endif
00765 }
00766 
00767 
00768 template<typename T> inline
00769 typename Array<T>::iterator
00770 Array<T>::end()
00771 {
00772 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00773   return begin() + size();
00774 #else
00775   return vec().end();
00776 #endif
00777 }
00778 
00779 
00780 template<typename T> inline
00781 typename Array<T>::const_iterator
00782 Array<T>::begin() const
00783 {
00784 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00785   if (is_null(extern_carcp_))
00786     extern_carcp_ = arcp(rcp_const_cast<const std::vector<T> >(vec_));
00787   return extern_carcp_;
00788 #else
00789   return vec().begin();
00790 #endif
00791 }
00792 
00793 
00794 template<typename T> inline
00795 typename Array<T>::const_iterator
00796 Array<T>::end() const
00797 {
00798 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00799   return begin() + size();
00800 #else
00801   return vec().end();
00802 #endif
00803 }
00804 
00805 
00806 template<typename T> inline
00807 typename Array<T>::reverse_iterator
00808 Array<T>::rbegin()
00809 {
00810 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00811   return reverse_iterator(end());
00812 #else
00813   return vec().rbegin();
00814 #endif
00815 }
00816 
00817 
00818 template<typename T> inline
00819 typename Array<T>::reverse_iterator
00820 Array<T>::rend()
00821 {
00822 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00823   return reverse_iterator(begin());
00824 #else
00825   return vec().rend();
00826 #endif
00827 }
00828 
00829 
00830 template<typename T> inline
00831 typename Array<T>::const_reverse_iterator
00832 Array<T>::rbegin() const
00833 {
00834 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00835   return const_reverse_iterator(end());
00836 #else
00837   return vec().rbegin();
00838 #endif
00839 }
00840 
00841 
00842 template<typename T> inline
00843 typename Array<T>::const_reverse_iterator
00844 Array<T>::rend() const
00845 {
00846 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00847   return const_reverse_iterator(begin());
00848 #else
00849   return vec().rend();
00850 #endif
00851 }
00852 
00853 
00854 template<typename T> inline
00855 typename Array<T>::size_type
00856 Array<T>::size() const
00857 {
00858   return vec().size();
00859 }
00860 
00861 
00862 template<typename T> inline
00863 typename Array<T>::size_type
00864 Array<T>::max_size() const
00865 {
00866   return vec().max_size();
00867 }
00868 
00869 
00870 template<typename T> inline
00871 void
00872 Array<T>::resize(Ordinal new_size, const value_type& x)
00873 {
00874   vec(true).resize(new_size,x);
00875 }
00876 
00877 
00878 template<typename T> inline
00879 typename Array<T>::size_type
00880 Array<T>::capacity() const
00881 {
00882   return vec().capacity();
00883 }
00884 
00885 
00886 template<typename T> inline
00887 bool Array<T>::empty() const
00888 {
00889   return vec().empty();
00890 }
00891 
00892 
00893 template<typename T> inline
00894 void Array<T>::reserve(Ordinal n)
00895 {
00896   vec(true).reserve(n);
00897 }
00898 
00899 
00900 template<typename T> inline
00901 typename Array<T>::reference
00902 Array<T>::operator[](Ordinal i)
00903 {
00904 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00905   assertIndex(i);
00906 #endif
00907   return vec()[i];
00908 }
00909 
00910 
00911 template<typename T> inline
00912 typename Array<T>::const_reference
00913 Array<T>::operator[](Ordinal i) const
00914 {
00915 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00916   assertIndex(i);
00917 #endif
00918   return vec()[i];
00919 }
00920 
00921 
00922 template<typename T> inline
00923 typename Array<T>::reference
00924 Array<T>::at(Ordinal i)
00925 {
00926 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00927   assertIndex(i);
00928 #endif
00929   return vec().at(i);
00930 }
00931 
00932 
00933 template<typename T> inline
00934 typename Array<T>::const_reference
00935 Array<T>::at(Ordinal i) const
00936 {
00937 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00938   assertIndex(i);
00939 #endif
00940   return vec().at(i);
00941 }
00942 
00943 
00944 template<typename T> inline
00945 typename Array<T>::reference
00946 Array<T>::front()
00947 {
00948 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00949   assertNotNull();
00950 #endif
00951   return vec().front();
00952 }
00953 
00954 
00955 template<typename T> inline
00956 typename Array<T>::const_reference
00957 Array<T>::front() const
00958 {
00959 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00960   assertNotNull();
00961 #endif
00962   return vec().front();
00963 }
00964 
00965 
00966 template<typename T> inline
00967 typename Array<T>::reference
00968 Array<T>::back()
00969 {
00970 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00971   assertNotNull();
00972 #endif
00973   return vec().back();
00974 }
00975 
00976 
00977 template<typename T> inline
00978 typename Array<T>::const_reference
00979 Array<T>::back() const
00980 {
00981 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00982   assertNotNull();
00983 #endif
00984   return vec().back();
00985 }
00986 
00987 
00988 template<typename T> inline
00989 void Array<T>::push_back(const value_type& x)
00990 {
00991   vec(true).push_back(x);
00992 }
00993 
00994 
00995 template<typename T> inline
00996 void Array<T>::pop_back()
00997 {
00998 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00999   assertNotNull();
01000 #endif
01001   vec(true).pop_back();
01002 }
01003 
01004 
01005 // 2007/11/20: rabartl: Note: In the below insertion and deletion functions,
01006 // you have to grab the raw iterator first before you call vec(true,true)
01007 // which will invalidate the iterator.  I had it that raw_position(...) was
01008 // called in the same statement at vec(true,true) and some compilers migh call
01009 // vec(true,true) before they call raw_position(...) which results in an
01010 // exception being thrown.
01011 
01012 
01013 template<typename T> inline
01014 typename Array<T>::iterator
01015 Array<T>::insert(iterator position, const value_type& x)
01016 {
01017 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01018   // Assert a valid iterator and get vector iterator
01019   const typename std::vector<T>::iterator raw_poss = raw_position(position);
01020   const difference_type i = position - begin();
01021   vec(true,true).insert(raw_poss,x);
01022   return begin() + i;
01023 #else
01024   return vec_.insert(position,x);
01025 #endif
01026 }
01027 
01028 
01029 template<typename T> inline
01030 void Array<T>::insert(iterator position, Ordinal n, const value_type& x)
01031 {
01032 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01033   const typename std::vector<T>::iterator raw_poss = raw_position(position);
01034   vec(true,true).insert(raw_poss,n,x);
01035 #else
01036   return vec_.insert(position,n,x);
01037 #endif
01038 }
01039 
01040 
01041 template<typename T> template<typename InputIterator> inline
01042 void Array<T>::insert(iterator position, InputIterator first, InputIterator last)
01043 {
01044 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01045   const typename std::vector<T>::iterator raw_poss = raw_position(position);
01046   vec(true,true).insert(raw_poss,first,last);
01047 #else
01048   return vec_.insert(position,first,last);
01049 #endif
01050 }
01051 
01052 
01053 template<typename T> inline
01054 typename Array<T>::iterator
01055 Array<T>::erase(iterator position)
01056 {
01057 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01058   assertNotNull();
01059   // Assert a valid iterator and get vector iterator
01060   const typename std::vector<T>::iterator raw_poss = raw_position(position);
01061   const difference_type i = position - begin();
01062   vec(true,true).erase(raw_poss);
01063   return begin() + i;
01064 #else
01065   return vec_.erase(position);
01066 #endif
01067 }
01068 
01069 
01070 template<typename T> inline
01071 typename Array<T>::iterator
01072 Array<T>::erase(iterator first, iterator last)
01073 {
01074 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01075   assertNotNull();
01076   // Assert a valid iterator and get vector iterator
01077   const typename std::vector<T>::iterator raw_first = raw_position(first);
01078   const typename std::vector<T>::iterator raw_last = raw_position(last);
01079   const difference_type i = first - begin();
01080   vec(true,true).erase(raw_first,raw_last);
01081   return begin() + i;
01082 #else
01083   return vec_.erase(first,last);
01084 #endif
01085 }
01086 
01087 
01088 template<typename T> inline
01089 void Array<T>::swap(Array& x)
01090 {
01091   vec(true).swap(x.vec());
01092 }
01093 
01094 
01095 template<typename T> inline
01096 void Array<T>::clear()
01097 {
01098   vec(true).clear();
01099 }
01100 
01101 
01102 // Non-standard functions
01103 
01104 
01105 template<typename T> inline
01106 Array<T>& Array<T>::append(const T& x)
01107 {
01108   this->push_back(x);
01109   return *this;
01110 }
01111 
01112 
01113 template<typename T> inline
01114 void Array<T>::remove(int i)
01115 {
01116 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01117   assertIndex(i);
01118 #endif
01119   // Erase the i-th element of this array.
01120   this->erase( this->begin() + i );
01121 }
01122 
01123 
01124 template<typename T> inline
01125 int Array<T>::length() const
01126 {
01127   return this->size();
01128 }
01129 
01130 
01131 template<typename T> inline
01132 std::string Array<T>::toString() const
01133 {
01134   return (*this)().toString();
01135 }
01136 
01137 
01138 template<typename T> inline
01139 bool Array<T>::hasBoundsChecking()
01140 {
01141 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK  
01142   return true;
01143 #else
01144   return false;
01145 #endif
01146 }
01147 
01148 
01149 template<typename T> inline
01150 T* Array<T>::getRawPtr()
01151 {
01152   return ( size() ? &(*this)[0] : 0 );
01153 }
01154 
01155 
01156 template<typename T> inline
01157 const T* Array<T>::getRawPtr() const
01158 {
01159   return ( size() ? &(*this)[0] : 0 );
01160 }
01161 
01162 
01163 // Conversions to and from std::vector
01164 
01165 
01166 template<typename T> inline
01167 Array<T>::Array( const std::vector<T> &v ) :
01168 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01169   vec_(new std::vector<T>(v))
01170 #else
01171   vec_(v)
01172 #endif
01173 {}
01174 
01175 
01176 template<typename T> inline
01177 std::vector<T> Array<T>::toVector() const
01178 {
01179   if (!size())
01180     return std::vector<T>();
01181   std::vector<T> v(begin(),end());
01182   return v;
01183 }
01184 
01185 
01186 template<typename T> inline
01187 Array<T>& Array<T>::operator=( const std::vector<T> &v )
01188 {
01189   vec(true) = v;
01190   return *this;
01191 }
01192 
01193 
01194 // Views
01195 
01196 
01197 template<typename T> inline
01198 ArrayView<T> Array<T>::view( Ordinal offset, Ordinal size_in )
01199 {
01200   if (size_in) {
01201 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01202     return ArrayView<T>(this->begin().persistingView(offset, size_in));
01203 #else
01204     return arrayView( &vec()[offset], size_in );
01205 #endif
01206   }
01207   return Teuchos::null;
01208 }
01209 
01210 
01211 template<typename T> inline
01212 ArrayView<const T> Array<T>::view( Ordinal offset, Ordinal size_in ) const
01213 {
01214   if (size_in) {
01215 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01216     return ArrayView<const T>(this->begin().persistingView(offset, size_in));
01217 #else
01218     return arrayView( &vec()[offset], size_in );
01219 #endif
01220   }
01221   return Teuchos::null;
01222   // NOTE: Above, we use a different implementation to call the const version
01223   // of begin() instead of the non-const version.  This sets up a different
01224   // ArrayRCP object that gets checked.
01225 }
01226 
01227 
01228 template<typename T> inline
01229 ArrayView<T> Array<T>::operator()( Ordinal offset, Ordinal size_in )
01230 {
01231   return view(offset, size_in);
01232 }
01233 
01234 
01235 template<typename T> inline
01236 ArrayView<const T> Array<T>::operator()( Ordinal offset, Ordinal size_in ) const
01237 {
01238   return view(offset, size_in);
01239 }
01240 
01241 
01242 template<typename T> inline
01243 ArrayView<T> Array<T>::operator()()
01244 {
01245   if (!size())
01246     return null;
01247   return this->view(0, size());
01248 }
01249 
01250 
01251 template<typename T> inline
01252 ArrayView<const T> Array<T>::operator()() const
01253 {
01254   if (!size())
01255     return null;
01256   return this->view(0, size());
01257 }
01258 
01259 
01260 template<typename T> inline
01261 Array<T>::operator ArrayView<T>()
01262 {
01263   return this->operator()();
01264 }
01265 
01266 
01267 template<typename T> inline
01268 Array<T>::operator ArrayView<const T>() const
01269 {
01270   return this->operator()();
01271 }
01272 
01273 
01274 // private
01275 
01276 
01277 template<typename T>
01278 std::vector<T>&
01279 Array<T>::vec( bool isStructureBeingModified, bool activeIter )
01280 {
01281 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01282   if (isStructureBeingModified) {
01283     // Give up my ArrayRCPs used for iterator access since the array we be
01284     // getting modifed!
01285     extern_arcp_ = null;
01286     extern_carcp_ = null;
01287     if (activeIter) {
01288       // If there is an active iterator in this call, then we need to allow
01289       // for the existance of one or more other iterators!  We can't know for
01290       // sure how many other iterators there will be since some copy
01291       // constructors etc., might be called!  This leaves a dangerous
01292       // situration in place where the client might access the iterator after
01293       // this call!
01294       
01295       // 2007/11/08: rabartl: ToDo: I need to add a bool field to RCPNode that
01296       // stores if the underlying object is valid or not.  I can then put in a
01297       // debug-enabled check that any use of that object will be invalid and
01298       // throw!  The WEAK RCP pointer approach might be able to handle this!
01299     }
01300     else {
01301       // If there is no active iterator, then we don't allow any other
01302       // dangling references or we will thrown an exception!
01303       TEST_FOR_EXCEPTION( vec_.count() > 1, DanglingReferenceError,
01304         "Error, Array is being modified while a dangling reference exists!");
01305     }
01306   }
01307   return *vec_;
01308 #else
01309   // get rid of "unused parameter" warnings
01310   (void)isStructureBeingModified;
01311   (void)activeIter;
01312   return vec_;
01313 #endif
01314 }
01315 
01316 
01317 template<typename T> inline
01318 const std::vector<T>&
01319 Array<T>::vec() const
01320 {
01321 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01322   return *vec_;
01323 #else
01324   return vec_;
01325 #endif
01326 }
01327 
01328 
01329 template<typename T> inline
01330 typename std::vector<T>::iterator
01331 Array<T>::raw_position( iterator position )
01332 {
01333 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01334   const iterator first = this->begin();
01335   const iterator last = this->end();
01336   TEST_FOR_EXCEPTION(
01337     !(first <= position && position <= last), DanglingReferenceError,
01338     "Error, this iterator is no longer valid for this Aray!"
01339     );
01340   // Note, above operator<=(...) functions will throw
01341   // IncompatibleIteratorsError if the iterators do not share the same
01342   // RCP_node object!
01343   return vec_->begin() + (position - this->begin());
01344 #else
01345   return position;
01346 #endif
01347 }
01348 
01349 
01350 template<typename T> inline
01351 void Array<T>::assertIndex(int i) const
01352 {
01353   TEST_FOR_EXCEPTION(
01354     !( 0 <= i && i < length() ), RangeError,
01355     typeName(*this)<<"::assertIndex(i): "
01356     "index " << i << " out of range [0, "<< length() << ")"
01357     );
01358 }
01359 
01360 
01361 template<typename T> inline
01362 void Array<T>::assertNotNull() const
01363 {
01364   TEST_FOR_EXCEPTION(
01365     !size(), NullReferenceError,
01366     typeName(*this)<<"::assertNotNull(): "
01367     "Error, the array has size zero!"
01368     );
01369 }
01370 
01371 
01372 } // namespace Teuchos
01373 
01374 
01375 // Nonmember functions
01376 
01377 
01378 template<typename T> inline
01379 bool Teuchos::operator==( const Array<T> &a1, const Array<T> &a2 )
01380 { return (a1.vec() == a2.vec()); }
01381 
01382 
01383 template<typename T> inline
01384 bool Teuchos::operator!=( const Array<T> &a1, const Array<T> &a2 )
01385 { return (a1.vec() != a2.vec()); }
01386 
01387 
01388 template<typename T> inline
01389 void Teuchos::swap( Array<T> &a1, Array<T> &a2 )
01390 { a1.swap(a2); }
01391 
01392 
01393 template<typename T> inline
01394 bool Teuchos::operator<( const Array<T> &a1, const Array<T> &a2 )
01395 { return (a1.vec() < a2.vec()); }
01396 
01397 
01398 template<typename T> inline
01399 bool Teuchos::operator<=( const Array<T> &a1, const Array<T> &a2 )
01400 { return (a1.vec() <= a2.vec()); }
01401 
01402 
01403 template<typename T> inline
01404 bool Teuchos::operator>( const Array<T> &a1, const Array<T> &a2 )
01405 { return (a1.vec() > a2.vec()); }
01406 
01407 
01408 template<typename T> inline
01409 bool Teuchos::operator>=( const Array<T> &a1, const Array<T> &a2 )
01410 { return (a1.vec() >= a2.vec()); }
01411 
01412 
01413 template<typename T> inline
01414 std::ostream& Teuchos::operator<<(
01415   std::ostream& os, const Array<T>& array
01416   )
01417 {
01418   return os << Teuchos::toString(array);
01419 }
01420 
01421 
01422 template<typename T> inline
01423 int Teuchos::hashCode(const Array<T>& array)
01424 {
01425   int rtn = hashCode(array.length());
01426   for (int i=0; i<array.length(); i++)
01427   {
01428     rtn += hashCode(array[i]);
01429   }
01430   return rtn;
01431 }
01432 
01433 
01434 template<typename T> inline
01435 std::vector<T> Teuchos::createVector( const Array<T> &a )
01436 {
01437   return a.toVector();
01438 }
01439 
01440 
01441 template<typename T> inline
01442 std::string Teuchos::toString(const Array<T>& array)
01443 {
01444   return array.toString();
01445 }
01446 
01447 
01448 template<typename T>
01449 Teuchos::Array<T>
01450 Teuchos::fromStringToArray(const std::string& arrayStr)
01451 {
01452   const std::string str = Utils::trimWhiteSpace(arrayStr);
01453   std::istringstream iss(str);
01454   TEST_FOR_EXCEPTION(
01455     ( str[0]!='{' || str[str.length()-1] != '}' )
01456     ,InvalidArrayStringRepresentation
01457     ,"Error, the std::string:\n"
01458     "----------\n"
01459     <<str<<
01460     "\n----------\n"
01461     "is not a valid array represntation!"
01462     );
01463   char c;
01464   c = iss.get(); // Read initial '{'
01465   TEST_FOR_EXCEPT(c!='{'); // Should not throw!
01466   // Now we are ready to begin reading the entries of the array!
01467   Array<T> a;
01468   while( !iss.eof() ) {
01469     // Get the basic entry std::string
01470     std::string entryStr;
01471     std::getline(iss,entryStr,','); // Get next entry up to ,!
01472     // ToDo: Above, we might have to be careful to look for the opening and
01473     // closing of parentheses in order not to pick up an internal ',' in the
01474     // middle of an entry (for a std::complex number for instance).  The above
01475     // implementation assumes that there will be no commas in the middle of
01476     // the std::string representation of an entry.  This is certainly true for
01477     // the types bool, int, float, and double.
01478     //
01479     // Trim whitespace from beginning and end
01480     entryStr = Utils::trimWhiteSpace(entryStr);
01481     // Remove the final '}' if this is the last entry and we did not
01482     // actually terminate the above getline(...) on ','
01483     bool found_end = false;
01484     if(entryStr[entryStr.length()-1]=='}') {
01485       entryStr = entryStr.substr(0,entryStr.length()-1);
01486       found_end = true;
01487       if( entryStr.length()==0 && a.size()==0 )
01488         return a; // This is the empty array "{}" (with any spaces in it!)
01489     }
01490     TEST_FOR_EXCEPTION(
01491       0 == entryStr.length()
01492       ,InvalidArrayStringRepresentation
01493       ,"Error, the std::string:\n"
01494       "----------\n"
01495       <<str<<
01496       "\n----------\n"
01497       "is not a valid array represntation!"
01498       );
01499     // Finally we can convert the entry and add it to the array!
01500     std::istringstream entryiss(entryStr);
01501     T entry;
01502     Teuchos::extractDataFromISS( entryiss, entry );
01503     // ToDo: We may need to define a traits class to allow us to specialized
01504     // how conversion from a std::string to a object is done!
01505     a.push_back(entry);
01506     // At the end of the loop body here, if we have reached the last '}'
01507     // then the input stream iss should be empty and iss.eof() should be
01508     // true, so the loop should terminate.  We put an std::exception test here
01509     // just in case something has gone wrong.
01510     TEST_FOR_EXCEPTION(
01511       found_end && !iss.eof()
01512       ,InvalidArrayStringRepresentation
01513       ,"Error, the std::string:\n"
01514       "----------\n"
01515       <<str<<
01516       "\n----------\n"
01517       "is not a valid array represntation!"
01518       );
01519   }
01520   return a;
01521 }
01522 
01523 
01524 #endif // TEUCHOS_ARRAY_H

Generated on Wed May 12 21:24:40 2010 for Teuchos - Trilinos Tools Package by  doxygen 1.4.7