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