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

Generated on Wed May 12 21:24:40 2010 for Teuchos - Trilinos Tools Package by  doxygen 1.4.7