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