Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Teuchos_ArrayRCP.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // 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 ArrayView<T>() const
00496 {
00497   return this->operator()();
00498 }
00499 
00500 
00501 template<class T> inline
00502 ArrayRCP<T>::operator ArrayRCP<const T>() const
00503 {
00504   if (size()) {
00505     return ArrayRCP<const T>(ptr_, lowerOffset_, size(), node_);
00506   }
00507   return null;
00508 }
00509 
00510 
00511 // std::vector like functions
00512 
00513 
00514 template<class T> inline
00515 void ArrayRCP<T>::assign(size_type n, const T &val)
00516 {
00517   *this = arcp<T>(n);
00518   std::fill_n(this->begin(), n, val);
00519 }
00520 
00521 
00522 template<class T>
00523 template<class Iter>
00524 inline
00525 void ArrayRCP<T>::assign(Iter first, Iter last)
00526 {
00527   const size_type new_n = std::distance(first, last);
00528   if (new_n != size())
00529     *this = arcp<T>(new_n);
00530   std::copy( first, last, begin() );
00531 }
00532 
00533 
00534 template<class T> inline
00535 void ArrayRCP<T>::resize(const size_type n, const T &val)
00536 {
00537 #ifdef TEUCHOS_DEBUG
00538   TEUCHOS_ASSERT_EQUALITY(lowerOffset(), 0);
00539 #endif
00540   if (n == 0) {
00541     clear();
00542     return;
00543   }
00544   const size_type orig_n = size();
00545   if (n != orig_n) {
00546     ArrayRCP<T> tmp = *this;
00547     *this = arcp<T>(n);
00548     const size_type small_n = std::min(n, orig_n);
00549     for (size_type i = 0; i < small_n; ++i)
00550       (*this)[i] = tmp[i];
00551     for (size_type i = orig_n; i < n; ++i)
00552       (*this)[i] = val;
00553     upperOffset_ = n-1;
00554   }
00555 }
00556 
00557 
00558 template<class T> inline
00559 void ArrayRCP<T>::clear()
00560 {
00561   *this = null;
00562 }
00563 
00564 
00565 // Misc functions
00566 
00567 template<class T> inline
00568 void ArrayRCP<T>::deepCopy(const ArrayView<const T>& av)
00569 {
00570   if (av.size() == 0) {
00571     *this = null;
00572     return;
00573   }
00574   assign(av.begin(), av.end());
00575 }
00576 
00577 
00578 // Reference counting
00579 
00580 
00581 template<class T> inline
00582 ERCPStrength ArrayRCP<T>::strength() const
00583 {
00584   return node_.strength();
00585 }
00586 
00587 
00588 template<class T> inline
00589 bool ArrayRCP<T>::is_valid_ptr() const
00590 {
00591   if (ptr_)
00592     return node_.is_valid_ptr();
00593   return true;
00594 }
00595 
00596 
00597 template<class T> inline
00598 int ArrayRCP<T>::strong_count() const
00599 {
00600   return node_.strong_count();
00601 }
00602 
00603 
00604 template<class T> inline
00605 int ArrayRCP<T>::weak_count() const
00606 {
00607   return node_.weak_count();
00608 }
00609 
00610 
00611 template<class T> inline
00612 int ArrayRCP<T>::total_count() const
00613 {
00614   return node_.total_count();
00615 }
00616 
00617 
00618 template<class T> inline
00619 void ArrayRCP<T>::set_has_ownership()
00620 {
00621   node_.has_ownership(true);
00622 }
00623 
00624 
00625 template<class T> inline
00626 bool ArrayRCP<T>::has_ownership() const
00627 {
00628   return node_.has_ownership();
00629 }
00630 
00631 
00632 template<class T> inline
00633 T* ArrayRCP<T>::release()
00634 {
00635   debug_assert_valid_ptr();
00636   node_.has_ownership(false);
00637   return ptr_;
00638 }
00639 
00640 
00641 template<class T> inline
00642 ArrayRCP<T> ArrayRCP<T>::create_weak() const
00643 {
00644   debug_assert_valid_ptr();
00645   return ArrayRCP<T>(ptr_, lowerOffset_, size(), node_.create_weak());
00646 }
00647 
00648 
00649 template<class T> inline
00650 ArrayRCP<T> ArrayRCP<T>::create_strong() const
00651 {
00652   debug_assert_valid_ptr();
00653   return ArrayRCP<T>(ptr_, lowerOffset_, size(), node_.create_strong());
00654 }
00655 
00656 
00657 template<class T>
00658 template <class T2>
00659 inline
00660 bool ArrayRCP<T>::shares_resource(const ArrayRCP<T2>& r_ptr) const
00661 {
00662   return node_.same_node(r_ptr.access_private_node());
00663   // Note: above, r_ptr is *not* the same class type as *this so we can not
00664   // access its node_ member directly!  This is an interesting detail to the
00665   // C++ protected/private protection mechanism!
00666 }
00667 
00668 
00669 // Assertion Functions
00670 
00671 
00672 template<class T> inline
00673 const ArrayRCP<T>&
00674 ArrayRCP<T>::assert_not_null() const
00675 {
00676   if(!ptr_)
00677     throw_null_ptr_error(typeName(*this));
00678   return *this;
00679 }
00680 
00681 
00682 template<class T> inline
00683 const ArrayRCP<T>& ArrayRCP<T>::assert_valid_ptr() const
00684 {
00685   if (ptr_)
00686     node_.assert_valid_ptr(*this);
00687   return *this;
00688 }
00689 
00690 
00691 template<class T> inline
00692 const ArrayRCP<T>&
00693 ArrayRCP<T>::assert_in_range( size_type lowerOffset_in, size_type size_in ) const
00694 {
00695   assert_not_null();
00696   TEUCHOS_TEST_FOR_EXCEPTION(
00697     !(
00698       (lowerOffset_ <= lowerOffset_in && lowerOffset_in+size_in-1 <= upperOffset_)
00699       &&
00700       size_in >= 0
00701       ),
00702     Teuchos::RangeError,
00703     typeName(*this)<<"::assert_in_range:"
00704     " Error, [lowerOffset,lowerOffset+size-1] = ["
00705     <<lowerOffset_in<<","<<(lowerOffset_in+size_in-1)<<"] does not lie in the"
00706     " range ["<<lowerOffset_<<","<<upperOffset_<<"]!"
00707     );
00708   return *this;
00709 }
00710 
00711 
00712 // Deprecated
00713 
00714 
00715 template<class T> inline
00716 int ArrayRCP<T>::count() const {
00717   return node_.count();
00718 }
00719 
00720 
00721 // very bad public functions
00722 
00723 
00724 template<class T> inline
00725 ArrayRCP<T>::ArrayRCP(
00726   T* p, size_type lowerOffset_in, size_type size_in,
00727   const RCPNodeHandle& node
00728   )
00729   :ptr_(p),
00730    node_(node),
00731    lowerOffset_(lowerOffset_in),
00732    upperOffset_(size_in + lowerOffset_in - 1)
00733 {}
00734 
00735 
00736 template<class T> inline
00737 T* ArrayRCP<T>::access_private_ptr() const
00738 {
00739   return ptr_;
00740 }
00741 
00742 
00743 template<class T> inline
00744 RCPNodeHandle& ArrayRCP<T>::nonconst_access_private_node()
00745 {
00746   return node_;
00747 }
00748 
00749 
00750 template<class T> inline
00751 const RCPNodeHandle& ArrayRCP<T>::access_private_node() const
00752 {
00753   return node_;
00754 }
00755 
00756 // Array<void> and Array<const void> specializations
00757 
00758 
00759 ArrayRCP<void>::ArrayRCP()
00760 {
00761   TEUCHOS_TEST_FOR_EXCEPT(true);
00762 }
00763 
00764 
00765 ArrayRCP<const void>::ArrayRCP()
00766 {
00767   TEUCHOS_TEST_FOR_EXCEPT(true);
00768 }
00769 
00770 
00771 }  // end namespace Teuchos
00772 
00773 
00774 // ///////////////////////////////////////////
00775 // Non-member functions for ArrayRCP
00776 
00777 
00778 namespace Teuchos {
00779 namespace Utilities {
00780 template<class T1, class T2>
00781 inline void assert_shares_resource(
00782   const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2
00783   )
00784 {
00785 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00786   TEUCHOS_TEST_FOR_EXCEPTION(
00787     !p1.shares_resource(p2), IncompatibleIteratorsError,
00788     "Error, these iterators are *not* pointing to the same valid memory!"
00789     );
00790 #endif
00791 }
00792 } // namespace Utilities
00793 } // namespace Teuchos
00794 
00795 
00796 template<class T> inline
00797 Teuchos::ArrayRCP<T>
00798 Teuchos::arcp(
00799 T* p, typename ArrayRCP<T>::size_type lowerOffset
00800   ,typename ArrayRCP<T>::size_type size_in
00801   ,bool owns_mem
00802   )
00803 {
00804   return ArrayRCP<T>(p, lowerOffset, size_in, owns_mem);
00805 }
00806 
00807 
00808 template<class T, class Dealloc_T>
00809 inline
00810 Teuchos::ArrayRCP<T>
00811 Teuchos::arcp(
00812 T* p, typename ArrayRCP<T>::size_type lowerOffset
00813   ,typename ArrayRCP<T>::size_type size_in
00814   ,Dealloc_T dealloc, bool owns_mem
00815   )
00816 {
00817   return ArrayRCP<T>(p, lowerOffset, size_in, dealloc, owns_mem);
00818 }
00819 
00820 
00821 template<class T> inline
00822 Teuchos::ArrayRCP<T>
00823 Teuchos::arcp( typename ArrayRCP<T>::size_type size )
00824 {
00825 #ifdef TEUCHOS_DEBUG
00826   TEUCHOS_ASSERT_INEQUALITY( size, >=, 0 );
00827 #endif
00828   if (size == 0) {
00829     return null;
00830   }
00831   return ArrayRCP<T>(new T[size], 0, size, true);
00832 }
00833 
00834 
00835 template<class T> inline
00836 Teuchos::ArrayRCP<T>
00837 Teuchos::arcpCloneNode(const ArrayRCP<T> &a)
00838 {
00839   if (is_null(a)) {
00840     return null;
00841   }
00842   return arcpWithEmbeddedObj(a.getRawPtr(), a.lowerOffset(), a.size(),
00843     a, false);
00844 }
00845 
00846 
00847 template<class T> inline
00848 Teuchos::ArrayRCP<T>
00849 Teuchos::arcpClone( const ArrayView<const T> &v )
00850 {
00851   const ArrayRCP<T> new_arcp = arcp<T>(v.size());
00852   std::copy( v.begin(), v.end(), new_arcp.begin() );
00853   return new_arcp;
00854 }
00855 
00856 
00857 template<class T, class Embedded>
00858 Teuchos::ArrayRCP<T>
00859 Teuchos::arcpWithEmbeddedObjPreDestroy(
00860   T* p,
00861   typename ArrayRCP<T>::size_type lowerOffset,
00862   typename ArrayRCP<T>::size_type size,
00863   const Embedded &embedded,
00864   bool owns_mem
00865   )
00866 {
00867   return arcp(
00868     p, lowerOffset, size,
00869     embeddedObjDeallocArrayDelete<T>(embedded, PRE_DESTROY),
00870     owns_mem
00871     );
00872 }
00873 
00874 
00875 template<class T, class Embedded>
00876 Teuchos::ArrayRCP<T>
00877 Teuchos::arcpWithEmbeddedObjPostDestroy(
00878   T* p,
00879   typename ArrayRCP<T>::size_type lowerOffset,
00880   typename ArrayRCP<T>::size_type size,
00881   const Embedded &embedded,
00882   bool owns_mem
00883   )
00884 {
00885   return arcp(
00886     p, lowerOffset, size,
00887     embeddedObjDeallocArrayDelete<T>(embedded, POST_DESTROY),
00888     owns_mem
00889     );
00890 }
00891 
00892 
00893 template<class T, class Embedded>
00894 Teuchos::ArrayRCP<T>
00895 Teuchos::arcpWithEmbeddedObj(
00896   T* p,
00897   typename ArrayRCP<T>::size_type lowerOffset,
00898   typename ArrayRCP<T>::size_type size,
00899   const Embedded &embedded,
00900   bool owns_mem
00901   )
00902 {
00903   return arcpWithEmbeddedObjPostDestroy<T,Embedded>(
00904     p, lowerOffset, size, embedded, owns_mem );
00905 }
00906 
00907 
00908 template<class T> inline
00909 Teuchos::ArrayRCP<T>
00910 Teuchos::arcp( const RCP<std::vector<T> > &v )
00911 {
00912   if ( is_null(v) || !v->size() )
00913     return null;
00914   return arcpWithEmbeddedObjPostDestroy<T,RCP<std::vector<T> > >(
00915     &(*v)[0], 0, v->size(),
00916     v, false
00917     );
00918 }
00919 
00920 
00921 template<class T> inline
00922 Teuchos::ArrayRCP<const T>
00923 Teuchos::arcp( const RCP<const std::vector<T> > &v )
00924 {
00925   if ( is_null(v) || !v->size() )
00926     return null;
00927   return arcpWithEmbeddedObjPostDestroy<const T,RCP<const std::vector<T> > >(
00928     &(*v)[0], 0, v->size(),
00929     v, false
00930     );
00931 }
00932 
00933 
00934 template<class T> inline
00935 Teuchos::ArrayRCP<T>
00936 Teuchos::arcpFromArrayView(const ArrayView<T> &av)
00937 {
00938 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00939   return av.access_private_arcp();
00940 #else
00941   return arcp(av.getRawPtr(), 0, av.size(), false);
00942 #endif  
00943 }
00944 
00945 
00946 template<class T> inline
00947 Teuchos::RCP<std::vector<T> >
00948 Teuchos::get_std_vector( const ArrayRCP<T> &ptr )
00949 {
00950   return getEmbeddedObj<T, RCP<std::vector<T> > >(ptr);
00951 }
00952 
00953 
00954 template<class T> inline
00955 Teuchos::RCP<const std::vector<T> >
00956 Teuchos::get_std_vector( const ArrayRCP<const T> &ptr )
00957 {
00958   return getEmbeddedObj<const T, RCP<const std::vector<T> > >(ptr);
00959 }
00960 
00961 
00962 template<class T> inline
00963 bool Teuchos::is_null( const ArrayRCP<T> &p )
00964 {
00965   return p.is_null();
00966 }
00967 
00968 
00969 template<class T> inline
00970 bool Teuchos::nonnull( const ArrayRCP<T> &p )
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 T> inline
00984 bool Teuchos::operator!=( const ArrayRCP<T> &p, ENull )
00985 {
00986   return !p.is_null();
00987 }
00988 
00989 
00990 template<class T1, class T2>
00991 inline
00992 bool Teuchos::operator==( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
00993 {
00994   return p1.access_private_ptr() == p2.access_private_ptr();
00995 }
00996 
00997 
00998 template<class T1, class T2>
00999 inline
01000 bool Teuchos::operator!=( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01001 {
01002   return p1.access_private_ptr() != p2.access_private_ptr();
01003 }
01004 
01005 
01006 template<class T1, class T2>
01007 inline
01008 bool Teuchos::operator<( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01009 {
01010   return p1.access_private_ptr() < p2.access_private_ptr();
01011 }
01012 
01013 
01014 template<class T1, class T2>
01015 inline
01016 bool Teuchos::operator<=( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01017 {
01018   Utilities::assert_shares_resource(p1,p2);
01019   return p1.access_private_ptr() <= p2.access_private_ptr();
01020 }
01021 
01022 
01023 template<class T1, class T2>
01024 inline
01025 bool Teuchos::operator>( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01026 {
01027   Utilities::assert_shares_resource(p1,p2);
01028   return p1.access_private_ptr() > p2.access_private_ptr();
01029 }
01030 
01031 
01032 template<class T1, class T2>
01033 inline
01034 bool Teuchos::operator>=( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01035 {
01036   Utilities::assert_shares_resource(p1,p2);
01037   return p1.access_private_ptr() >= p2.access_private_ptr();
01038 }
01039 
01040 
01041 template<class T>
01042 typename Teuchos::ArrayRCP<T>::difference_type
01043 Teuchos::operator-( const ArrayRCP<T> &p1, const ArrayRCP<T> &p2 )
01044 {
01045   Utilities::assert_shares_resource(p1,p2);
01046   return p1.access_private_ptr() - p2.access_private_ptr();
01047 }
01048 
01049 
01050 template<class T2, class T1>
01051 inline
01052 Teuchos::ArrayRCP<T2>
01053 Teuchos::arcp_reinterpret_cast(const ArrayRCP<T1>& p1)
01054 {
01055   typedef typename ArrayRCP<T1>::size_type size_type;
01056   const int sizeOfT1 = sizeof(T1);
01057   const int sizeOfT2 = sizeof(T2);
01058   size_type lowerOffset2 = (p1.lowerOffset()*sizeOfT1) / sizeOfT2;
01059   size_type upperOffset2 = ((p1.upperOffset()+1)*sizeOfT1) / sizeOfT2 - 1;
01060   T2 *ptr2 = reinterpret_cast<T2*>(p1.get());
01061   return ArrayRCP<T2>(
01062     ptr2, lowerOffset2, upperOffset2 - lowerOffset2 + 1,
01063     p1.access_private_node()
01064     );
01065   // Note: Above is just fine even if p1.get()==NULL!
01066 }
01067 
01068 
01069 template<class T2, class T1>
01070 Teuchos::ArrayRCP<T2>
01071 Teuchos::arcp_reinterpret_cast_nonpod(const ArrayRCP<T1>& p1, const T2& val)
01072 {
01073   typedef typename ArrayRCP<T2>::iterator itr_t;
01074   ArrayRCP<T2> arcp2 = arcp_reinterpret_cast<T2>(p1);
01075   for (itr_t itr = arcp2.begin(); itr != arcp2.end(); ++itr) {
01076     new (&*itr) T2(val);
01077   }
01078   return arcpWithEmbeddedObj(
01079     arcp2.getRawPtr(), 0, arcp2.size(),
01080     ArcpReinterpretCastEmbeddedObj<T2, T1>(p1),
01081     false);
01082   // Above, the ownership of the memory is totally owned by the embedded
01083   // object and the default deallocator policy object does not do anything.
01084   // This is just fine.
01085 }
01086 
01087 
01088 template<class T2, class T1>
01089 inline
01090 Teuchos::ArrayRCP<T2>
01091 Teuchos::arcp_const_cast(const ArrayRCP<T1>& p1)
01092 {
01093   typedef typename ArrayRCP<T1>::size_type size_type;
01094   T2 *ptr2 = const_cast<T2*>(p1.get());
01095   return ArrayRCP<T2>(
01096     ptr2, p1.lowerOffset(), p1.size(),
01097     p1.access_private_node()
01098     );
01099   // Note: Above is just fine even if p1.get()==NULL!
01100 }
01101 
01102 
01103 template<class T2, class T1>
01104 inline
01105 Teuchos::ArrayRCP<T2>
01106 Teuchos::arcp_implicit_cast(const ArrayRCP<T1>& p1)
01107 {
01108   typedef typename ArrayRCP<T1>::size_type size_type;
01109   T2 * raw_ptr2 = p1.get();
01110   return ArrayRCP<T2>(
01111     raw_ptr2, p1.lowerOffset(), p1.size(),
01112     p1.access_private_node()
01113     );
01114   // Note: Above is just fine even if p1.get()==NULL!
01115 }
01116 
01117 
01118 template<class T1, class T2>
01119 inline
01120 void Teuchos::set_extra_data(
01121   const T1 &extra_data, const std::string& name,
01122   const Ptr<ArrayRCP<T2> > &p, EPrePostDestruction destroy_when,
01123   bool force_unique
01124   )
01125 {
01126   p->assert_not_null();
01127   p->nonconst_access_private_node().set_extra_data( any(extra_data), name, destroy_when,
01128     force_unique );
01129 }
01130 
01131 
01132 template<class T1, class T2>
01133 inline
01134 T1& Teuchos::get_extra_data( ArrayRCP<T2>& p, const std::string& name )
01135 {
01136   p.assert_not_null();
01137   return any_cast<T1>(
01138     p.nonconst_access_private_node().get_extra_data(
01139       TypeNameTraits<T1>::name(), name
01140       )
01141     );
01142 }
01143 
01144 
01145 template<class T1, class T2>
01146 inline
01147 const T1& Teuchos::get_extra_data( const ArrayRCP<T2>& p, const std::string& name )
01148 {
01149   p.assert_not_null();
01150   return any_cast<T1>(
01151     p.access_private_node().get_extra_data(
01152       TypeNameTraits<T1>::name() ,name
01153       )
01154     );
01155 }
01156 
01157 
01158 template<class T1, class T2>
01159 inline
01160 T1* Teuchos::get_optional_extra_data( ArrayRCP<T2>& p, const std::string& name )
01161 {
01162   p.assert_not_null();
01163   any *extra_data = p.nonconst_access_private_node().get_optional_extra_data(
01164     TypeNameTraits<T1>::name(), name);
01165   if( extra_data ) return &any_cast<T1>(*extra_data);
01166   return NULL;
01167 }
01168 
01169 
01170 template<class T1, class T2>
01171 inline
01172 const T1* Teuchos::get_optional_extra_data( const ArrayRCP<T2>& p, const std::string& name )
01173 {
01174   p.assert_not_null();
01175   any *extra_data = p.access_private_node().get_optional_extra_data(
01176     TypeNameTraits<T1>::name(), name);
01177   if( extra_data ) return &any_cast<T1>(*extra_data);
01178   return NULL;
01179 }
01180 
01181 
01182 template<class Dealloc_T, class T>
01183 inline
01184 const Dealloc_T&
01185 Teuchos::get_dealloc( const ArrayRCP<T>& p )
01186 {
01187   return get_nonconst_dealloc<Dealloc_T>(p);
01188 }
01189 
01190 
01191 template<class Dealloc_T, class T>
01192 inline
01193 Dealloc_T& 
01194 Teuchos::get_nonconst_dealloc( const Teuchos::ArrayRCP<T>& p )
01195 {
01196   typedef RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>  requested_type;
01197   p.assert_not_null();
01198   RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>
01199     *dnode = dynamic_cast<RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>*>(
01200       p.access_private_node().node_ptr());
01201   TEUCHOS_TEST_FOR_EXCEPTION(
01202     dnode==NULL, NullReferenceError
01203     ,"get_dealloc<" << TypeNameTraits<Dealloc_T>::name()
01204     << "," << TypeNameTraits<T>::name() << ">(p): "
01205     << "Error, requested type \'" << TypeNameTraits<requested_type>::name()
01206     << "\' does not match actual type of the node \'"
01207     << typeName(*p.access_private_node().node_ptr()) << "!"
01208     );
01209   return dnode->get_nonconst_dealloc();
01210 }
01211 
01212 
01213 template<class Dealloc_T, class T>
01214 inline
01215 const Dealloc_T*
01216 Teuchos::get_optional_dealloc( const ArrayRCP<T>& p )
01217 {
01218   return get_optional_dealloc<Dealloc_T>(p);
01219 }
01220 
01221 
01222 template<class Dealloc_T, class T>
01223 inline
01224 Dealloc_T*
01225 Teuchos::get_optional_nonconst_dealloc( const Teuchos::ArrayRCP<T>& p )
01226 {
01227   p.assert_not_null();
01228   typedef RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>
01229     RCPNT;
01230   RCPNT *dnode = dynamic_cast<RCPNT*>(p.access_private_node().node_ptr());
01231   if (dnode)
01232     return &dnode->get_nonconst_dealloc();
01233   return 0;
01234 }
01235 
01236 
01237 template<class TOrig, class Embedded, class T>
01238 const Embedded& Teuchos::getEmbeddedObj( const ArrayRCP<T>& p )
01239 {
01240   typedef EmbeddedObjDealloc<TOrig,Embedded,DeallocArrayDelete<TOrig> > Dealloc_t;
01241   return get_dealloc<Dealloc_t>(p).getObj();
01242 }
01243 
01244 
01245 template<class TOrig, class Embedded, class T>
01246 Embedded& Teuchos::getNonconstEmbeddedObj( const ArrayRCP<T>& p )
01247 {
01248   typedef EmbeddedObjDealloc<TOrig,Embedded,DeallocArrayDelete<TOrig> > Dealloc_t;
01249   return get_nonconst_dealloc<Dealloc_t>(p).getNonconstObj();
01250 }
01251 
01252 
01253 template<class T>
01254 std::ostream& Teuchos::operator<<( std::ostream& out, const ArrayRCP<T>& p )
01255 {
01256   out
01257     << TypeNameTraits<ArrayRCP<T> >::name() << "{"
01258     << "ptr="<<(const void*)(p.get()) // I can't find any alternative to this C cast :-(
01259     <<",lowerOffset="<<p.lowerOffset()
01260     <<",upperOffset="<<p.upperOffset()
01261     <<",size="<<p.size()
01262     <<",node="<<p.access_private_node()
01263     <<",count="<<p.count()
01264     <<"}";
01265   return out;
01266 }
01267 
01268 
01269 #endif // TEUCHOS_ARRAY_RCP_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines