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