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