1 // @HEADER
2 // ***********************************************************************
3 //
4 //                    Teuchos: Common Tools Package
5 //                 Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #ifndef TEUCHOS_ARRAY_H
43 #define TEUCHOS_ARRAY_H
44 
45 /*! \file Teuchos_Array.hpp
46   \brief Templated array class derived from the STL std::vector
47 */
48 
49 #include "Teuchos_ConfigDefs.hpp"
50 #include "Teuchos_Assert.hpp"
51 #include "Teuchos_TypeNameTraits.hpp"
52 #include "Teuchos_ArrayRCP.hpp"
53 #include "Teuchos_Tuple.hpp"
54 #include "Teuchos_Utils.hpp"
55 #include "Teuchos_Assert.hpp"
56 
57 #if defined(HAVE_TEUCHOSCORE_CXX11) && defined(HAVE_TEUCHOS_ARRAY_BOUNDSCHECK) && defined(HAVE_TEUCHOS_THREAD_SAFE) && !defined(REMOVE_THREAD_PROTECTION_FOR_ARRAY)
58 #include <mutex>
59 #define USE_MUTEX_LOCK_FOR_ARRAY
60 #endif
61 
62 namespace Teuchos {
63 
64 /** \brief .
65  *
66  * \ingroup teuchos_mem_mng_grp
67  */
68 class InvalidArrayStringRepresentation : public std::logic_error
InvalidArrayStringRepresentation(const std::string & what_arg)69 {public:InvalidArrayStringRepresentation(const std::string& what_arg) : std::logic_error(what_arg) {}};
70 
71 
72 template<typename T> class Array;
73 
74 
75 // 2007/11/30: rabartl: Below, I had to move the initial declaration of these
76 // non-member template functions outside of the Array class since the Sun
77 // compiler on sass9000 would not accept this.  However, this did work on a
78 // number of other compilers such a g++, Intel C++ etc.  The old in-class
79 // non-member friend definition is clearly ISO 98 C++ as shown in Item 46 of
80 // "Effective C++: Third Edition".  This is not the end of the world but this
81 // is something to remember for this platform.
82 
83 
84 /** \brief Equality operator.
85  *
86  * \relates Array
87  */
88 template<typename T> inline
89 bool operator==( const Array<T> &a1, const Array<T> &a2 );
90 
91 
92 /** \brief Non-equality operator.
93  *
94  * \relates Array
95  */
96 template<typename T> inline
97 bool operator!=( const Array<T> &a1, const Array<T> &a2 );
98 
99 
100 /** \brief Non-member swap (specializes default std version).
101  *
102  * \relates Array
103  */
104 template<typename T> inline
105 void swap( Array<T> &a1, Array<T> &a2 );
106 
107 
108 /** \brief Less-than operator.
109  *
110  * \relates Array
111  */
112 template<typename T> inline
113 bool operator<( const Array<T> &a1, const Array<T> &a2 );
114 
115 
116 /** \brief Less-than-or-equal operator.
117  *
118  * \relates Array
119  */
120 template<typename T> inline
121 bool operator<=( const Array<T> &a1, const Array<T> &a2 );
122 
123 
124 /** \brief Greater-than operator.
125  *
126  * \relates Array
127  */
128 template<typename T> inline
129 bool operator>( const Array<T> &a1, const Array<T> &a2 );
130 
131 
132 /** \brief Greater-than-or-equal operator.
133  *
134  * \relates Array
135  */
136 template<typename T> inline
137 bool operator>=( const Array<T> &a1, const Array<T> &a2 );
138 
139 
140 /** \brief Replacement for std::vector that is compatible with
141  *     the Teuchos Memory Management classes.
142  * \tparam T The type of each entry in the array.
143  * \ingroup teuchos_mem_mng_grp
144  *
145  * This class implements a one-dimensional array, with a number of
146  * entries specified at run time.  It can be used as a drop-in
147  * replacement for the C++98 version of std::vector<T>.  It also has
148  * functions and methods for interacting with the other Teuchos Memory
149  * Management classes.  For example, you can get a nonpersisting view
150  * of an Array's entries as an ArrayView, or a nonowning (weak)
151  * ArrayRCP.
152  *
153  * If the CMake configuration option Teuchos_ENABLE_DEBUG is ON at
154  * build time, Array will do bounds and iterator checking at run time.
155  * This has a nontrivial run-time cost, so it is off by default, but
156  * you may find it useful for debugging.  Please note that if
157  * debugging is on, the types of Array's iterators change in order to
158  * implement these checks.  Thus, you should always use Array's
159  * typedefs to get the iterator types, and not assume that they are
160  * raw pointers.
161  *
162  * \section Teuchos_Array_Tuple_sec Tuple Construction
163  *
164  * A user can create a Teuchos::Tuple object to initialize an Array object by
165  * using one of the the convenient overloaded Teuchos::tuple() non-member
166  * constructor functions.  For example, see Array_test.cpp for how this is
167  * done.
168  *
169  * \section Teuchos_Array_DesignDiscussion_sec Design Discussion
170  *
171  * Currently, this class defines implicit conversions to ArrayView.  An
172  * alternative design would be to have Array derive from ArrayView.  This is a
173  * workable design but it would impart some extra storage and runtime
174  * overhead.  Perhaps the most significant overhead would be having the reset
175  * the base ArrayView pointer and size on each and every change in the
176  * structure of the container.  This would import extra overhead beyond a
177  * straight std::vector.
178  *
179  * The big advantage of deriving Array from ArrayView is that this would allow
180  * Array to be used to call some functions taking ArrayView without requiring
181  * an implicit conversion.  While the implicit shallow conversion from Array
182  * to ArrayView is very cheap (just a pointer and int copy), it does cause
183  * problems where the compiler will refuse to perform an implicit conversion
184  * to call a templated function.  However, note that an implicit conversion to
185  * an ArrayView<const T> would always have to be performed no matter what.
186  *
187  * In summary, having Array implicitly convert to ArrayView instead of having
188  * Array derive from ArrayView results in faster and simpler code at the
189  * expense of the compiler refusing the make implicit conversions in some
190  * cases when calling template functions.  Such conversion problems can always
191  * be dealt with by using explicit template arguments.
192  */
193 template<typename T>
194 class Array
195 {
196 public:
197 
198   // 2007/11/30: rabartl: Below, note that the only reason that these
199   // functions are declared as friends is so that the compiler will do
200   // automatic type conversions as described in "Effective C++: Third Edition"
201   // Item 46.
202 
203   /** \brief . */
204   template<typename T2>
205   friend bool Teuchos::operator==( const Array<T2> &a1, const Array<T2> &a2 );
206 
207   /** \brief . */
208   template<typename T2>
209   friend bool Teuchos::operator!=( const Array<T2> &a1, const Array<T2> &a2 );
210 
211   /** \brief . */
212   template<typename T2>
213   friend void swap( Array<T2> &a1, Array<T2> &a2 );
214 
215   /** \brief . */
216   template<typename T2>
217   friend bool Teuchos::operator<( const Array<T2> &a1, const Array<T2> &a2 );
218 
219   /** \brief . */
220   template<typename T2>
221   friend bool Teuchos::operator<=( const Array<T2> &a1, const Array<T2> &a2 );
222 
223   /** \brief . */
224   template<typename T2>
225   friend bool Teuchos::operator>( const Array<T2> &a1, const Array<T2> &a2 );
226 
227   /** \brief . */
228   template<typename T2>
229   friend bool Teuchos::operator>=( const Array<T2> &a1, const Array<T2> &a2 );
230 
231   /** \name std::vector typedefs */
232   //@{
233 
234   //! The type of indices.
235   typedef Teuchos_Ordinal Ordinal;
236   //! The type of Array sizes and capacities.
237   typedef Ordinal size_type;
238   //! The type of the difference between two size_type values.
239   typedef Ordinal difference_type;
240   //! The type of an entry of the Array; for compatibility with std::vector.
241   typedef typename std::vector<T>::value_type value_type;
242   //! The type of a pointer to T; for compatibility with std::vector.
243   typedef typename std::vector<T>::pointer pointer;
244   //! The type of a const pointer to T; for compatibility with std::vector.
245   typedef typename std::vector<T>::const_pointer const_pointer;
246   //! The type of a reference to T; for compatibility with std::vector.
247   typedef typename std::vector<T>::reference reference;
248   //! The type of a const reference to T; for compatibility with std::vector.
249   typedef typename std::vector<T>::const_reference const_reference;
250   //! The allocator type; for compatibility with std::vector.
251   typedef typename std::vector<T>::allocator_type allocator_type;
252 
253 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
254   //! The type of a forward iterator.
255   typedef ArrayRCP<T> iterator;
256   //! The type of a const forward iterator.
257   typedef ArrayRCP<const T> const_iterator;
258   //! The type of a reverse iterator.
259   typedef std::reverse_iterator<iterator> reverse_iterator;
260   //! The type of a const reverse iterator.
261   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
262 #else
263   //! The type of a forward iterator.
264   typedef typename std::vector<T>::iterator iterator;
265   //! The type of a const forward iterator.
266   typedef typename std::vector<T>::const_iterator const_iterator;
267   //! The type of a reverse iterator.
268   typedef typename std::vector<T>::reverse_iterator reverse_iterator;
269   //! The type of a const reverse iterator.
270   typedef typename std::vector<T>::const_reverse_iterator const_reverse_iterator;
271 #endif
272 
273   //@}
274   /** \name All constructors */
275   //@{
276 
277   //! Default constructor; creates an empty Array.
278   inline Array();
279 
280   //! Create an array of length n, and fill it with the given value.
281   inline explicit Array(size_type n, const value_type& value = value_type());
282 
283   //! Copy constructor (does a deep copy).
284   inline Array(const Array<T>& x);
285 
286   //! Create an array, and fill it with values from the given iterator range.
287   template<typename InputIterator>
288   inline Array(InputIterator first, InputIterator last);
289 
290   //! Create an Array which is a deep copy of the given ArrayView.
291   inline Array(const ArrayView<const T>& a);
292 
293   //! Copy constructor from the given Tuple.
294   template<int N>
295   inline Array(const Tuple<T,N>& t);
296 
297   //! Destructor.
298   inline ~Array();
299 
300   //! Assignment operator (does a deep copy).
301   inline Array& operator=(const Array<T>& a);
302 
303   //@}
304   /// \name Other std::vector functions
305   ///
306   /// Array has mostly the same interface as std::vector.  This allows
307   /// use of Array in place of std::vector, for gradual porting to use
308   /// the Teuchos Memory Management classes.
309   //@{
310 
311   /** \brief . */
312   inline void assign(size_type n, const value_type& val);
313   /** \brief . */
314   template<typename InputIterator>
315   inline void assign(InputIterator first, InputIterator last);
316   /** \brief . */
317   inline iterator begin();
318   /** \brief . */
319   inline iterator end();
320   /** \brief . */
321   inline const_iterator begin() const;
322   /** \brief . */
323   inline const_iterator end() const;
324   /** \brief . */
325   inline reverse_iterator rbegin();
326   /** \brief . */
327   inline reverse_iterator rend();
328   /** \brief . */
329   inline const_reverse_iterator rbegin() const;
330   /** \brief . */
331   inline const_reverse_iterator rend() const;
332   /** \brief . */
333   inline size_type size() const;
334   /** \brief . */
335   inline size_type max_size() const;
336   /** \brief . */
337   inline void resize(size_type new_size, const value_type& x = value_type());
338   /** \brief . */
339   inline size_type capacity() const;
340   /** \brief . */
341   inline bool empty() const;
342   /** \brief . */
343   inline void reserve(size_type n);
344   /** \brief . */
345   inline reference operator[](size_type i);
346   /** \brief . */
347   inline const_reference operator[](size_type i) const;
348   /** \brief . */
349   inline reference at(size_type i);
350   /** \brief . */
351   inline const_reference at(size_type i) const;
352   /** \brief . */
353   inline reference front();
354   /** \brief . */
355   inline const_reference front() const;
356   /** \brief . */
357   inline reference back();
358   /** \brief . */
359   inline const_reference back() const;
360   /** \brief . */
361   inline void push_back(const value_type& x);
362   /** \brief . */
363   inline void pop_back();
364   /** \brief . */
365   inline iterator insert(iterator position, const value_type& x);
366   /** \brief . */
367   inline void insert(iterator position, size_type n, const value_type& x);
368   /** \brief . */
369   template<typename InputIterator>
370   inline void insert(iterator position, InputIterator first, InputIterator last);
371   /** \brief . */
372   inline iterator erase(iterator position);
373   /** \brief . */
374   inline iterator erase(iterator first, iterator last);
375   /** \brief . */
376   inline void swap(Array& x);
377   /** \brief . */
378   inline void clear();
379 
380   //@}
381   /** \name General non-standard functions. */
382   //@{
383 
384   /** \brief Add a new entry at the end of the array.
385    *
386    * Resize to allow space for the new entry.
387    */
388   inline Array<T>& append(const T& x);
389 
390   /** \brief Remove the i-th element from the array, with optional
391    * boundschecking.
392    */
393   inline void remove(int i);
394 
395   /** \brief Return number of elements in the array.
396    *
397    * Equivalent to size(), but * included for backwards compatibility.
398    */
399   inline int length() const;
400 
401   /** \brief Convert an Array to an <tt>std::string</tt> */
402   inline std::string toString() const;
403 
404   /** \brief Return true if Array has been compiled with boundschecking on. */
405   inline static bool hasBoundsChecking();
406 
407   /** \brief Return a raw pointer to beginning of array or NULL if unsized. */
408   inline T* getRawPtr();
409 
410   /// \brief Return a raw pointer to beginning of array.
411   ///
412   /// Same semantics as \c getRawPtr (which see).
413   inline T* data();
414 
415   /** \brief Return a const raw pointer to beginning of array or NULL if unsized. */
416   inline const T* getRawPtr() const;
417 
418   /// \brief Return a const raw pointer to beginning of array.
419   ///
420   /// Same semantics as \c getRawPtr (which see).
421   inline const T* data() const;
422 
423   //@}
424   /** \name Conversions to and from std::vector. */
425   //@{
426 
427   //! Copy constructor from an std::vector (does a deep copy).
428   inline Array( const std::vector<T> &v );
429 
430   /** \brief Explicit copy conversion to an std::vector. */
431   inline std::vector<T> toVector() const;
432 
433   /** \brief Assignment operator for std::vector. */
434   inline Array& operator=( const std::vector<T> &v );
435 
436   //@}
437 
438   //! @name Views
439   //@{
440 
441         /** \brief Return non-const view of a contiguous range of elements.
442          *
443          * <b>Preconditions:</b><ul>
444    * <li><tt>0 <= offset && offset + size <= this->size()</tt>
445          * </ul>
446          *
447          * <b>Postconditions:</b><ul>
448    * <li><tt>returnVal.size() == size</tt>
449          * </ul>
450    *
451    * NOTE: A <tt>size==0</tt> view of even an empty Array is allowed and
452    * returns a <tt>null</tt> view.
453    */
454         inline ArrayView<T> view( size_type offset, size_type size );
455 
456         /** \brief Return const view of a contiguous range of elements.
457          *
458          * <b>Preconditions:</b><ul>
459    * <li><tt>0 <= offset && offset + size <= this->size()</tt>
460          * </ul>
461          *
462          * <b>Postconditions:</b><ul>
463    * <li><tt>returnVal.size() == size</tt>
464          * </ul>
465    *
466    * NOTE: A <tt>size==0</tt> view of even an empty Array is allowed and
467    * returns a <tt>null</tt> view.
468    */
469         inline ArrayView<const T> view( size_type offset, size_type size ) const;
470 
471         /** \brief Return a non-const view of a contiguous range of elements (calls
472    * view(offset,size)).
473    */
474         inline ArrayView<T> operator()( size_type offset, size_type size );
475 
476         /** \brief Return a const view of a contiguous range of elements (calls
477    * view(offset,size)).
478    */
479         inline ArrayView<const T> operator()( size_type offset, size_type size ) const;
480 
481         /** \brief Return an non-const ArrayView of *this.
482    *
483    * NOTE: This will return a null ArrayView if this->size() == 0.
484    */
485         inline ArrayView<T> operator()();
486 
487         /** \brief Return an const ArrayView of *this.
488    *
489    * NOTE: This will return a null ArrayView if this->size() == 0.
490    */
491         inline ArrayView<const T> operator()() const;
492 
493   /** \brief Perform an implicit conversion to a non-const ArrayView (calls
494    * operator()()).
495    */
496         inline operator ArrayView<T>();
497 
498   /** \brief Perform an implicit conversion to a non-const ArrayView (calls
499    * operator()()).
500    */
501         inline operator ArrayView<const T>() const;
502 
503   //@}
504 
505 private:
506 
507 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
508   RCP<std::vector<T> > vec_;
509   mutable ArrayRCP<T> extern_arcp_;
510   mutable ArrayRCP<const T> extern_carcp_;
511 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
512   mutable std::mutex mutex_lock; // this mutex provides thread safe debugging for the vec_, extern_arcp_, extern_carcp_
513 #endif
514 #else
515   std::vector<T> vec_;
516 #endif
517 
518   inline std::vector<T>& vec(
519     bool isStructureBeingModified = false,
520     bool activeIter = false
521     );
522 
523   inline const std::vector<T>& vec() const;
524 
525   inline typename std::vector<T>::iterator
526   raw_position( iterator position );
527 
528   inline void assertIndex(size_type i) const;
529 
530   inline void assertNotNull() const;
531 
532 };
533 
534 
535 /** \brief Wrap an <tt>RCP<Array<T> ></tt> object as an <tt>ArrayRCP<T></tt>
536  * object.
537  *
538  * \relates ArrayRCP
539  */
540 template<class T>
arcp(const RCP<Array<T>> & v)541 ArrayRCP<T> arcp( const RCP<Array<T> > &v )
542 {
543   if ( is_null(v) || !v->size() )
544     return null;
545   return arcpWithEmbeddedObjPostDestroy<T,RCP<Array<T> > >(
546     &(*v)[0], 0, v->size(),
547     v, false
548     );
549 }
550 
551 
552 /** \brief Wrap a <tt>RCP<const Array<T> ></tt> object as an
553  * <tt>ArrayRCP<const T></tt> object.
554  *
555  * \relates ArrayRCP
556  */
557 template<class T>
arcp(const RCP<const Array<T>> & v)558 ArrayRCP<const T> arcp( const RCP<const Array<T> > &v )
559 {
560   if ( is_null(v) || !v->size() )
561     return null;
562   return arcpWithEmbeddedObjPostDestroy<const T,RCP<const Array<T> > >(
563     &(*v)[0], 0, v->size(),
564     v, false
565     );
566 }
567 
568 
569 /** \brief Wrap an <tt>Array<T></tt> object as a non-owning
570  * <tt>ArrayRCP<T></tt> object.
571  *
572  * \relates ArrayRCP
573  */
574 template<class T>
arcpFromArray(Array<T> & a)575 ArrayRCP<T> arcpFromArray( Array<T> &a )
576 {
577   if (a.size() == 0)
578     return null;
579 #ifdef TEUCHOS_DEBUG
580   return a.begin(); // Catch dangling reference!
581 #else
582   return arcp(a.getRawPtr(), 0, a.size(), false);
583 #endif
584 }
585 
586 
587 /** \brief Wrap a <tt>const Array<T></tt> object as a non-owning
588  * <tt>ArrayRCP<T></tt> object.
589  *
590  * \relates ArrayRCP
591  */
592 template<class T>
arcpFromArray(const Array<T> & a)593 ArrayRCP<const T> arcpFromArray( const Array<T> &a )
594 {
595   if (a.size() == 0)
596     return null;
597 #ifdef TEUCHOS_DEBUG
598   return a.begin(); // Catch dangling reference!
599 #else
600   return arcp(a.getRawPtr(), 0, a.size(), false);
601 #endif
602 }
603 
604 
605 /** \brief Write an Array to an ostream.
606  *
607  * This prints arrays in the form:
608 
609  \verbatim
610 
611  { 1.0, 2.0, 3.0 }
612 
613  \endverbatim
614 
615  * \relates Array
616  */
617 template<typename T>
618 std::ostream& operator<<(std::ostream& os, const Array<T>& array);
619 
620 
621 /** \brief Return the hash code.
622  *
623  * \relates Array.
624  */
625 template<typename T> inline
626 int hashCode(const Array<T>& array);
627 
628 
629 /** \brief Copy conversion to an std::vector.
630  *
631  * This function is included for consistency with ArrayView.
632  *
633  * \relates Array.
634  */
635 template<typename T> inline
636 std::vector<T> createVector( const Array<T> &a );
637 
638 
639 /** \brief Convert an array to a string representation.
640  *
641  * \relates Array
642  */
643 template<typename T>
644 std::string toString(const Array<T>& array);
645 
646 
647 /** \brief Converts from std::string representation (as created by
648  * <tt>toString()</tt>) back into the array object.
649  *
650  * \param arrayStr [in] The std::string representation of the array (see
651  * below).
652  *
653  * <b>Exceptions:</b> If the std::string representation is not valid, then an
654  * std::exception of type <tt>InvalidArrayStringRepresentation</tt> with be
655  * thrown with a decent error message attached.
656  *
657  * The formating of the std::string <tt>arrayStr</tt> must look like:
658 
659  \verbatim
660 
661  {  val[0], val[1], val[2], val[3], ..., val[n-1] }
662 
663  \endverbatim
664 
665  * Currently <tt>operator>>()</tt> is used to convert the entries from their
666  * std::string representation to objects of type <tt>T</tt>.  White space is
667  * unimportant and the parser keys off of ',', '{' and '}' so even newlines
668  * are allowed.  In the future, a traits class might be defined that will
669  * allow for finer-grained control of how the conversion from strings to
670  * values is performed in cases where <tt>operator>>()</tt> does not exist
671  * for certain types.
672  *
673  * <b>Warning!</b> Currently this function only supports reading in flat
674  * array objects for basic types like <tt>bool</tt>, <tt>int</tt>, and
675  * <tt>double</tt> and does not yet support nested arrays (i.e. no
676  * <tt>Array<Array<int> ></tt>) or other such fancy nested types.  Support
677  * for nested arrays and other user defined types <tt>T</tt> can be added in
678  * the future with no impact on user code.  Only the parser for the array
679  * needs to be improved.  More specifically, the current implementation will
680  * not work for any types <tt>T</tt> who's std::string representation contains
681  * the characters <tt>','</tt> or <tt>'}'</tt>.  This implementation can be
682  * modified to allow any such types by watching for the nesting of common
683  * enclosing structures like <tt>[...]</tt>, <tt>{...}</tt> or
684  * <tt>(...)</tt> within each entry of the std::string representation.  However,
685  * this should all just work fine on most machines for the types
686  * <tt>int</tt>, <tt>bool</tt>, <tt>float</tt>, <tt>double</tt> etc.
687  *
688  * <b>Warning!</b> Trying to read in an array in std::string format of doubles in
689  * scientific notation such as <tt>{1e+2,3.53+6,...}</tt> into an array
690  * object such as <tt>Array<int></tt> will not yield the correct results.
691  * If one wants to allow a neutral std::string representation to be read in as an
692  * <tt>Array<double></tt> object or an <tt>Array<int></tt> object, then
693  * general formating such as <tt>{100,3530000,...}</tt> should be used.
694  * This templated function is unable to deal std::complex type conversion issues.
695  *
696  * \relates Array.
697  */
698 template<typename T>
699 Array<T> fromStringToArray(const std::string& arrayStr);
700 
701 /** \brief A wrapper around the \c fromStringToArray function
702  * which allows the operator>> to be used on Arrays.
703  *
704  * \relates Array
705  */
706 template<typename T>
operator >>(std::istringstream & in,Array<T> & array)707 std::istringstream& operator>> (std::istringstream& in, Array<T>& array){
708   array = fromStringToArray<T>(in.str());
709   return in;
710 }
711 
712 /** \brief Extracts data from an istringstream object
713  * \note This templated function is necessary for the proper extraction of
714  *       data by the \c fromStringToArray function.
715  * \relates Array.
716  */
717 template<typename T> inline
extractDataFromISS(std::istringstream & iss,T & data)718 void extractDataFromISS( std::istringstream& iss, T& data )
719 {
720   iss >> data; // Assumes type has operator>>(...) defined!
721 }
722 
723 /** \brief Extracts std::string data from an istringstream object
724  * \note This function overloads the templated \c extractDataFromISS function
725          and is necessary for the proper extraction of std::string objects
726          by the \c fromStringToArray function.
727  * \relates Array.
728  */
729 inline
extractDataFromISS(std::istringstream & iss,std::string & data)730 void extractDataFromISS( std::istringstream& iss, std::string& data )
731 {
732   // grab unformatted string.
733   data = iss.str();
734   // remove white space from beginning and end of string.
735   data = Utils::trimWhiteSpace(data);
736 }
737 
738 /**
739  * \brief Get the format that is used for the specialization of the TypeName
740  * traits class for Array.
741  *
742  * The string returned will contain only one
743  * "*" character. The "*" character should then be replaced with the actual
744  * template type of the array.
745  * \relates Array.
746  */
747 inline
getArrayTypeNameTraitsFormat()748 std::string getArrayTypeNameTraitsFormat(){
749   return "Array(*)";
750 }
751 
752 
753 
754 /** \brief TypeNameTraits specialization for Array.
755  *
756  * NOTE: Use of this class requires that either that the type T be
757  * defined or that a TypeNameTraits<T> specialization exists.  In
758  * order not to restrict the use of Array<T> for undefined pointer
759  * types (where T=U*), this TypeNameTraits class specialization will
760  * not be used in core Array functionality.
761  *
762  * This matters because some MPI implementations use pointers to
763  * undefined structs.  If you want to portably store these undefined
764  * struct pointers in an Array, then you can't use this traits class.
765  * This is a limitation of the C++ language itself.
766  *
767  * \ingroup teuchos_mem_mng_grp
768  */
769 template<typename T>
770 class TEUCHOSCORE_LIB_DLL_EXPORT TypeNameTraits<Array<T> > {
771 public:
name()772   static std::string name(){
773     std::string formatString = getArrayTypeNameTraitsFormat();
774     size_t starPos = formatString.find("*");
775     std::string prefix = formatString.substr(0,starPos);
776     std::string postFix = formatString.substr(starPos+1);
777     return prefix+TypeNameTraits<T>::name()+postFix;
778   }
concreteName(const Array<T> &)779   static std::string concreteName(const Array<T>&)
780     { return name(); }
781 };
782 
783 
784 } // namespace Teuchos
785 
786 
787 //
788 // Implementation
789 //
790 
791 
792 namespace Teuchos {
793 
794 
795 // All constructors
796 
797 
798 template<typename T> inline
Array()799 Array<T>::Array()
800 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
801   : vec_(rcp(new std::vector<T>()))
802 #endif
803 {}
804 
805 
806 template<typename T> inline
Array(size_type n,const value_type & value)807 Array<T>::Array(size_type n, const value_type& value) :
808 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
809   vec_(rcp(new std::vector<T>(n,value)))
810 #else
811   vec_(n, value)
812 #endif
813 {}
814 
815 
816 template<typename T> inline
Array(const Array<T> & x)817 Array<T>::Array(const Array<T>& x) :
818 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
819   vec_(rcp(new std::vector<T>(*x.vec_)))
820 #else
821   vec_(x.vec_)
822 #endif
823 {}
824 
825 
826 template<typename T> template<typename InputIterator> inline
Array(InputIterator first,InputIterator last)827 Array<T>::Array(InputIterator first, InputIterator last) :
828 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
829   vec_(rcp(new std::vector<T>(first, last)))
830 #else
831   vec_(first, last)
832 #endif
833 {}
834 
835 
836 template<typename T> inline
~Array()837 Array<T>::~Array()
838 {}
839 
840 
841 template<typename T> inline
Array(const ArrayView<const T> & a)842 Array<T>::Array(const ArrayView<const T>& a)
843 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
844   : vec_(rcp(new std::vector<T>()))
845 #endif
846 {
847   insert(begin(), a.begin(), a.end());
848 }
849 
850 
851 template<typename T>
852 template<int N>
853 inline
Array(const Tuple<T,N> & t)854 Array<T>::Array(const Tuple<T,N>& t)
855 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
856   : vec_(rcp(new std::vector<T>()))
857 #endif
858 {
859   insert(begin(), t.begin(), t.end());
860 }
861 
862 
863 template<typename T> inline
operator =(const Array & a)864 Array<T>& Array<T>::operator=(const Array& a)
865 {
866 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
867   std::lock_guard<std::mutex> lockGuard(mutex_lock);
868 #endif
869   vec(true) = a.vec();
870   return *this;
871 }
872 
873 
874 // Other std::vector functions
875 
876 
877 template<typename T> inline
assign(size_type n,const value_type & val)878 void Array<T>::assign(size_type n, const value_type& val)
879 {
880 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
881   std::lock_guard<std::mutex> lockGuard(mutex_lock);
882 #endif
883   vec(true).assign(n,val);
884 }
885 
886 
887 template<typename T> template<typename InputIterator> inline
assign(InputIterator first,InputIterator last)888 void Array<T>::assign(InputIterator first, InputIterator last)
889 {
890 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
891   std::lock_guard<std::mutex> lockGuard(mutex_lock);
892 #endif
893   vec(true).assign(first,last);
894 }
895 
896 
897 template<typename T> inline
898 typename Array<T>::iterator
begin()899 Array<T>::begin()
900 {
901 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
902 
903 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
904   std::lock_guard<std::mutex> lockGuard(mutex_lock);
905 #endif
906 
907   if (is_null(extern_arcp_)) {
908     // Here we must use the same RCP to avoid creating two unrelated RCPNodes!
909     extern_arcp_ = arcp(vec_); // Will be null if vec_ is sized!
910   }
911   // Returning a weak pointer will help to catch dangling references but still
912   // keep the same behavior as optimized code.
913 
914   return extern_arcp_.create_weak();
915 #else
916   return vec().begin();
917 #endif
918 }
919 
920 
921 template<typename T> inline
922 typename Array<T>::iterator
end()923 Array<T>::end()
924 {
925 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
926   return begin() + size();
927 #else
928   return vec().end();
929 #endif
930 }
931 
932 template<typename T> inline
933 typename Array<T>::const_iterator
begin() const934 Array<T>::begin() const
935 {
936 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
937 
938 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
939   std::lock_guard<std::mutex> lockGuard(mutex_lock);
940 #endif
941   if (is_null(extern_carcp_)) {
942     // Note that this used to call the non-const begin() function above
943     // I've moved that code here to make the mutex locking more transparent and
944     // prevent the need to structure something awkward to avoid double locks
945     // The original line of code was this:
946     // extern_carcp_ = const_cast<Array<T>*>(this)->begin();
947     // Now replaced by the following code which mirrors the above begin() call
948     if (is_null(extern_arcp_)) {
949       extern_arcp_ = arcp(vec_);
950     }
951     // note that we call create_weak() twice, first on the non-const and then
952     // below on the const - this preserves the original design exactly
953     extern_carcp_ = extern_arcp_.create_weak();
954   }
955 
956   // Returning a weak pointer will help to catch dangling references but still
957   // keep the same behavior as optimized code.
958   return extern_carcp_.create_weak();
959 #else
960   return vec().begin();
961 #endif
962 }
963 
964 
965 template<typename T> inline
966 typename Array<T>::const_iterator
end() const967 Array<T>::end() const
968 {
969 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
970   return begin() + size();
971 #else
972   return vec().end();
973 #endif
974 }
975 
976 
977 template<typename T> inline
978 typename Array<T>::reverse_iterator
rbegin()979 Array<T>::rbegin()
980 {
981 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
982   return reverse_iterator(end());
983 #else
984   return vec().rbegin();
985 #endif
986 }
987 
988 
989 template<typename T> inline
990 typename Array<T>::reverse_iterator
rend()991 Array<T>::rend()
992 {
993 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
994   return reverse_iterator(begin());
995 #else
996   return vec().rend();
997 #endif
998 }
999 
1000 
1001 template<typename T> inline
1002 typename Array<T>::const_reverse_iterator
rbegin() const1003 Array<T>::rbegin() const
1004 {
1005 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1006   return const_reverse_iterator(end());
1007 #else
1008   return vec().rbegin();
1009 #endif
1010 }
1011 
1012 
1013 template<typename T> inline
1014 typename Array<T>::const_reverse_iterator
rend() const1015 Array<T>::rend() const
1016 {
1017 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1018   return const_reverse_iterator(begin());
1019 #else
1020   return vec().rend();
1021 #endif
1022 }
1023 
1024 
1025 template<typename T> inline
1026 typename Array<T>::size_type
size() const1027 Array<T>::size() const
1028 {
1029   return vec().size();
1030 }
1031 
1032 
1033 template<typename T> inline
1034 typename Array<T>::size_type
max_size() const1035 Array<T>::max_size() const
1036 {
1037   return std::numeric_limits<size_type>::max();
1038 }
1039 
1040 
1041 template<typename T> inline
1042 void
resize(size_type new_size,const value_type & x)1043 Array<T>::resize(size_type new_size, const value_type& x)
1044 {
1045 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1046   std::lock_guard<std::mutex> lockGuard(mutex_lock);
1047 #endif
1048   vec(true).resize(new_size,x);
1049 }
1050 
1051 
1052 template<typename T> inline
1053 typename Array<T>::size_type
capacity() const1054 Array<T>::capacity() const
1055 {
1056   return vec().capacity();
1057 }
1058 
1059 
1060 template<typename T> inline
empty() const1061 bool Array<T>::empty() const
1062 {
1063   return vec().empty();
1064 }
1065 
1066 
1067 template<typename T> inline
reserve(size_type n)1068 void Array<T>::reserve(size_type n)
1069 {
1070 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1071   std::lock_guard<std::mutex> lockGuard(mutex_lock);
1072 #endif
1073   vec(true).reserve(n);
1074 }
1075 
1076 
1077 template<typename T> inline
1078 typename Array<T>::reference
operator [](size_type i)1079 Array<T>::operator[](size_type i)
1080 {
1081 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1082   assertIndex(i);
1083 #endif
1084   return vec()[i];
1085 }
1086 
1087 
1088 template<typename T> inline
1089 typename Array<T>::const_reference
operator [](size_type i) const1090 Array<T>::operator[](size_type i) const
1091 {
1092 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1093   assertIndex(i);
1094 #endif
1095   return vec()[i];
1096 }
1097 
1098 
1099 template<typename T> inline
1100 typename Array<T>::reference
at(size_type i)1101 Array<T>::at(size_type i)
1102 {
1103 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1104   assertIndex(i);
1105 #endif
1106   return vec().at(i);
1107 }
1108 
1109 
1110 template<typename T> inline
1111 typename Array<T>::const_reference
at(size_type i) const1112 Array<T>::at(size_type i) const
1113 {
1114 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1115   assertIndex(i);
1116 #endif
1117   return vec().at(i);
1118 }
1119 
1120 
1121 template<typename T> inline
1122 typename Array<T>::reference
front()1123 Array<T>::front()
1124 {
1125 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1126   assertNotNull();
1127 #endif
1128   return vec().front();
1129 }
1130 
1131 
1132 template<typename T> inline
1133 typename Array<T>::const_reference
front() const1134 Array<T>::front() const
1135 {
1136 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1137   assertNotNull();
1138 #endif
1139   return vec().front();
1140 }
1141 
1142 
1143 template<typename T> inline
1144 typename Array<T>::reference
back()1145 Array<T>::back()
1146 {
1147 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1148   assertNotNull();
1149 #endif
1150   return vec().back();
1151 }
1152 
1153 
1154 template<typename T> inline
1155 typename Array<T>::const_reference
back() const1156 Array<T>::back() const
1157 {
1158 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1159   assertNotNull();
1160 #endif
1161   return vec().back();
1162 }
1163 
1164 
1165 template<typename T> inline
push_back(const value_type & x)1166 void Array<T>::push_back(const value_type& x)
1167 {
1168 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1169   std::lock_guard<std::mutex> lockGuard(mutex_lock);
1170 #endif
1171   vec(true).push_back(x);
1172 }
1173 
1174 
1175 template<typename T> inline
pop_back()1176 void Array<T>::pop_back()
1177 {
1178 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1179   assertNotNull();
1180 #endif
1181 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1182   std::lock_guard<std::mutex> lockGuard(mutex_lock);
1183 #endif
1184   vec(true).pop_back();
1185 }
1186 
1187 
1188 // 2009/11/13:: rabartl: After moving to a full RCPNode tracing and lookup
1189 // model, I had to how modifying functions like insert(...) and erase(...)
1190 // work which have active iterators controled by the client and yet need to
1191 // allow the structure of the container change.  The way these troublesome
1192 // functions work is that first the raw std::vector iterator is extracted.
1193 // The function vec(true, true) then deletes the strong iterators but there is
1194 // still a weak ArrayRCP object that is owned by the client which is being
1195 // passed into this function.  The issue is that the design of ArrayRCP is
1196 // such that the RCPNode object is not removed but instead remains in order to
1197 // perform runtime checking.
1198 
1199 
1200 template<typename T> inline
1201 typename Array<T>::iterator
insert(iterator position,const value_type & x)1202 Array<T>::insert(iterator position, const value_type& x)
1203 {
1204 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1205   // Assert a valid iterator and get vector iterator
1206   const typename std::vector<T>::iterator raw_poss = raw_position(position);
1207   const difference_type i = position - begin();
1208 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1209   {
1210   std::lock_guard<std::mutex> lockGuard(mutex_lock);
1211 #endif
1212   vec(true, true).insert(raw_poss, x);
1213 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1214   } // must unlock mutex_lock before calling begin() which will lock again
1215 #endif
1216   return begin() + i;
1217 #else
1218   return vec_.insert(position, x);
1219 #endif
1220 }
1221 
1222 
1223 template<typename T> inline
insert(iterator position,size_type n,const value_type & x)1224 void Array<T>::insert(iterator position, size_type n, const value_type& x)
1225 {
1226 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1227   const typename std::vector<T>::iterator raw_poss = raw_position(position);
1228 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1229   std::lock_guard<std::mutex> lockGuard(mutex_lock);
1230 #endif
1231   vec(true, true).insert(raw_poss, n, x);
1232 #else
1233   vec_.insert(position, n, x);
1234 #endif
1235 }
1236 
1237 
1238 template<typename T> template<typename InputIterator> inline
insert(iterator position,InputIterator first,InputIterator last)1239 void Array<T>::insert(iterator position, InputIterator first, InputIterator last)
1240 {
1241 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1242   const typename std::vector<T>::iterator raw_poss = raw_position(position);
1243 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1244   std::lock_guard<std::mutex> lockGuard(mutex_lock);
1245 #endif
1246   vec(true, true).insert(raw_poss, first, last);
1247 #else
1248   vec_.insert(position, first, last);
1249 #endif
1250 }
1251 
1252 
1253 template<typename T> inline
1254 typename Array<T>::iterator
erase(iterator position)1255 Array<T>::erase(iterator position)
1256 {
1257 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1258   assertNotNull();
1259   // Assert a valid iterator and get vector iterator
1260   const typename std::vector<T>::iterator raw_poss = raw_position(position);
1261   const difference_type i = position - begin();
1262 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1263   {
1264   std::lock_guard<std::mutex> lockGuard(mutex_lock);
1265 #endif
1266   vec(true, true).erase(raw_poss);
1267 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1268   } // must unlock mutex_lock before call begin() or dead lock on second call
1269 #endif
1270   return begin() + i;
1271 #else
1272   return vec_.erase(position);
1273 #endif
1274 }
1275 
1276 
1277 template<typename T> inline
1278 typename Array<T>::iterator
erase(iterator first,iterator last)1279 Array<T>::erase(iterator first, iterator last)
1280 {
1281 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1282   if (empty()) {
1283     TEUCHOS_ASSERT(first == begin());
1284     TEUCHOS_ASSERT(last == end());
1285     return end();
1286   }
1287   assertNotNull();
1288   // Assert a valid iterator and get vector iterator
1289   const typename std::vector<T>::iterator raw_first = raw_position(first);
1290   const typename std::vector<T>::iterator raw_last = raw_position(last);
1291   const difference_type i = first - begin();
1292 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1293   {
1294   std::lock_guard<std::mutex> lockGuard(mutex_lock);
1295 #endif
1296   vec(true,true).erase(raw_first,raw_last);
1297 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1298   }  // must unlock mutex_lock before call begin() or dead lock on second call
1299 #endif
1300   return begin() + i;
1301 #else
1302   return vec_.erase(first,last);
1303 #endif
1304 }
1305 
1306 
1307 template<typename T> inline
swap(Array & x)1308 void Array<T>::swap(Array& x)
1309 {
1310 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1311   std::lock_guard<std::mutex> lockGuard(mutex_lock);
1312 #endif
1313   vec(true).swap(x.vec());
1314 }
1315 
1316 
1317 template<typename T> inline
clear()1318 void Array<T>::clear()
1319 {
1320 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1321   std::lock_guard<std::mutex> lockGuard(mutex_lock);
1322 #endif
1323   vec(true).clear();
1324 }
1325 
1326 
1327 // Non-standard functions
1328 
1329 
1330 template<typename T> inline
append(const T & x)1331 Array<T>& Array<T>::append(const T& x)
1332 {
1333   this->push_back(x);
1334   return *this;
1335 }
1336 
1337 
1338 template<typename T> inline
remove(int i)1339 void Array<T>::remove(int i)
1340 {
1341 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1342   assertIndex(i);
1343 #endif
1344   // Erase the i-th element of this array.
1345   this->erase( this->begin() + i );
1346 }
1347 
1348 
1349 template<typename T> inline
length() const1350 int Array<T>::length() const
1351 {
1352   return static_cast<int> (this->size ());
1353 }
1354 
1355 
1356 template<typename T> inline
toString() const1357 std::string Array<T>::toString() const
1358 {
1359   return (*this)().toString(); // Use ArrayView<T>::toString()
1360 }
1361 
1362 
1363 template<typename T> inline
hasBoundsChecking()1364 bool Array<T>::hasBoundsChecking()
1365 {
1366 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1367   return true;
1368 #else
1369   return false;
1370 #endif
1371 }
1372 
1373 
1374 template<typename T> inline
getRawPtr()1375 T* Array<T>::getRawPtr()
1376 {
1377   return ( size() ? &(*this)[0] : nullptr );
1378 }
1379 
1380 template<typename T> inline
data()1381 T* Array<T>::data()
1382 {
1383   return ( size() ? &(*this)[0] : nullptr );
1384 }
1385 
1386 template<typename T> inline
getRawPtr() const1387 const T* Array<T>::getRawPtr() const
1388 {
1389   return ( size() ? &(*this)[0] : nullptr );
1390 }
1391 
1392 template<typename T> inline
data() const1393 const T* Array<T>::data() const
1394 {
1395   return ( size() ? &(*this)[0] : nullptr );
1396 }
1397 
1398 // Conversions to and from std::vector
1399 
1400 
1401 template<typename T> inline
Array(const std::vector<T> & v)1402 Array<T>::Array( const std::vector<T> &v ) :
1403 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1404   vec_(new std::vector<T>(v))
1405 #else
1406   vec_(v)
1407 #endif
1408 {}
1409 
1410 
1411 template<typename T> inline
toVector() const1412 std::vector<T> Array<T>::toVector() const
1413 {
1414   if (!size())
1415     return std::vector<T>();
1416   std::vector<T> v(begin(),end());
1417   return v;
1418 }
1419 
1420 
1421 template<typename T> inline
operator =(const std::vector<T> & v)1422 Array<T>& Array<T>::operator=( const std::vector<T> &v )
1423 {
1424 #ifdef USE_MUTEX_LOCK_FOR_ARRAY
1425   std::lock_guard<std::mutex> lockGuard(mutex_lock);
1426 #endif
1427   vec(true) = v;
1428   return *this;
1429 }
1430 
1431 
1432 // Views
1433 
1434 
1435 template<typename T> inline
view(size_type offset,size_type size_in)1436 ArrayView<T> Array<T>::view( size_type offset, size_type size_in )
1437 {
1438   if (size_in) {
1439 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1440     return ArrayView<T>(this->begin().persistingView(offset, size_in));
1441 #else
1442     return arrayView( &vec()[offset], size_in );
1443 #endif
1444   }
1445   return Teuchos::null;
1446 }
1447 
1448 
1449 template<typename T> inline
view(size_type offset,size_type size_in) const1450 ArrayView<const T> Array<T>::view( size_type offset, size_type size_in ) const
1451 {
1452   if (size_in) {
1453 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1454     return ArrayView<const T>(this->begin().persistingView(offset, size_in));
1455 #else
1456     return arrayView( &vec()[offset], size_in );
1457 #endif
1458   }
1459   return Teuchos::null;
1460   // NOTE: Above, we use a different implementation to call the const version
1461   // of begin() instead of the non-const version.  This sets up a different
1462   // ArrayRCP object that gets checked.
1463 }
1464 
1465 
1466 template<typename T> inline
operator ()(size_type offset,size_type size_in)1467 ArrayView<T> Array<T>::operator()( size_type offset, size_type size_in )
1468 {
1469   return view(offset, size_in);
1470 }
1471 
1472 
1473 template<typename T> inline
operator ()(size_type offset,size_type size_in) const1474 ArrayView<const T> Array<T>::operator()( size_type offset, size_type size_in ) const
1475 {
1476   return view(offset, size_in);
1477 }
1478 
1479 
1480 template<typename T> inline
operator ()()1481 ArrayView<T> Array<T>::operator()()
1482 {
1483   if (!size())
1484     return null;
1485   return this->view(0, size());
1486 }
1487 
1488 
1489 template<typename T> inline
operator ()() const1490 ArrayView<const T> Array<T>::operator()() const
1491 {
1492   if (!size())
1493     return null;
1494   return this->view(0, size());
1495 }
1496 
1497 
1498 template<typename T> inline
operator ArrayView<T>()1499 Array<T>::operator ArrayView<T>()
1500 {
1501   return this->operator()();
1502 }
1503 
1504 
1505 template<typename T> inline
operator ArrayView<const T>() const1506 Array<T>::operator ArrayView<const T>() const
1507 {
1508   return this->operator()();
1509 }
1510 
1511 
1512 // private
1513 
1514 
1515 template<typename T>
1516 std::vector<T>&
vec(bool isStructureBeingModified,bool activeIter)1517 Array<T>::vec( bool isStructureBeingModified, bool activeIter )
1518 {
1519 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1520   (void)activeIter;
1521   if (isStructureBeingModified) {
1522     // Give up my ArrayRCPs used for iterator access since the array we be
1523     // getting modifed!  Any clients that have views through weak pointers
1524     // better not touch them!
1525 
1526     // Note that in debug mode these are mutex protected - the mutex should
1527     // always be locked when this function is called with
1528     // isStructureBeingModified true
1529     extern_arcp_ = null;
1530     extern_carcp_ = null;
1531   }
1532   return *vec_;
1533 #else
1534   // get rid of "unused parameter" warnings
1535   (void)isStructureBeingModified;
1536   (void)activeIter;
1537   return vec_;
1538 #endif
1539 }
1540 
1541 
1542 template<typename T> inline
1543 const std::vector<T>&
vec() const1544 Array<T>::vec() const
1545 {
1546 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1547   return *vec_;
1548 #else
1549   return vec_;
1550 #endif
1551 }
1552 
1553 
1554 template<typename T> inline
1555 typename std::vector<T>::iterator
raw_position(iterator position)1556 Array<T>::raw_position( iterator position )
1557 {
1558 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1559   const iterator first = this->begin();
1560   const iterator last = this->end();
1561   TEUCHOS_TEST_FOR_EXCEPTION(
1562     !(first <= position && position <= last), DanglingReferenceError,
1563     "Error, this iterator is no longer valid for this Aray!"
1564     );
1565   // Note, above operator<=(...) functions will throw
1566   // IncompatibleIteratorsError if the iterators do not share the same
1567   // RCP_node object!
1568   return vec_->begin() + (position - this->begin());
1569 #else
1570   return position;
1571 #endif
1572 }
1573 
1574 
1575 template<typename T> inline
assertIndex(size_type i) const1576 void Array<T>::assertIndex(size_type i) const
1577 {
1578   TEUCHOS_TEST_FOR_EXCEPTION(
1579     !( 0 <= i && i < size() ), RangeError,
1580     "Array<T>::assertIndex(i): i="<<i<<" out of range [0, "<< size() << ")"
1581     );
1582 }
1583 
1584 
1585 template<typename T> inline
assertNotNull() const1586 void Array<T>::assertNotNull() const
1587 {
1588   TEUCHOS_TEST_FOR_EXCEPTION(
1589     !size(), NullReferenceError,
1590     typeName(*this)<<"::assertNotNull(): "
1591     "Error, the array has size zero!"
1592     );
1593 }
1594 
1595 
1596 } // namespace Teuchos
1597 
1598 
1599 // Nonmember functions
1600 
1601 
1602 template<typename T> inline
operator ==(const Array<T> & a1,const Array<T> & a2)1603 bool Teuchos::operator==( const Array<T> &a1, const Array<T> &a2 )
1604 { return (a1.vec() == a2.vec()); }
1605 
1606 
1607 template<typename T> inline
operator !=(const Array<T> & a1,const Array<T> & a2)1608 bool Teuchos::operator!=( const Array<T> &a1, const Array<T> &a2 )
1609 { return (a1.vec() != a2.vec()); }
1610 
1611 
1612 template<typename T> inline
swap(Array<T> & a1,Array<T> & a2)1613 void Teuchos::swap( Array<T> &a1, Array<T> &a2 )
1614 { a1.swap(a2); }
1615 
1616 
1617 template<typename T> inline
operator <(const Array<T> & a1,const Array<T> & a2)1618 bool Teuchos::operator<( const Array<T> &a1, const Array<T> &a2 )
1619 { return (a1.vec() < a2.vec()); }
1620 
1621 
1622 template<typename T> inline
operator <=(const Array<T> & a1,const Array<T> & a2)1623 bool Teuchos::operator<=( const Array<T> &a1, const Array<T> &a2 )
1624 { return (a1.vec() <= a2.vec()); }
1625 
1626 
1627 template<typename T> inline
operator >(const Array<T> & a1,const Array<T> & a2)1628 bool Teuchos::operator>( const Array<T> &a1, const Array<T> &a2 )
1629 { return (a1.vec() > a2.vec()); }
1630 
1631 
1632 template<typename T> inline
operator >=(const Array<T> & a1,const Array<T> & a2)1633 bool Teuchos::operator>=( const Array<T> &a1, const Array<T> &a2 )
1634 { return (a1.vec() >= a2.vec()); }
1635 
1636 
1637 template<typename T> inline
operator <<(std::ostream & os,const Array<T> & array)1638 std::ostream& Teuchos::operator<<(
1639   std::ostream& os, const Array<T>& array
1640   )
1641 {
1642   return os << Teuchos::toString(array);
1643 }
1644 
1645 
1646 template<typename T> inline
hashCode(const Array<T> & array)1647 int Teuchos::hashCode(const Array<T>& array)
1648 {
1649   int rtn = hashCode(array.length());
1650   for (int i=0; i<array.length(); i++)
1651   {
1652     rtn += hashCode(array[i]);
1653   }
1654   if (rtn < 0)
1655   {
1656     /* Convert the largest -ve int to zero and -1 to
1657     * std::numeric_limits<int>::max()
1658     * */
1659     size_t maxIntBeforeWrap = std::numeric_limits<int>::max();
1660     maxIntBeforeWrap ++;
1661     rtn += maxIntBeforeWrap;
1662   }
1663   return rtn;
1664 }
1665 
1666 
1667 template<typename T> inline
createVector(const Array<T> & a)1668 std::vector<T> Teuchos::createVector( const Array<T> &a )
1669 {
1670   return a.toVector();
1671 }
1672 
1673 
1674 template<typename T> inline
toString(const Array<T> & array)1675 std::string Teuchos::toString(const Array<T>& array)
1676 {
1677   return array.toString();
1678 }
1679 
1680 
1681 template<typename T>
1682 Teuchos::Array<T>
fromStringToArray(const std::string & arrayStr)1683 Teuchos::fromStringToArray(const std::string& arrayStr)
1684 {
1685   const std::string str = Utils::trimWhiteSpace(arrayStr);
1686   std::istringstream iss(str);
1687   TEUCHOS_TEST_FOR_EXCEPTION(
1688     ( str[0]!='{' || str[str.length()-1] != '}' )
1689     ,InvalidArrayStringRepresentation
1690     ,"Error, the std::string:\n"
1691     "----------\n"
1692     <<str<<
1693     "\n----------\n"
1694     "is not a valid array represntation!"
1695     );
1696   char c;
1697   c = iss.get(); // Read initial '{'
1698   TEUCHOS_TEST_FOR_EXCEPT(c!='{'); // Should not throw!
1699   // Now we are ready to begin reading the entries of the array!
1700   Array<T> a;
1701   while( !iss.eof() ) {
1702     // Get the basic entry std::string
1703     std::string entryStr;
1704     std::getline(iss,entryStr,','); // Get next entry up to ,!
1705     // ToDo: Above, we might have to be careful to look for the opening and
1706     // closing of parentheses in order not to pick up an internal ',' in the
1707     // middle of an entry (for a std::complex number for instance).  The above
1708     // implementation assumes that there will be no commas in the middle of
1709     // the std::string representation of an entry.  This is certainly true for
1710     // the types bool, int, float, and double.
1711     //
1712     // Trim whitespace from beginning and end
1713     entryStr = Utils::trimWhiteSpace(entryStr);
1714     TEUCHOS_TEST_FOR_EXCEPTION(
1715       0 == entryStr.length(),
1716       InvalidArrayStringRepresentation,
1717       "Error, the std::string:\n"
1718       "----------\n"
1719       <<str<<
1720       "\n----------\n"
1721       "is not a valid array represntation because it has an empty array entry!"
1722       );
1723     // Remove the final '}' if this is the last entry and we did not
1724     // actually terminate the above getline(...) on ','
1725     bool found_end = false;
1726     if(entryStr[entryStr.length()-1]=='}') {
1727       entryStr = entryStr.substr(0,entryStr.length()-1);
1728       found_end = true;
1729       if( entryStr.length()==0 && a.size()==0 )
1730         return a; // This is the empty array "{}" (with any spaces in it!)
1731     }
1732     // Finally we can convert the entry and add it to the array!
1733     std::istringstream entryiss(entryStr);
1734     T entry;
1735     Teuchos::extractDataFromISS( entryiss, entry );
1736     // ToDo: We may need to define a traits class to allow us to specialized
1737     // how conversion from a std::string to a object is done!
1738     a.push_back(entry);
1739     // At the end of the loop body here, if we have reached the last '}'
1740     // then the input stream iss should be empty and iss.eof() should be
1741     // true, so the loop should terminate.  We put an std::exception test here
1742     // just in case something has gone wrong.
1743     TEUCHOS_TEST_FOR_EXCEPTION(
1744       found_end && !iss.eof()
1745       ,InvalidArrayStringRepresentation
1746       ,"Error, the std::string:\n"
1747       "----------\n"
1748       <<str<<
1749       "\n----------\n"
1750       "is not a valid array represntation!"
1751       );
1752   }
1753   return a;
1754 }
1755 
1756 
1757 #endif // TEUCHOS_ARRAY_H
1758