Teuchos - Trilinos Tools Package Version of the Day
Teuchos_ArrayRCP.hpp
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #ifndef TEUCHOS_ARRAY_RCP_HPP
00043 #define TEUCHOS_ARRAY_RCP_HPP
00044 
00045 
00046 #include "Teuchos_ArrayRCPDecl.hpp"
00047 #include "Teuchos_ArrayView.hpp"
00048 #include "Teuchos_Assert.hpp"
00049 #include "Teuchos_dyn_cast.hpp"
00050 #include "Teuchos_as.hpp"
00051 
00052 
00053 namespace Teuchos {
00054 
00055 
00056 // Helper code (not for general clients)
00057 
00058 
00059 template<class T> inline
00060 RCPNode* ArrayRCP_createNewRCPNodeRawPtr( T* p, bool has_ownership_in )
00061 {
00062   return new RCPNodeTmpl<T,DeallocArrayDelete<T> >(
00063     p, DeallocArrayDelete<T>(), has_ownership_in
00064     );
00065 }
00066 
00067 
00068 template<class T, class Dealloc_T>
00069 inline
00070 RCPNode* ArrayRCP_createNewDeallocRCPNodeRawPtr(
00071   T* p, Dealloc_T dealloc, bool has_ownership_in
00072   )
00073 {
00074     return new RCPNodeTmpl<T,Dealloc_T>(p, dealloc, has_ownership_in);
00075 }
00076 
00077 
00078 template<class T2, class T1>
00079 class ArcpReinterpretCastEmbeddedObj
00080 {
00081 public:
00082   typedef T2 ptr_t;
00083   ArcpReinterpretCastEmbeddedObj()
00084     : arcp_pod_(null)
00085     {}
00086   ArcpReinterpretCastEmbeddedObj(const ArrayRCP<T1> &arcp_pod)
00087     : arcp_pod_(arcpCloneNode(arcp_pod)) // Unique reference count!
00088     {}
00089   // NOTE: The default copy constructor is allowed and does the right thing
00090   ~ArcpReinterpretCastEmbeddedObj()
00091     { freeMemory(); }
00092   ArcpReinterpretCastEmbeddedObj&
00093   operator=(const ArcpReinterpretCastEmbeddedObj& arceo)
00094     {
00095       assert(is_null(arceo.arcp_pod_)); // Can only be a catestrophic programming error!
00096       freeMemory();
00097       return *this;
00098     }
00099 private:
00100   ArrayRCP<T1> arcp_pod_; 
00101   void freeMemory()
00102     {
00103       typedef typename ArrayRCP<T2>::iterator itr_t;
00104       if (arcp_pod_.strong_count() == 1) {
00105         ArrayRCP<T2> arcp2 = arcp_reinterpret_cast<T2>(arcp_pod_);
00106         for (itr_t itr = arcp2.begin(); itr != arcp2.end(); ++itr) {
00107           itr->~T2();
00108         }
00109         arcp_pod_ = null;
00110       }
00111     }
00112 };
00113 
00114 
00115 // Constructors/Destructors/Initializers 
00116 
00117 template<class T> inline
00118 ArrayRCP<T>::ArrayRCP( ENull )
00119   : ptr_(NULL), lowerOffset_(0), upperOffset_(-1)
00120 {}
00121 
00122 
00123 template<class T> inline
00124 ArrayRCP<T>::ArrayRCP(size_type n, const T& val)
00125   : ptr_(0), lowerOffset_(0), upperOffset_(-1)
00126 {
00127   *this = arcp<T>(n);
00128   std::fill_n(begin(), n, val);
00129 }
00130 
00131 
00132 template<class T> inline
00133 ArrayRCP<T>::ArrayRCP(
00134   T* p, size_type lowerOffset_in, size_type size_in,
00135   bool has_ownership_in, const ERCPNodeLookup rcpNodeLookup
00136   )
00137   : ptr_(p),
00138 #ifndef TEUCHOS_DEBUG
00139     node_(ArrayRCP_createNewRCPNodeRawPtr(p, has_ownership_in)),
00140 #endif // TEUCHOS_DEBUG
00141     lowerOffset_(lowerOffset_in),
00142     upperOffset_(size_in + lowerOffset_in - 1)
00143 {
00144 #ifdef TEUCHOS_DEBUG
00145   if (p) {
00146     RCPNode* existing_RCPNode = 0;
00147     if (!has_ownership_in && rcpNodeLookup==RCP_ENABLE_NODE_LOOKUP) {
00148       existing_RCPNode = RCPNodeTracer::getExistingRCPNode(p);
00149     }
00150     if (existing_RCPNode) {
00151       // Will not call add_new_RCPNode(...)
00152       node_ = RCPNodeHandle(existing_RCPNode, RCP_WEAK, false);
00153     }
00154     else {
00155       // Will call add_new_RCPNode(...)
00156       RCPNodeThrowDeleter nodeDeleter(ArrayRCP_createNewRCPNodeRawPtr(p, has_ownership_in));
00157       node_ = RCPNodeHandle(
00158         nodeDeleter.get(),
00159         p, typeName(*p), concreteTypeName(*p),
00160         has_ownership_in
00161         );
00162       nodeDeleter.release();
00163     }
00164   }
00165 #endif // TEUCHOS_DEBUG
00166 }
00167 
00168 
00169 template<class T>
00170 template<class Dealloc_T>
00171 inline
00172 ArrayRCP<T>::ArrayRCP(
00173   T* p, size_type lowerOffset_in, size_type size_in,
00174   Dealloc_T dealloc, bool has_ownership_in
00175   )
00176   : ptr_(p),
00177 #ifndef TEUCHOS_DEBUG
00178     node_(ArrayRCP_createNewDeallocRCPNodeRawPtr(p, dealloc, has_ownership_in)),
00179 #endif // TEUCHOS_DEBUG
00180     lowerOffset_(lowerOffset_in),
00181     upperOffset_(size_in + lowerOffset_in - 1)
00182 {
00183 #ifdef TEUCHOS_DEBUG
00184   if (p) {
00185     node_ = RCPNodeHandle(
00186       ArrayRCP_createNewDeallocRCPNodeRawPtr(p, dealloc, has_ownership_in),
00187       p, typeName(*p), concreteTypeName(*p),
00188       has_ownership_in
00189       //, RCP_STRONG, false
00190       );
00191   }
00192 #endif // TEUCHOS_DEBUG
00193 }
00194 
00195 
00196 template<class T> inline
00197 ArrayRCP<T>::ArrayRCP(const ArrayRCP<T>& r_ptr)
00198   :ptr_(r_ptr.ptr_),
00199    node_(r_ptr.node_),
00200    lowerOffset_(r_ptr.lowerOffset_),
00201    upperOffset_(r_ptr.upperOffset_)
00202 {}
00203 
00204 
00205 template<class T> inline
00206 ArrayRCP<T>::~ArrayRCP()
00207 {}
00208 
00209 
00210 template<class T> inline
00211 ArrayRCP<T>& ArrayRCP<T>::operator=(const ArrayRCP<T>& r_ptr)
00212 {
00213   if( this == &r_ptr )
00214     return *this; // Assignment to self
00215   node_ = r_ptr.access_private_node(); // May throw in debug mode!
00216   ptr_ = r_ptr.ptr_;
00217   lowerOffset_ = r_ptr.lowerOffset_;
00218   upperOffset_ = r_ptr.upperOffset_;
00219   return *this;
00220   // NOTE: It is critical that the assignment of ptr_ come *after* the
00221   // assignment of node_ since node_ might throw an exception!
00222 }
00223 
00224 
00225 // Object/Pointer Access Functions
00226 
00227 
00228 template<class T> inline
00229 bool ArrayRCP<T>::is_null() const
00230 {
00231   return ptr_ == 0;
00232 }
00233 
00234 
00235 template<class T> inline
00236 T* ArrayRCP<T>::operator->() const
00237 {
00238   debug_assert_valid_ptr();
00239   debug_assert_in_range(0,1);
00240   return ptr_;
00241 }
00242 
00243 
00244 template<class T> inline
00245 T& ArrayRCP<T>::operator*() const
00246 {
00247   debug_assert_valid_ptr();
00248   debug_assert_in_range(0,1);
00249   return *ptr_;
00250 }
00251 
00252 
00253 template<class T> inline
00254 T* ArrayRCP<T>::get() const
00255 {
00256   if(ptr_) {
00257     debug_assert_valid_ptr();
00258     debug_assert_in_range(0,1);
00259   }
00260   return ptr_;
00261 }
00262 
00263 
00264 template<class T> inline
00265 T* ArrayRCP<T>::getRawPtr() const
00266 {
00267   return this->get();
00268 }
00269 
00270 
00271 template<class T> inline
00272 T& ArrayRCP<T>::operator[](size_type offset) const
00273 {
00274   debug_assert_valid_ptr();
00275   debug_assert_in_range(offset,1);
00276   return ptr_[offset];
00277 }
00278 
00279 
00280 // Pointer Arithmetic Functions
00281 
00282 
00283 template<class T> inline
00284 ArrayRCP<T>& ArrayRCP<T>::operator++()
00285 {
00286   debug_assert_valid_ptr();
00287   ++ptr_;
00288   --lowerOffset_;
00289   --upperOffset_;
00290   return *this;
00291 }
00292 
00293 
00294 template<class T> inline
00295 ArrayRCP<T> ArrayRCP<T>::operator++(int)
00296 {
00297   debug_assert_valid_ptr();
00298   ArrayRCP<T> r_ptr = *this;
00299   ++(*this);
00300   return r_ptr;
00301 }
00302 
00303 
00304 template<class T> inline
00305 ArrayRCP<T>& ArrayRCP<T>::operator--()
00306 {
00307   debug_assert_valid_ptr();
00308   --ptr_;
00309   ++lowerOffset_;
00310   ++upperOffset_;
00311   return *this;
00312 }
00313 
00314 
00315 template<class T> inline
00316 ArrayRCP<T> ArrayRCP<T>::operator--(int)
00317 {
00318   debug_assert_valid_ptr();
00319   ArrayRCP<T> r_ptr = *this;
00320   --(*this);
00321   return r_ptr;
00322 }
00323 
00324 
00325 template<class T> inline
00326 ArrayRCP<T>& ArrayRCP<T>::operator+=(size_type offset)
00327 {
00328   debug_assert_valid_ptr();
00329   ptr_ += offset;
00330   lowerOffset_ -= offset;
00331   upperOffset_ -= offset;
00332   return *this;
00333 }
00334 
00335 
00336 template<class T> inline
00337 ArrayRCP<T>& ArrayRCP<T>::operator-=(size_type offset)
00338 {
00339   debug_assert_valid_ptr();
00340   ptr_ -= offset;
00341   lowerOffset_ += offset;
00342   upperOffset_ += offset;
00343   return *this;
00344 }
00345 
00346 
00347 template<class T> inline
00348 ArrayRCP<T> ArrayRCP<T>::operator+(size_type offset) const
00349 {
00350   ArrayRCP<T> r_ptr = *this;
00351   r_ptr+=(offset);
00352   return r_ptr;
00353 }
00354 
00355 
00356 template<class T> inline
00357 ArrayRCP<T> ArrayRCP<T>::operator-(size_type offset) const
00358 {
00359   ArrayRCP<T> r_ptr = *this;
00360   r_ptr-=offset;
00361   return r_ptr;
00362 }
00363 
00364 
00365 // Standard Container-Like Functions
00366 
00367 
00368 template<class T> inline
00369 typename ArrayRCP<T>::iterator ArrayRCP<T>::begin() const
00370 {
00371   debug_assert_valid_ptr();
00372 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00373   return *this;
00374 #else
00375   return ptr_;
00376 #endif
00377 }
00378 
00379 
00380 template<class T> inline
00381 typename ArrayRCP<T>::iterator ArrayRCP<T>::end() const
00382 {
00383   debug_assert_valid_ptr();
00384 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00385   return *this + (upperOffset_ + 1);
00386 #else
00387   return ptr_ + (upperOffset_ + 1);
00388 #endif
00389 }
00390 
00391 
00392 // ArrayRCP Views 
00393 
00394 
00395 template<class T> inline
00396 ArrayRCP<const T> ArrayRCP<T>::getConst() const
00397 {
00398   if (ptr_) {
00399     debug_assert_valid_ptr();
00400     const T *cptr = ptr_; // Will not compile if not legal!
00401     return ArrayRCP<const T>(cptr, lowerOffset_, size(), node_);
00402   }
00403   return null;
00404 }
00405 
00406 
00407 template<class T> inline
00408 ArrayRCP<T>
00409 ArrayRCP<T>::persistingView( size_type lowerOffset_in, size_type size_in ) const
00410 {
00411   if (size_in == 0) {
00412     return null;
00413   }
00414   debug_assert_valid_ptr();
00415   debug_assert_in_range(lowerOffset_in, size_in);
00416   ArrayRCP<T> ptr = *this;
00417   ptr.ptr_ = ptr.ptr_ + lowerOffset_in;
00418   ptr.lowerOffset_ = 0;
00419   ptr.upperOffset_ = size_in - 1;
00420   return ptr;
00421 }
00422 
00423 
00424 // Size and extent query functions
00425 
00426 
00427 template<class T> inline
00428 typename ArrayRCP<T>::size_type
00429 ArrayRCP<T>::lowerOffset() const
00430 {
00431   debug_assert_valid_ptr();
00432   return lowerOffset_;
00433 }
00434 
00435 
00436 template<class T> inline
00437 typename ArrayRCP<T>::size_type
00438 ArrayRCP<T>::upperOffset() const
00439 {
00440   debug_assert_valid_ptr();
00441   return upperOffset_;
00442 }
00443 
00444 
00445 template<class T> inline
00446 typename ArrayRCP<T>::size_type
00447 ArrayRCP<T>::size() const
00448 {
00449   debug_assert_valid_ptr();
00450   return upperOffset_ - lowerOffset_ + 1;
00451 }
00452 
00453 
00454 // ArrayView views 
00455 
00456 
00457 template<class T> inline
00458 ArrayView<T> ArrayRCP<T>::view( size_type lowerOffset_in, size_type size_in ) const
00459 {
00460   if (size_in == 0) {
00461     return null;
00462   }
00463   debug_assert_valid_ptr();
00464   debug_assert_in_range(lowerOffset_in,size_in);
00465 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00466   return ArrayView<T>(persistingView(lowerOffset_in, size_in).create_weak());
00467 #else
00468   return arrayView(ptr_ + lowerOffset_in, size_in);
00469 #endif
00470   // ToDo: Implement checks for dangling references!
00471 }
00472 
00473 
00474 template<class T> inline
00475 ArrayView<T> ArrayRCP<T>::operator()( size_type lowerOffset_in, size_type size_in ) const
00476 {
00477   return view(lowerOffset_in, size_in);
00478 }
00479 
00480 
00481 template<class T> inline
00482 ArrayView<T> ArrayRCP<T>::operator()() const
00483 {
00484   if (size()) {
00485     return view(lowerOffset_, size());
00486   }
00487   return null;
00488 }
00489 
00490 
00491 // Implicit conversions
00492 
00493 
00494 template<class T> inline
00495 ArrayRCP<T>::operator ArrayRCP<const T>() const
00496 {
00497   if (size()) {
00498     return ArrayRCP<const T>(ptr_, lowerOffset_, size(), node_);
00499   }
00500   return null;
00501 }
00502 
00503 
00504 // std::vector like functions
00505 
00506 
00507 template<class T> inline
00508 void ArrayRCP<T>::assign(size_type n, const T &val)
00509 {
00510   *this = arcp<T>(n);
00511   std::fill_n(this->begin(), n, val);
00512 }
00513 
00514 
00515 template<class T>
00516 template<class Iter>
00517 inline
00518 void ArrayRCP<T>::assign(Iter first, Iter last)
00519 {
00520   const size_type new_n = std::distance(first, last);
00521   if (new_n != size())
00522     *this = arcp<T>(new_n);
00523   std::copy( first, last, begin() );
00524 }
00525 
00526 
00527 template<class T> inline
00528 void ArrayRCP<T>::resize(const size_type n, const T &val)
00529 {
00530 #ifdef TEUCHOS_DEBUG
00531   TEUCHOS_ASSERT_EQUALITY(lowerOffset(), 0);
00532 #endif
00533   if (n == 0) {
00534     clear();
00535     return;
00536   }
00537   const size_type orig_n = size();
00538   if (n != orig_n) {
00539     ArrayRCP<T> tmp = *this;
00540     *this = arcp<T>(n);
00541     const size_type small_n = std::min(n, orig_n);
00542     for (size_type i = 0; i < small_n; ++i)
00543       (*this)[i] = tmp[i];
00544     for (size_type i = orig_n; i < n; ++i)
00545       (*this)[i] = val;
00546     upperOffset_ = n-1;
00547   }
00548 }
00549 
00550 
00551 template<class T> inline
00552 void ArrayRCP<T>::clear()
00553 {
00554   *this = null;
00555 }
00556 
00557 
00558 // Misc functions
00559 
00560 template<class T> inline
00561 void ArrayRCP<T>::deepCopy(const ArrayView<const T>& av)
00562 {
00563   if (av.size() == 0) {
00564     *this = null;
00565     return;
00566   }
00567   assign(av.begin(), av.end());
00568 }
00569 
00570 
00571 // Reference counting
00572 
00573 
00574 template<class T> inline
00575 ERCPStrength ArrayRCP<T>::strength() const
00576 {
00577   return node_.strength();
00578 }
00579 
00580 
00581 template<class T> inline
00582 bool ArrayRCP<T>::is_valid_ptr() const
00583 {
00584   if (ptr_)
00585     return node_.is_valid_ptr();
00586   return true;
00587 }
00588 
00589 
00590 template<class T> inline
00591 int ArrayRCP<T>::strong_count() const
00592 {
00593   return node_.strong_count();
00594 }
00595 
00596 
00597 template<class T> inline
00598 int ArrayRCP<T>::weak_count() const
00599 {
00600   return node_.weak_count();
00601 }
00602 
00603 
00604 template<class T> inline
00605 int ArrayRCP<T>::total_count() const
00606 {
00607   return node_.total_count();
00608 }
00609 
00610 
00611 template<class T> inline
00612 void ArrayRCP<T>::set_has_ownership()
00613 {
00614   node_.has_ownership(true);
00615 }
00616 
00617 
00618 template<class T> inline
00619 bool ArrayRCP<T>::has_ownership() const
00620 {
00621   return node_.has_ownership();
00622 }
00623 
00624 
00625 template<class T> inline
00626 T* ArrayRCP<T>::release()
00627 {
00628   debug_assert_valid_ptr();
00629   node_.has_ownership(false);
00630   return ptr_;
00631 }
00632 
00633 
00634 template<class T> inline
00635 ArrayRCP<T> ArrayRCP<T>::create_weak() const
00636 {
00637   debug_assert_valid_ptr();
00638   return ArrayRCP<T>(ptr_, lowerOffset_, size(), node_.create_weak());
00639 }
00640 
00641 
00642 template<class T> inline
00643 ArrayRCP<T> ArrayRCP<T>::create_strong() const
00644 {
00645   debug_assert_valid_ptr();
00646   return ArrayRCP<T>(ptr_, lowerOffset_, size(), node_.create_strong());
00647 }
00648 
00649 
00650 template<class T>
00651 template <class T2>
00652 inline
00653 bool ArrayRCP<T>::shares_resource(const ArrayRCP<T2>& r_ptr) const
00654 {
00655   return node_.same_node(r_ptr.access_private_node());
00656   // Note: above, r_ptr is *not* the same class type as *this so we can not
00657   // access its node_ member directly!  This is an interesting detail to the
00658   // C++ protected/private protection mechanism!
00659 }
00660 
00661 
00662 // Assertion Functions
00663 
00664 
00665 template<class T> inline
00666 const ArrayRCP<T>&
00667 ArrayRCP<T>::assert_not_null() const
00668 {
00669   if(!ptr_)
00670     throw_null_ptr_error(typeName(*this));
00671   return *this;
00672 }
00673 
00674 
00675 template<class T> inline
00676 const ArrayRCP<T>& ArrayRCP<T>::assert_valid_ptr() const
00677 {
00678   if (ptr_)
00679     node_.assert_valid_ptr(*this);
00680   return *this;
00681 }
00682 
00683 
00684 template<class T> inline
00685 const ArrayRCP<T>&
00686 ArrayRCP<T>::assert_in_range( size_type lowerOffset_in, size_type size_in ) const
00687 {
00688   assert_not_null();
00689   TEUCHOS_TEST_FOR_EXCEPTION(
00690     !(
00691       (lowerOffset_ <= lowerOffset_in && lowerOffset_in+size_in-1 <= upperOffset_)
00692       &&
00693       size_in >= 0
00694       ),
00695     Teuchos::RangeError,
00696     typeName(*this)<<"::assert_in_range:"
00697     " Error, [lowerOffset,lowerOffset+size-1] = ["
00698     <<lowerOffset_in<<","<<(lowerOffset_in+size_in-1)<<"] does not lie in the"
00699     " range ["<<lowerOffset_<<","<<upperOffset_<<"]!"
00700     );
00701   return *this;
00702 }
00703 
00704 
00705 // Deprecated
00706 
00707 
00708 template<class T> inline
00709 int ArrayRCP<T>::count() const {
00710   return node_.count();
00711 }
00712 
00713 
00714 // very bad public functions
00715 
00716 
00717 template<class T> inline
00718 ArrayRCP<T>::ArrayRCP(
00719   T* p, size_type lowerOffset_in, size_type size_in,
00720   const RCPNodeHandle& node
00721   )
00722   :ptr_(p),
00723    node_(node),
00724    lowerOffset_(lowerOffset_in),
00725    upperOffset_(size_in + lowerOffset_in - 1)
00726 {}
00727 
00728 
00729 template<class T> inline
00730 T* ArrayRCP<T>::access_private_ptr() const
00731 {
00732   return ptr_;
00733 }
00734 
00735 
00736 template<class T> inline
00737 RCPNodeHandle& ArrayRCP<T>::nonconst_access_private_node()
00738 {
00739   return node_;
00740 }
00741 
00742 
00743 template<class T> inline
00744 const RCPNodeHandle& ArrayRCP<T>::access_private_node() const
00745 {
00746   return node_;
00747 }
00748 
00749 // Array<void> and Array<const void> specializations
00750 
00751 
00752 ArrayRCP<void>::ArrayRCP()
00753 {
00754   TEUCHOS_TEST_FOR_EXCEPT(true);
00755 }
00756 
00757 
00758 ArrayRCP<const void>::ArrayRCP()
00759 {
00760   TEUCHOS_TEST_FOR_EXCEPT(true);
00761 }
00762 
00763 
00764 }  // end namespace Teuchos
00765 
00766 
00767 // ///////////////////////////////////////////
00768 // Non-member functions for ArrayRCP
00769 
00770 
00771 namespace Teuchos {
00772 namespace Utilities {
00773 template<class T1, class T2>
00774 inline void assert_shares_resource(
00775   const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2
00776   )
00777 {
00778 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00779   TEUCHOS_TEST_FOR_EXCEPTION(
00780     !p1.shares_resource(p2), IncompatibleIteratorsError,
00781     "Error, these iterators are *not* pointing to the same valid memory!"
00782     );
00783 #endif
00784 }
00785 } // namespace Utilities
00786 } // namespace Teuchos
00787 
00788 
00789 template<class T> inline
00790 Teuchos::ArrayRCP<T>
00791 Teuchos::arcp(
00792 T* p, typename ArrayRCP<T>::size_type lowerOffset
00793   ,typename ArrayRCP<T>::size_type size_in
00794   ,bool owns_mem
00795   )
00796 {
00797   return ArrayRCP<T>(p, lowerOffset, size_in, owns_mem);
00798 }
00799 
00800 
00801 template<class T, class Dealloc_T>
00802 inline
00803 Teuchos::ArrayRCP<T>
00804 Teuchos::arcp(
00805 T* p, typename ArrayRCP<T>::size_type lowerOffset
00806   ,typename ArrayRCP<T>::size_type size_in
00807   ,Dealloc_T dealloc, bool owns_mem
00808   )
00809 {
00810   return ArrayRCP<T>(p, lowerOffset, size_in, dealloc, owns_mem);
00811 }
00812 
00813 
00814 template<class T> inline
00815 Teuchos::ArrayRCP<T>
00816 Teuchos::arcp( typename ArrayRCP<T>::size_type size )
00817 {
00818 #ifdef TEUCHOS_DEBUG
00819   TEUCHOS_ASSERT_INEQUALITY( size, >=, 0 );
00820 #endif
00821   if (size == 0) {
00822     return null;
00823   }
00824   return ArrayRCP<T>(new T[size], 0, size, true);
00825 }
00826 
00827 
00828 template<class T> inline
00829 Teuchos::ArrayRCP<T>
00830 Teuchos::arcpCloneNode(const ArrayRCP<T> &a)
00831 {
00832   if (is_null(a)) {
00833     return null;
00834   }
00835   return arcpWithEmbeddedObj(a.getRawPtr(), a.lowerOffset(), a.size(),
00836     a, false);
00837 }
00838 
00839 
00840 template<class T> inline
00841 Teuchos::ArrayRCP<T>
00842 Teuchos::arcpClone( const ArrayView<const T> &v )
00843 {
00844   const ArrayRCP<T> new_arcp = arcp<T>(v.size());
00845   std::copy( v.begin(), v.end(), new_arcp.begin() );
00846   return new_arcp;
00847 }
00848 
00849 
00850 template<class T, class Embedded>
00851 Teuchos::ArrayRCP<T>
00852 Teuchos::arcpWithEmbeddedObjPreDestroy(
00853   T* p,
00854   typename ArrayRCP<T>::size_type lowerOffset,
00855   typename ArrayRCP<T>::size_type size,
00856   const Embedded &embedded,
00857   bool owns_mem
00858   )
00859 {
00860   return arcp(
00861     p, lowerOffset, size,
00862     embeddedObjDeallocArrayDelete<T>(embedded, PRE_DESTROY),
00863     owns_mem
00864     );
00865 }
00866 
00867 
00868 template<class T, class Embedded>
00869 Teuchos::ArrayRCP<T>
00870 Teuchos::arcpWithEmbeddedObjPostDestroy(
00871   T* p,
00872   typename ArrayRCP<T>::size_type lowerOffset,
00873   typename ArrayRCP<T>::size_type size,
00874   const Embedded &embedded,
00875   bool owns_mem
00876   )
00877 {
00878   return arcp(
00879     p, lowerOffset, size,
00880     embeddedObjDeallocArrayDelete<T>(embedded, POST_DESTROY),
00881     owns_mem
00882     );
00883 }
00884 
00885 
00886 template<class T, class Embedded>
00887 Teuchos::ArrayRCP<T>
00888 Teuchos::arcpWithEmbeddedObj(
00889   T* p,
00890   typename ArrayRCP<T>::size_type lowerOffset,
00891   typename ArrayRCP<T>::size_type size,
00892   const Embedded &embedded,
00893   bool owns_mem
00894   )
00895 {
00896   return arcpWithEmbeddedObjPostDestroy<T,Embedded>(
00897     p, lowerOffset, size, embedded, owns_mem );
00898 }
00899 
00900 
00901 template<class T> inline
00902 Teuchos::ArrayRCP<T>
00903 Teuchos::arcp( const RCP<std::vector<T> > &v )
00904 {
00905   if ( is_null(v) || !v->size() )
00906     return null;
00907   return arcpWithEmbeddedObjPostDestroy<T,RCP<std::vector<T> > >(
00908     &(*v)[0], 0, v->size(),
00909     v, false
00910     );
00911 }
00912 
00913 
00914 template<class T> inline
00915 Teuchos::ArrayRCP<const T>
00916 Teuchos::arcp( const RCP<const std::vector<T> > &v )
00917 {
00918   if ( is_null(v) || !v->size() )
00919     return null;
00920   return arcpWithEmbeddedObjPostDestroy<const T,RCP<const std::vector<T> > >(
00921     &(*v)[0], 0, v->size(),
00922     v, false
00923     );
00924 }
00925 
00926 
00927 template<class T> inline
00928 Teuchos::ArrayRCP<T>
00929 Teuchos::arcpFromArrayView(const ArrayView<T> &av)
00930 {
00931 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00932   return av.access_private_arcp();
00933 #else
00934   return arcp(av.getRawPtr(), 0, av.size(), false);
00935 #endif  
00936 }
00937 
00938 
00939 template<class T> inline
00940 Teuchos::RCP<std::vector<T> >
00941 Teuchos::get_std_vector( const ArrayRCP<T> &ptr )
00942 {
00943   return getEmbeddedObj<T, RCP<std::vector<T> > >(ptr);
00944 }
00945 
00946 
00947 template<class T> inline
00948 Teuchos::RCP<const std::vector<T> >
00949 Teuchos::get_std_vector( const ArrayRCP<const T> &ptr )
00950 {
00951   return getEmbeddedObj<const T, RCP<const std::vector<T> > >(ptr);
00952 }
00953 
00954 
00955 template<class T> inline
00956 bool Teuchos::is_null( const ArrayRCP<T> &p )
00957 {
00958   return p.is_null();
00959 }
00960 
00961 
00962 template<class T> inline
00963 bool Teuchos::nonnull( const ArrayRCP<T> &p )
00964 {
00965   return !p.is_null();
00966 }
00967 
00968 
00969 template<class T> inline
00970 bool Teuchos::operator==( const ArrayRCP<T> &p, ENull )
00971 {
00972   return p.is_null();
00973 }
00974 
00975 
00976 template<class T> inline
00977 bool Teuchos::operator!=( const ArrayRCP<T> &p, ENull )
00978 {
00979   return !p.is_null();
00980 }
00981 
00982 
00983 template<class T1, class T2>
00984 inline
00985 bool Teuchos::operator==( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
00986 {
00987   return p1.access_private_ptr() == p2.access_private_ptr();
00988 }
00989 
00990 
00991 template<class T1, class T2>
00992 inline
00993 bool Teuchos::operator!=( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
00994 {
00995   return p1.access_private_ptr() != p2.access_private_ptr();
00996 }
00997 
00998 
00999 template<class T1, class T2>
01000 inline
01001 bool Teuchos::operator<( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01002 {
01003   return p1.access_private_ptr() < p2.access_private_ptr();
01004 }
01005 
01006 
01007 template<class T1, class T2>
01008 inline
01009 bool Teuchos::operator<=( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01010 {
01011   Utilities::assert_shares_resource(p1,p2);
01012   return p1.access_private_ptr() <= p2.access_private_ptr();
01013 }
01014 
01015 
01016 template<class T1, class T2>
01017 inline
01018 bool Teuchos::operator>( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01019 {
01020   Utilities::assert_shares_resource(p1,p2);
01021   return p1.access_private_ptr() > p2.access_private_ptr();
01022 }
01023 
01024 
01025 template<class T1, class T2>
01026 inline
01027 bool Teuchos::operator>=( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01028 {
01029   Utilities::assert_shares_resource(p1,p2);
01030   return p1.access_private_ptr() >= p2.access_private_ptr();
01031 }
01032 
01033 
01034 template<class T>
01035 typename Teuchos::ArrayRCP<T>::difference_type
01036 Teuchos::operator-( const ArrayRCP<T> &p1, const ArrayRCP<T> &p2 )
01037 {
01038   Utilities::assert_shares_resource(p1,p2);
01039   return p1.access_private_ptr() - p2.access_private_ptr();
01040 }
01041 
01042 
01043 template<class T2, class T1>
01044 inline
01045 Teuchos::ArrayRCP<T2>
01046 Teuchos::arcp_reinterpret_cast(const ArrayRCP<T1>& p1)
01047 {
01048   typedef typename ArrayRCP<T1>::size_type size_type;
01049   const int sizeOfT1 = sizeof(T1);
01050   const int sizeOfT2 = sizeof(T2);
01051   size_type lowerOffset2 = (p1.lowerOffset()*sizeOfT1) / sizeOfT2;
01052   size_type upperOffset2 = ((p1.upperOffset()+1)*sizeOfT1) / sizeOfT2 - 1;
01053   T2 *ptr2 = reinterpret_cast<T2*>(p1.get());
01054   return ArrayRCP<T2>(
01055     ptr2, lowerOffset2, upperOffset2 - lowerOffset2 + 1,
01056     p1.access_private_node()
01057     );
01058   // Note: Above is just fine even if p1.get()==NULL!
01059 }
01060 
01061 
01062 template<class T2, class T1>
01063 Teuchos::ArrayRCP<T2>
01064 Teuchos::arcp_reinterpret_cast_nonpod(const ArrayRCP<T1>& p1, const T2& val)
01065 {
01066   typedef typename ArrayRCP<T2>::iterator itr_t;
01067   ArrayRCP<T2> arcp2 = arcp_reinterpret_cast<T2>(p1);
01068   for (itr_t itr = arcp2.begin(); itr != arcp2.end(); ++itr) {
01069     new (&*itr) T2(val);
01070   }
01071   return arcpWithEmbeddedObj(
01072     arcp2.getRawPtr(), 0, arcp2.size(),
01073     ArcpReinterpretCastEmbeddedObj<T2, T1>(p1),
01074     false);
01075   // Above, the ownership of the memory is totally owned by the embedded
01076   // object and the default deallocator policy object does not do anything.
01077   // This is just fine.
01078 }
01079 
01080 
01081 template<class T2, class T1>
01082 inline
01083 Teuchos::ArrayRCP<T2>
01084 Teuchos::arcp_const_cast(const ArrayRCP<T1>& p1)
01085 {
01086   typedef typename ArrayRCP<T1>::size_type size_type;
01087   T2 *ptr2 = const_cast<T2*>(p1.get());
01088   return ArrayRCP<T2>(
01089     ptr2, p1.lowerOffset(), p1.size(),
01090     p1.access_private_node()
01091     );
01092   // Note: Above is just fine even if p1.get()==NULL!
01093 }
01094 
01095 
01096 template<class T2, class T1>
01097 inline
01098 Teuchos::ArrayRCP<T2>
01099 Teuchos::arcp_implicit_cast(const ArrayRCP<T1>& p1)
01100 {
01101   typedef typename ArrayRCP<T1>::size_type size_type;
01102   T2 * raw_ptr2 = p1.get();
01103   return ArrayRCP<T2>(
01104     raw_ptr2, p1.lowerOffset(), p1.size(),
01105     p1.access_private_node()
01106     );
01107   // Note: Above is just fine even if p1.get()==NULL!
01108 }
01109 
01110 
01111 template<class T1, class T2>
01112 inline
01113 void Teuchos::set_extra_data(
01114   const T1 &extra_data, const std::string& name,
01115   const Ptr<ArrayRCP<T2> > &p, EPrePostDestruction destroy_when,
01116   bool force_unique
01117   )
01118 {
01119   p->assert_not_null();
01120   p->nonconst_access_private_node().set_extra_data( any(extra_data), name, destroy_when,
01121     force_unique );
01122 }
01123 
01124 
01125 template<class T1, class T2>
01126 inline
01127 T1& Teuchos::get_extra_data( ArrayRCP<T2>& p, const std::string& name )
01128 {
01129   p.assert_not_null();
01130   return any_cast<T1>(
01131     p.nonconst_access_private_node().get_extra_data(
01132       TypeNameTraits<T1>::name(), name
01133       )
01134     );
01135 }
01136 
01137 
01138 template<class T1, class T2>
01139 inline
01140 const T1& Teuchos::get_extra_data( const ArrayRCP<T2>& p, const std::string& name )
01141 {
01142   p.assert_not_null();
01143   return any_cast<T1>(
01144     p.access_private_node().get_extra_data(
01145       TypeNameTraits<T1>::name() ,name
01146       )
01147     );
01148 }
01149 
01150 
01151 template<class T1, class T2>
01152 inline
01153 T1* Teuchos::get_optional_extra_data( ArrayRCP<T2>& p, const std::string& name )
01154 {
01155   p.assert_not_null();
01156   any *extra_data = p.nonconst_access_private_node().get_optional_extra_data(
01157     TypeNameTraits<T1>::name(), name);
01158   if( extra_data ) return &any_cast<T1>(*extra_data);
01159   return NULL;
01160 }
01161 
01162 
01163 template<class T1, class T2>
01164 inline
01165 const T1* Teuchos::get_optional_extra_data( const ArrayRCP<T2>& p, const std::string& name )
01166 {
01167   p.assert_not_null();
01168   any *extra_data = p.access_private_node().get_optional_extra_data(
01169     TypeNameTraits<T1>::name(), name);
01170   if( extra_data ) return &any_cast<T1>(*extra_data);
01171   return NULL;
01172 }
01173 
01174 
01175 template<class Dealloc_T, class T>
01176 inline
01177 const Dealloc_T&
01178 Teuchos::get_dealloc( const ArrayRCP<T>& p )
01179 {
01180   return get_nonconst_dealloc<Dealloc_T>(p);
01181 }
01182 
01183 
01184 template<class Dealloc_T, class T>
01185 inline
01186 Dealloc_T& 
01187 Teuchos::get_nonconst_dealloc( const Teuchos::ArrayRCP<T>& p )
01188 {
01189   typedef RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>  requested_type;
01190   p.assert_not_null();
01191   RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>
01192     *dnode = dynamic_cast<RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>*>(
01193       p.access_private_node().node_ptr());
01194   TEUCHOS_TEST_FOR_EXCEPTION(
01195     dnode==NULL, NullReferenceError
01196     ,"get_dealloc<" << TypeNameTraits<Dealloc_T>::name()
01197     << "," << TypeNameTraits<T>::name() << ">(p): "
01198     << "Error, requested type \'" << TypeNameTraits<requested_type>::name()
01199     << "\' does not match actual type of the node \'"
01200     << typeName(*p.access_private_node().node_ptr()) << "!"
01201     );
01202   return dnode->get_nonconst_dealloc();
01203 }
01204 
01205 
01206 template<class Dealloc_T, class T>
01207 inline
01208 const Dealloc_T*
01209 Teuchos::get_optional_dealloc( const ArrayRCP<T>& p )
01210 {
01211   return get_optional_dealloc<Dealloc_T>(p);
01212 }
01213 
01214 
01215 template<class Dealloc_T, class T>
01216 inline
01217 Dealloc_T*
01218 Teuchos::get_optional_nonconst_dealloc( const Teuchos::ArrayRCP<T>& p )
01219 {
01220   p.assert_not_null();
01221   typedef RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>
01222     RCPNT;
01223   RCPNT *dnode = dynamic_cast<RCPNT*>(p.access_private_node().node_ptr());
01224   if (dnode)
01225     return &dnode->get_nonconst_dealloc();
01226   return 0;
01227 }
01228 
01229 
01230 template<class TOrig, class Embedded, class T>
01231 const Embedded& Teuchos::getEmbeddedObj( const ArrayRCP<T>& p )
01232 {
01233   typedef EmbeddedObjDealloc<TOrig,Embedded,DeallocArrayDelete<TOrig> > Dealloc_t;
01234   return get_dealloc<Dealloc_t>(p).getObj();
01235 }
01236 
01237 
01238 template<class TOrig, class Embedded, class T>
01239 Embedded& Teuchos::getNonconstEmbeddedObj( const ArrayRCP<T>& p )
01240 {
01241   typedef EmbeddedObjDealloc<TOrig,Embedded,DeallocArrayDelete<TOrig> > Dealloc_t;
01242   return get_nonconst_dealloc<Dealloc_t>(p).getNonconstObj();
01243 }
01244 
01245 
01246 template<class T>
01247 std::ostream& Teuchos::operator<<( std::ostream& out, const ArrayRCP<T>& p )
01248 {
01249   out
01250     << TypeNameTraits<ArrayRCP<T> >::name() << "{"
01251     << "ptr="<<(const void*)(p.access_private_ptr())
01252     <<",lowerOffset="<<p.lowerOffset()
01253     <<",upperOffset="<<p.upperOffset()
01254     <<",size="<<p.size()
01255     <<",node="<<p.access_private_node()
01256     <<",strong_count="<<p.strong_count()
01257     <<",weak_count="<<p.weak_count()
01258     <<"}";
01259   return out;
01260   // NOTES:
01261   // * I can't find any alternative to this C cast (problems with char data)
01262   // * Don't range check the pointer since this code does not dereference it.
01263   //   This is needed to allow printing the end() or past end() for debugging.
01264 }
01265 
01266 
01267 #endif // TEUCHOS_ARRAY_RCP_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines