Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Teuchos_ArrayRCP.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #ifndef TEUCHOS_ARRAY_RCP_HPP
00043 #define TEUCHOS_ARRAY_RCP_HPP
00044 
00045 
00046 #include "Teuchos_ArrayRCPDecl.hpp"
00047 #include "Teuchos_ArrayView.hpp"
00048 #include "Teuchos_Assert.hpp"
00049 #include "Teuchos_dyn_cast.hpp"
00050 #include "Teuchos_as.hpp"
00051 
00052 
00053 namespace Teuchos {
00054 
00055 
00056 // Helper code (not for general clients)
00057 
00058 
00059 template<class T> inline
00060 RCPNode* ArrayRCP_createNewRCPNodeRawPtr( T* p, bool has_ownership_in )
00061 {
00062   return new RCPNodeTmpl<T,DeallocArrayDelete<T> >(
00063     p, DeallocArrayDelete<T>(), has_ownership_in
00064     );
00065 }
00066 
00067 
00068 template<class T, class Dealloc_T>
00069 inline
00070 RCPNode* ArrayRCP_createNewDeallocRCPNodeRawPtr(
00071   T* p, Dealloc_T dealloc, bool has_ownership_in
00072   )
00073 {
00074     return new RCPNodeTmpl<T,Dealloc_T>(p, dealloc, has_ownership_in);
00075 }
00076 
00077 
00078 template<class T2, class T1>
00079 class ArcpReinterpretCastEmbeddedObj
00080 {
00081 public:
00082   typedef T2 ptr_t;
00083   ArcpReinterpretCastEmbeddedObj()
00084     : arcp_pod_(null)
00085     {}
00086   ArcpReinterpretCastEmbeddedObj(const ArrayRCP<T1> &arcp_pod)
00087     : arcp_pod_(arcpCloneNode(arcp_pod)) // Unique reference count!
00088     {}
00089   // NOTE: The default copy constructor is allowed and does the right thing
00090   ~ArcpReinterpretCastEmbeddedObj()
00091     { freeMemory(); }
00092   ArcpReinterpretCastEmbeddedObj&
00093   operator=(const ArcpReinterpretCastEmbeddedObj& arceo)
00094     {
00095       assert(is_null(arceo.arcp_pod_)); // Can only be a catestrophic programming error!
00096       freeMemory();
00097       return *this;
00098     }
00099 private:
00100   ArrayRCP<T1> arcp_pod_;
00101   void freeMemory()
00102     {
00103       typedef typename ArrayRCP<T2>::iterator itr_t;
00104       if (arcp_pod_.strong_count() == 1) {
00105         ArrayRCP<T2> arcp2 = arcp_reinterpret_cast<T2>(arcp_pod_);
00106         for (itr_t itr = arcp2.begin(); itr != arcp2.end(); ++itr) {
00107           itr->~T2();
00108         }
00109         arcp_pod_ = null;
00110       }
00111     }
00112 };
00113 
00114 
00115 // Constructors/Destructors/Initializers
00116 
00117 template<class T> inline
00118 ArrayRCP<T>::ArrayRCP( ENull )
00119   : ptr_(NULL), lowerOffset_(0), upperOffset_(-1)
00120 {}
00121 
00122 template<class T> inline
00123 ArrayRCP<const T>::ArrayRCP( ENull )
00124   : ptr_(NULL), lowerOffset_(0), upperOffset_(-1)
00125 {}
00126 
00127 
00128 template<class T> inline
00129 ArrayRCP<T>::ArrayRCP(size_type n, const T& val)
00130   : ptr_(0), lowerOffset_(0), upperOffset_(-1)
00131 {
00132   *this = arcp<T>(n);
00133   std::fill_n(begin(), n, val);
00134 }
00135 
00136 template<class T> inline
00137 ArrayRCP<const T>::ArrayRCP (size_type n, const T& val)
00138   : ptr_(0), lowerOffset_(0), upperOffset_(-1)
00139 {
00140   // We can't call std::fill_n on a const T*, so we have to create a
00141   // nonconst array first, fill it, and then convert to const.
00142   ArrayRCP<T> nonconstArray (n, val);
00143   *this = arcp_const_cast<const T> (nonconstArray);
00144 }
00145 
00146 
00147 template<class T> inline
00148 ArrayRCP<T>::ArrayRCP(
00149   T* p, size_type lowerOffset_in, size_type size_in,
00150   bool has_ownership_in, const ERCPNodeLookup rcpNodeLookup
00151   )
00152   : ptr_(p),
00153 #ifndef TEUCHOS_DEBUG
00154     node_(ArrayRCP_createNewRCPNodeRawPtr(p, has_ownership_in)),
00155 #endif // TEUCHOS_DEBUG
00156     lowerOffset_(lowerOffset_in),
00157     upperOffset_(size_in + lowerOffset_in - 1)
00158 {
00159 #ifdef TEUCHOS_DEBUG
00160   if (p) {
00161     RCPNode* existing_RCPNode = 0;
00162     if (!has_ownership_in && rcpNodeLookup==RCP_ENABLE_NODE_LOOKUP) {
00163       existing_RCPNode = RCPNodeTracer::getExistingRCPNode(p);
00164     }
00165     if (existing_RCPNode) {
00166       // Will not call add_new_RCPNode(...)
00167       node_ = RCPNodeHandle(existing_RCPNode, RCP_WEAK, false);
00168     }
00169     else {
00170       // Will call add_new_RCPNode(...)
00171       RCPNodeThrowDeleter nodeDeleter(ArrayRCP_createNewRCPNodeRawPtr(p, has_ownership_in));
00172       node_ = RCPNodeHandle(
00173         nodeDeleter.get(),
00174         p, typeName(*p), concreteTypeName(*p),
00175         has_ownership_in
00176         );
00177       nodeDeleter.release();
00178     }
00179   }
00180 #else // NOT TEUCHOS_DEBUG
00181   (void) rcpNodeLookup; // Silence "unused variable" compiler warning.
00182 #endif // TEUCHOS_DEBUG
00183 }
00184 
00185 template<class T> inline
00186 ArrayRCP<const T>::
00187 ArrayRCP (const T* p, size_type lowerOffset_in, size_type size_in,
00188     bool has_ownership_in, const ERCPNodeLookup rcpNodeLookup)
00189   : ptr_(p),
00190 #ifndef TEUCHOS_DEBUG
00191     node_(ArrayRCP_createNewRCPNodeRawPtr(p, has_ownership_in)),
00192 #endif // TEUCHOS_DEBUG
00193     lowerOffset_(lowerOffset_in),
00194     upperOffset_(size_in + lowerOffset_in - 1)
00195 {
00196 #ifdef TEUCHOS_DEBUG
00197   if (p) {
00198     RCPNode* existing_RCPNode = 0;
00199     if (! has_ownership_in && rcpNodeLookup == RCP_ENABLE_NODE_LOOKUP) {
00200       existing_RCPNode = RCPNodeTracer::getExistingRCPNode (p);
00201     }
00202     if (existing_RCPNode) {
00203       // Will not call add_new_RCPNode(...)
00204       node_ = RCPNodeHandle(existing_RCPNode, RCP_WEAK, false);
00205     }
00206     else {
00207       // Will call add_new_RCPNode(...)
00208       RCPNodeThrowDeleter nodeDeleter (ArrayRCP_createNewRCPNodeRawPtr (p, has_ownership_in));
00209       node_ = RCPNodeHandle(
00210         nodeDeleter.get (),
00211         p, typeName (*p), concreteTypeName (*p),
00212         has_ownership_in
00213         );
00214       nodeDeleter.release ();
00215     }
00216   }
00217 #else // NOT TEUCHOS_DEBUG
00218   (void) rcpNodeLookup; // Silence "unused variable" compiler warning.
00219 #endif // TEUCHOS_DEBUG
00220 }
00221 
00222 
00223 template<class T>
00224 template<class Dealloc_T>
00225 inline
00226 ArrayRCP<T>::ArrayRCP(
00227   T* p, size_type lowerOffset_in, size_type size_in,
00228   Dealloc_T dealloc, bool has_ownership_in
00229   )
00230   : ptr_(p),
00231 #ifndef TEUCHOS_DEBUG
00232     node_(ArrayRCP_createNewDeallocRCPNodeRawPtr(p, dealloc, has_ownership_in)),
00233 #endif // TEUCHOS_DEBUG
00234     lowerOffset_(lowerOffset_in),
00235     upperOffset_(size_in + lowerOffset_in - 1)
00236 {
00237 #ifdef TEUCHOS_DEBUG
00238   if (p) {
00239     node_ = RCPNodeHandle(
00240       ArrayRCP_createNewDeallocRCPNodeRawPtr(p, dealloc, has_ownership_in),
00241       p, typeName(*p), concreteTypeName(*p),
00242       has_ownership_in
00243       //, RCP_STRONG, false
00244       );
00245   }
00246 #endif // TEUCHOS_DEBUG
00247 }
00248 
00249 template<class T>
00250 template<class Dealloc_T>
00251 inline
00252 ArrayRCP<const T>::ArrayRCP(
00253   const T* p, size_type lowerOffset_in, size_type size_in,
00254   Dealloc_T dealloc, bool has_ownership_in
00255   )
00256   : ptr_(p),
00257 #ifndef TEUCHOS_DEBUG
00258     node_(ArrayRCP_createNewDeallocRCPNodeRawPtr(p, dealloc, has_ownership_in)),
00259 #endif // TEUCHOS_DEBUG
00260     lowerOffset_(lowerOffset_in),
00261     upperOffset_(size_in + lowerOffset_in - 1)
00262 {
00263 #ifdef TEUCHOS_DEBUG
00264   if (p) {
00265     node_ = RCPNodeHandle(
00266       ArrayRCP_createNewDeallocRCPNodeRawPtr(p, dealloc, has_ownership_in),
00267       p, typeName(*p), concreteTypeName(*p),
00268       has_ownership_in
00269       //, RCP_STRONG, false
00270       );
00271   }
00272 #endif // TEUCHOS_DEBUG
00273 }
00274 
00275 
00276 template<class T> inline
00277 ArrayRCP<T>::ArrayRCP(const ArrayRCP<T>& r_ptr)
00278   :ptr_(r_ptr.ptr_),
00279    node_(r_ptr.node_),
00280    lowerOffset_(r_ptr.lowerOffset_),
00281    upperOffset_(r_ptr.upperOffset_)
00282 {}
00283 
00284 template<class T> inline
00285 ArrayRCP<const T>::ArrayRCP (const ArrayRCP<const T>& r_ptr)
00286   :ptr_(r_ptr.ptr_),
00287    node_(r_ptr.node_),
00288    lowerOffset_(r_ptr.lowerOffset_),
00289    upperOffset_(r_ptr.upperOffset_)
00290 {}
00291 
00292 
00293 template<class T> inline
00294 ArrayRCP<T>::~ArrayRCP() {}
00295 
00296 template<class T> inline
00297 ArrayRCP<const T>::~ArrayRCP() {}
00298 
00299 
00300 template<class T> inline
00301 ArrayRCP<T>& ArrayRCP<T>::operator=(const ArrayRCP<T>& r_ptr)
00302 {
00303   if( this == &r_ptr )
00304     return *this; // Assignment to self
00305   node_ = r_ptr.access_private_node(); // May throw in debug mode!
00306   ptr_ = r_ptr.ptr_;
00307   lowerOffset_ = r_ptr.lowerOffset_;
00308   upperOffset_ = r_ptr.upperOffset_;
00309   return *this;
00310   // NOTE: It is critical that the assignment of ptr_ come *after* the
00311   // assignment of node_ since node_ might throw an exception!
00312 }
00313 
00314 template<class T> inline
00315 ArrayRCP<const T>& 
00316 ArrayRCP<const T>::operator= (const ArrayRCP<const T>& r_ptr)
00317 {
00318   if (this == &r_ptr) {
00319     return *this; // Assignment to self
00320   }
00321   node_ = r_ptr.access_private_node (); // May throw in debug mode!
00322   ptr_ = r_ptr.ptr_;
00323   lowerOffset_ = r_ptr.lowerOffset_;
00324   upperOffset_ = r_ptr.upperOffset_;
00325   return *this;
00326   // NOTE: The assignment of ptr_ MUST come after the assignment of
00327   // node_, since that line of code might throw an exception!
00328 }
00329 
00330 
00331 // Object/Pointer Access Functions
00332 
00333 
00334 template<class T> inline
00335 bool ArrayRCP<T>::is_null() const {
00336   return ptr_ == 0;
00337 }
00338 
00339 template<class T> inline
00340 bool ArrayRCP<const T>::is_null() const {
00341   return ptr_ == 0;
00342 }
00343 
00344 
00345 template<class T> inline
00346 T* ArrayRCP<T>::operator->() const
00347 {
00348   debug_assert_valid_ptr();
00349   debug_assert_in_range(0,1);
00350   return ptr_;
00351 }
00352 
00353 template<class T> inline
00354 const T* ArrayRCP<const T>::operator->() const
00355 {
00356   debug_assert_valid_ptr();
00357   debug_assert_in_range(0,1);
00358   return ptr_;
00359 }
00360 
00361 
00362 template<class T> inline
00363 T& ArrayRCP<T>::operator*() const
00364 {
00365   debug_assert_valid_ptr();
00366   debug_assert_in_range(0,1);
00367   return *ptr_;
00368 }
00369 
00370 template<class T> inline
00371 const T& ArrayRCP<const T>::operator*() const
00372 {
00373   debug_assert_valid_ptr();
00374   debug_assert_in_range(0,1);
00375   return *ptr_;
00376 }
00377 
00378 
00379 template<class T> inline
00380 T* ArrayRCP<T>::get() const
00381 {
00382   if (ptr_) {
00383     debug_assert_valid_ptr();
00384     debug_assert_in_range(0,1);
00385   }
00386   return ptr_;
00387 }
00388 
00389 template<class T> inline
00390 const T* ArrayRCP<const T>::get() const
00391 {
00392   if (ptr_) {
00393     debug_assert_valid_ptr();
00394     debug_assert_in_range(0,1);
00395   }
00396   return ptr_;
00397 }
00398 
00399 
00400 template<class T> inline
00401 T* ArrayRCP<T>::getRawPtr() const {
00402   return this->get();
00403 }
00404 
00405 template<class T> inline
00406 const T* ArrayRCP<const T>::getRawPtr() const {
00407   return this->get();
00408 }
00409 
00410 
00411 template<class T> inline
00412 T& ArrayRCP<T>::operator[](size_type offset) const
00413 {
00414   debug_assert_valid_ptr();
00415   debug_assert_in_range(offset,1);
00416   return ptr_[offset];
00417 }
00418 
00419 template<class T> inline
00420 const T& ArrayRCP<const T>::operator[] (size_type offset) const
00421 {
00422   debug_assert_valid_ptr();
00423   debug_assert_in_range(offset,1);
00424   return ptr_[offset];
00425 }
00426 
00427 
00428 // Pointer Arithmetic Functions
00429 
00430 
00431 template<class T> inline
00432 ArrayRCP<T>& ArrayRCP<T>::operator++()
00433 {
00434   debug_assert_valid_ptr();
00435   ++ptr_;
00436   --lowerOffset_;
00437   --upperOffset_;
00438   return *this;
00439 }
00440 
00441 template<class T> inline
00442 ArrayRCP<const T>& ArrayRCP<const T>::operator++()
00443 {
00444   debug_assert_valid_ptr();
00445   ++ptr_;
00446   --lowerOffset_;
00447   --upperOffset_;
00448   return *this;
00449 }
00450 
00451 
00452 template<class T> inline
00453 ArrayRCP<T> ArrayRCP<T>::operator++(int)
00454 {
00455   debug_assert_valid_ptr();
00456   ArrayRCP<T> r_ptr = *this;
00457   ++(*this);
00458   return r_ptr;
00459 }
00460 
00461 template<class T> inline
00462 ArrayRCP<const T> ArrayRCP<const T>::operator++(int)
00463 {
00464   debug_assert_valid_ptr();
00465   ArrayRCP<const T> r_ptr = *this;
00466   ++(*this);
00467   return r_ptr;
00468 }
00469 
00470 
00471 template<class T> inline
00472 ArrayRCP<T>& ArrayRCP<T>::operator--()
00473 {
00474   debug_assert_valid_ptr();
00475   --ptr_;
00476   ++lowerOffset_;
00477   ++upperOffset_;
00478   return *this;
00479 }
00480 
00481 template<class T> inline
00482 ArrayRCP<const T>& ArrayRCP<const T>::operator--()
00483 {
00484   debug_assert_valid_ptr();
00485   --ptr_;
00486   ++lowerOffset_;
00487   ++upperOffset_;
00488   return *this;
00489 }
00490 
00491 
00492 template<class T> inline
00493 ArrayRCP<T> ArrayRCP<T>::operator--(int)
00494 {
00495   debug_assert_valid_ptr();
00496   ArrayRCP<T> r_ptr = *this;
00497   --(*this);
00498   return r_ptr;
00499 }
00500 
00501 template<class T> inline
00502 ArrayRCP<const T> ArrayRCP<const T>::operator--(int)
00503 {
00504   debug_assert_valid_ptr();
00505   ArrayRCP<const T> r_ptr = *this;
00506   --(*this);
00507   return r_ptr;
00508 }
00509 
00510 
00511 template<class T> inline
00512 ArrayRCP<T>& ArrayRCP<T>::operator+=(size_type offset)
00513 {
00514   debug_assert_valid_ptr();
00515   ptr_ += offset;
00516   lowerOffset_ -= offset;
00517   upperOffset_ -= offset;
00518   return *this;
00519 }
00520 
00521 template<class T> inline
00522 ArrayRCP<const T>& ArrayRCP<const T>::operator+=(size_type offset)
00523 {
00524   debug_assert_valid_ptr();
00525   ptr_ += offset;
00526   lowerOffset_ -= offset;
00527   upperOffset_ -= offset;
00528   return *this;
00529 }
00530 
00531 
00532 template<class T> inline
00533 ArrayRCP<T>& ArrayRCP<T>::operator-=(size_type offset)
00534 {
00535   debug_assert_valid_ptr();
00536   ptr_ -= offset;
00537   lowerOffset_ += offset;
00538   upperOffset_ += offset;
00539   return *this;
00540 }
00541 
00542 template<class T> inline
00543 ArrayRCP<const T>& ArrayRCP<const T>::operator-=(size_type offset)
00544 {
00545   debug_assert_valid_ptr();
00546   ptr_ -= offset;
00547   lowerOffset_ += offset;
00548   upperOffset_ += offset;
00549   return *this;
00550 }
00551 
00552 
00553 template<class T> inline
00554 ArrayRCP<T> ArrayRCP<T>::operator+(size_type offset) const
00555 {
00556   ArrayRCP<T> r_ptr = *this;
00557   r_ptr+=(offset);
00558   return r_ptr;
00559 }
00560 
00561 template<class T> inline
00562 ArrayRCP<const T> ArrayRCP<const T>::operator+(size_type offset) const
00563 {
00564   ArrayRCP<const T> r_ptr = *this;
00565   r_ptr+=(offset);
00566   return r_ptr;
00567 }
00568 
00569 
00570 template<class T> inline
00571 ArrayRCP<T> ArrayRCP<T>::operator-(size_type offset) const
00572 {
00573   ArrayRCP<T> r_ptr = *this;
00574   r_ptr-=offset;
00575   return r_ptr;
00576 }
00577 
00578 template<class T> inline
00579 ArrayRCP<const T> ArrayRCP<const T>::operator-(size_type offset) const
00580 {
00581   ArrayRCP<const T> r_ptr = *this;
00582   r_ptr-=offset;
00583   return r_ptr;
00584 }
00585 
00586 
00587 // Standard Container-Like Functions
00588 
00589 
00590 template<class T> inline
00591 typename ArrayRCP<T>::iterator ArrayRCP<T>::begin() const
00592 {
00593   debug_assert_valid_ptr();
00594 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00595   return *this;
00596 #else
00597   return ptr_;
00598 #endif
00599 }
00600 
00601 template<class T> inline
00602 typename ArrayRCP<const T>::iterator ArrayRCP<const T>::begin() const
00603 {
00604   debug_assert_valid_ptr();
00605 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00606   return *this;
00607 #else
00608   return ptr_;
00609 #endif
00610 }
00611 
00612 
00613 template<class T> inline
00614 typename ArrayRCP<T>::iterator ArrayRCP<T>::end() const
00615 {
00616   debug_assert_valid_ptr();
00617 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00618   return *this + (upperOffset_ + 1);
00619 #else
00620   return ptr_ + (upperOffset_ + 1);
00621 #endif
00622 }
00623 
00624 template<class T> inline
00625 typename ArrayRCP<const T>::iterator ArrayRCP<const T>::end() const
00626 {
00627   debug_assert_valid_ptr();
00628 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00629   return *this + (upperOffset_ + 1);
00630 #else
00631   return ptr_ + (upperOffset_ + 1);
00632 #endif
00633 }
00634 
00635 
00636 // ArrayRCP Views
00637 
00638 
00639 template<class T> inline
00640 ArrayRCP<const T> ArrayRCP<T>::getConst() const
00641 {
00642   if (ptr_) {
00643     debug_assert_valid_ptr();
00644     const T *cptr = ptr_; // Will not compile if not legal!
00645     return ArrayRCP<const T>(cptr, lowerOffset_, size(), node_);
00646   }
00647   return null;
00648 }
00649 
00650 template<class T> inline
00651 ArrayRCP<const T> ArrayRCP<const T>::getConst() const {
00652   // Trivial implementation, since no need for conversion.
00653   return *this;
00654 }
00655 
00656 
00657 template<class T> inline
00658 ArrayRCP<T>
00659 ArrayRCP<T>::persistingView( size_type lowerOffset_in, size_type size_in ) const
00660 {
00661   if (size_in == 0) {
00662     return null;
00663   }
00664   debug_assert_valid_ptr();
00665   debug_assert_in_range(lowerOffset_in, size_in);
00666   ArrayRCP<T> ptr = *this;
00667   ptr.ptr_ = ptr.ptr_ + lowerOffset_in;
00668   ptr.lowerOffset_ = 0;
00669   ptr.upperOffset_ = size_in - 1;
00670   return ptr;
00671 }
00672 
00673 template<class T> inline
00674 ArrayRCP<const T>
00675 ArrayRCP<const T>::persistingView (size_type lowerOffset_in, size_type size_in) const
00676 {
00677   if (size_in == 0) {
00678     return null;
00679   }
00680   debug_assert_valid_ptr();
00681   debug_assert_in_range(lowerOffset_in, size_in);
00682   ArrayRCP<const T> ptr = *this;
00683   ptr.ptr_ = ptr.ptr_ + lowerOffset_in;
00684   ptr.lowerOffset_ = 0;
00685   ptr.upperOffset_ = size_in - 1;
00686   return ptr;
00687 }
00688 
00689 
00690 // Size and extent query functions
00691 
00692 
00693 template<class T> inline
00694 typename ArrayRCP<T>::size_type
00695 ArrayRCP<T>::lowerOffset() const
00696 {
00697   debug_assert_valid_ptr();
00698   return lowerOffset_;
00699 }
00700 
00701 template<class T> inline
00702 typename ArrayRCP<const T>::size_type
00703 ArrayRCP<const T>::lowerOffset() const
00704 {
00705   debug_assert_valid_ptr();
00706   return lowerOffset_;
00707 }
00708 
00709 
00710 template<class T> inline
00711 typename ArrayRCP<T>::size_type
00712 ArrayRCP<T>::upperOffset() const
00713 {
00714   debug_assert_valid_ptr();
00715   return upperOffset_;
00716 }
00717 
00718 template<class T> inline
00719 typename ArrayRCP<const T>::size_type
00720 ArrayRCP<const T>::upperOffset() const
00721 {
00722   debug_assert_valid_ptr();
00723   return upperOffset_;
00724 }
00725 
00726 
00727 template<class T> inline
00728 typename ArrayRCP<T>::size_type
00729 ArrayRCP<T>::size() const
00730 {
00731   debug_assert_valid_ptr();
00732   return upperOffset_ - lowerOffset_ + 1;
00733 }
00734 
00735 template<class T> inline
00736 typename ArrayRCP<const T>::size_type
00737 ArrayRCP<const T>::size() const
00738 {
00739   debug_assert_valid_ptr();
00740   return upperOffset_ - lowerOffset_ + 1;
00741 }
00742 
00743 
00744 // ArrayView views
00745 
00746 
00747 template<class T> inline
00748 ArrayView<T> ArrayRCP<T>::view( size_type lowerOffset_in, size_type size_in ) const
00749 {
00750   if (size_in == 0) {
00751     return null;
00752   }
00753   debug_assert_valid_ptr();
00754   debug_assert_in_range(lowerOffset_in,size_in);
00755 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00756   return ArrayView<T>(persistingView(lowerOffset_in, size_in).create_weak());
00757 #else
00758   return arrayView(ptr_ + lowerOffset_in, size_in);
00759 #endif
00760   // ToDo: Implement checks for dangling references!
00761 }
00762 
00763 template<class T> inline
00764 ArrayView<const T> 
00765 ArrayRCP<const T>::view (size_type lowerOffset_in, size_type size_in) const
00766 {
00767   if (size_in == 0) {
00768     return null;
00769   }
00770   debug_assert_valid_ptr();
00771   debug_assert_in_range(lowerOffset_in,size_in);
00772 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00773   return ArrayView<const T> (persistingView (lowerOffset_in, size_in).create_weak ());
00774 #else
00775   return arrayView (ptr_ + lowerOffset_in, size_in);
00776 #endif
00777   // ToDo: Implement checks for dangling references!
00778 }
00779 
00780 
00781 template<class T> inline
00782 ArrayView<T> ArrayRCP<T>::operator()( size_type lowerOffset_in, size_type size_in ) const
00783 {
00784   return view(lowerOffset_in, size_in);
00785 }
00786 
00787 template<class T> inline
00788 ArrayView<const T> 
00789 ArrayRCP<const T>::operator() (size_type lowerOffset_in, size_type size_in) const
00790 {
00791   return view (lowerOffset_in, size_in);
00792 }
00793 
00794 
00795 template<class T> inline
00796 ArrayView<T> ArrayRCP<T>::operator()() const
00797 {
00798   if (size()) {
00799     return view(lowerOffset_, size());
00800   }
00801   return null;
00802 }
00803 
00804 template<class T> inline
00805 ArrayView<const T> ArrayRCP<const T>::operator()() const
00806 {
00807   if (size()) {
00808     return view (lowerOffset_, size ());
00809   }
00810   return null;
00811 }
00812 
00813 
00814 // Implicit conversions
00815 
00816 
00817 template<class T> inline
00818 ArrayRCP<T>::operator ArrayRCP<const T>() const
00819 {
00820   if (size()) {
00821     return ArrayRCP<const T>(ptr_, lowerOffset_, size(), node_);
00822   }
00823   return null;
00824 }
00825 // The above operator does not exist in the partial specialization for
00826 // const T, because it doesn't make sense in that case.  (Many
00827 // compilers warn if one tries to implement that operator, because
00828 // that code would never get called.)
00829 
00830 
00831 // std::vector like functions
00832 //
00833 // Assignment (deep copy) doesn't make sense for the "const T" partial
00834 // specialization, so the assignment methods (assign() and deepCopy())
00835 // are omitted in that case.
00836 
00837 
00838 template<class T> inline
00839 void ArrayRCP<T>::assign (size_type n, const T &val) {
00840   *this = arcp<T> (n);
00841   std::fill_n (this->begin (), n, val);
00842 }
00843 
00844 
00845 template<class T>
00846 template<class Iter>
00847 inline
00848 void ArrayRCP<T>::assign (Iter first, Iter last) {
00849   const size_type new_n = std::distance (first, last);
00850   if (new_n != size ()) {
00851     *this = arcp<T> (new_n);
00852   }
00853   std::copy (first, last, begin ());
00854 }
00855 
00856 
00857 template<class T> inline
00858 void ArrayRCP<T>::resize(const size_type n, const T &val)
00859 {
00860 #ifdef TEUCHOS_DEBUG
00861   TEUCHOS_ASSERT_EQUALITY(lowerOffset(), 0);
00862 #endif
00863   if (n == 0) {
00864     clear();
00865     return;
00866   }
00867   const size_type orig_n = size();
00868   if (n != orig_n) {
00869     ArrayRCP<T> tmp = *this;
00870     *this = arcp<T>(n);
00871     const size_type small_n = std::min(n, orig_n);
00872     for (size_type i = 0; i < small_n; ++i)
00873       (*this)[i] = tmp[i];
00874     for (size_type i = orig_n; i < n; ++i)
00875       (*this)[i] = val;
00876     upperOffset_ = n-1;
00877   }
00878 }
00879 
00880 template<class T> inline
00881 void ArrayRCP<const T>::resize (const size_type n, const T& val)
00882 {
00883 #ifdef TEUCHOS_DEBUG
00884   TEUCHOS_ASSERT_EQUALITY(lowerOffset(), 0);
00885 #endif
00886   if (n == 0) {
00887     clear ();
00888     return;
00889   }
00890   const size_type orig_n = size ();
00891   if (n != orig_n) {
00892     ArrayRCP<const T> tmp = *this;
00893     // It's not allowed to assign to the result of operator[] for a
00894     // const right-hand side, so we have to assign to a temporary
00895     // nonconst ArrayRCP (nonconstThis) first.
00896     ArrayRCP<T> nonconstThis = arcp<T> (n);
00897     const size_type small_n = std::min (n, orig_n);
00898     for (size_type i = 0; i < small_n; ++i) {
00899       nonconstThis[i] = tmp[i];
00900     }
00901     for (size_type i = orig_n; i < n; ++i) {
00902       nonconstThis[i] = val;
00903     }
00904     *this = arcp_const_cast<const T> (nonconstThis);
00905     upperOffset_ = n-1;
00906   }
00907 }
00908 
00909 
00910 template<class T> inline
00911 void ArrayRCP<T>::clear() {
00912   *this = null;
00913 }
00914 
00915 template<class T> inline
00916 void ArrayRCP<const T>::clear() {
00917   *this = null;
00918 }
00919 
00920 
00921 // Misc functions
00922 
00923 
00924 template<class T> inline
00925 void ArrayRCP<T>::deepCopy(const ArrayView<const T>& av)
00926 {
00927   if (av.size() == 0) {
00928     *this = null;
00929     return;
00930   }
00931   assign(av.begin(), av.end());
00932 }
00933 
00934 
00935 // Reference counting
00936 
00937 
00938 template<class T> inline
00939 ERCPStrength ArrayRCP<T>::strength() const {
00940   return node_.strength();
00941 }
00942 
00943 template<class T> inline
00944 ERCPStrength ArrayRCP<const T>::strength() const {
00945   return node_.strength();
00946 }
00947 
00948 
00949 template<class T> inline
00950 bool ArrayRCP<T>::is_valid_ptr() const
00951 {
00952   if (ptr_)
00953     return node_.is_valid_ptr();
00954   return true;
00955 }
00956 
00957 template<class T> inline
00958 bool ArrayRCP<const T>::is_valid_ptr() const
00959 {
00960   if (ptr_)
00961     return node_.is_valid_ptr();
00962   return true;
00963 }
00964 
00965 
00966 template<class T> inline
00967 int ArrayRCP<T>::strong_count() const
00968 {
00969   return node_.strong_count();
00970 }
00971 
00972 template<class T> inline
00973 int ArrayRCP<const T>::strong_count() const
00974 {
00975   return node_.strong_count();
00976 }
00977 
00978 
00979 template<class T> inline
00980 int ArrayRCP<T>::weak_count() const
00981 {
00982   return node_.weak_count();
00983 }
00984 
00985 template<class T> inline
00986 int ArrayRCP<const T>::weak_count() const
00987 {
00988   return node_.weak_count();
00989 }
00990 
00991 
00992 template<class T> inline
00993 int ArrayRCP<T>::total_count() const
00994 {
00995   return node_.total_count();
00996 }
00997 
00998 template<class T> inline
00999 int ArrayRCP<const T>::total_count() const
01000 {
01001   return node_.total_count();
01002 }
01003 
01004 
01005 template<class T> inline
01006 void ArrayRCP<T>::set_has_ownership()
01007 {
01008   node_.has_ownership(true);
01009 }
01010 
01011 template<class T> inline
01012 void ArrayRCP<const T>::set_has_ownership()
01013 {
01014   node_.has_ownership(true);
01015 }
01016 
01017 
01018 template<class T> inline
01019 bool ArrayRCP<T>::has_ownership() const
01020 {
01021   return node_.has_ownership();
01022 }
01023 
01024 template<class T> inline
01025 bool ArrayRCP<const T>::has_ownership() const
01026 {
01027   return node_.has_ownership();
01028 }
01029 
01030 
01031 template<class T> inline
01032 T* ArrayRCP<T>::release()
01033 {
01034   debug_assert_valid_ptr();
01035   node_.has_ownership(false);
01036   return ptr_;
01037 }
01038 
01039 template<class T> inline
01040 const T* ArrayRCP<const T>::release()
01041 {
01042   debug_assert_valid_ptr();
01043   node_.has_ownership(false);
01044   return ptr_;
01045 }
01046 
01047 
01048 template<class T> inline
01049 ArrayRCP<T> ArrayRCP<T>::create_weak () const {
01050   debug_assert_valid_ptr ();
01051   return ArrayRCP<T> (ptr_, lowerOffset_, size (), node_.create_weak ());
01052 }
01053 
01054 template<class T> inline
01055 ArrayRCP<const T> ArrayRCP<const T>::create_weak() const {
01056   debug_assert_valid_ptr ();
01057   return ArrayRCP<const T> (ptr_, lowerOffset_, size (), node_.create_weak ());
01058 }
01059 
01060 
01061 template<class T> inline
01062 ArrayRCP<T> ArrayRCP<T>::create_strong () const {
01063   debug_assert_valid_ptr ();
01064   return ArrayRCP<T> (ptr_, lowerOffset_, size (), node_.create_strong ());
01065 }
01066 
01067 template<class T> inline
01068 ArrayRCP<const T> ArrayRCP<const T>::create_strong () const {
01069   debug_assert_valid_ptr ();
01070   return ArrayRCP<const T> (ptr_, lowerOffset_, size (), node_.create_strong ());
01071 }
01072 
01073 
01074 template<class T>
01075 template <class T2>
01076 inline
01077 bool ArrayRCP<T>::shares_resource (const ArrayRCP<T2>& r_ptr) const
01078 {
01079   return node_.same_node (r_ptr.access_private_node ());
01080   // Note: above, r_ptr is *not* the same class type as *this so we can not
01081   // access its node_ member directly!  This is an interesting detail to the
01082   // C++ protected/private protection mechanism!
01083 }
01084 
01085 template<class T>
01086 template <class T2>
01087 inline
01088 bool ArrayRCP<const T>::shares_resource (const ArrayRCP<T2>& r_ptr) const
01089 {
01090   return node_.same_node (r_ptr.access_private_node ());
01091   // Note: above, r_ptr is *not* the same class type as *this so we can not
01092   // access its node_ member directly!  This is an interesting detail to the
01093   // C++ protected/private protection mechanism!
01094 }
01095 
01096 
01097 // Assertion Functions
01098 
01099 
01100 template<class T> inline
01101 const ArrayRCP<T>&
01102 ArrayRCP<T>::assert_not_null() const
01103 {
01104   if(!ptr_)
01105     throw_null_ptr_error(typeName(*this));
01106   return *this;
01107 }
01108 
01109 template<class T> inline
01110 const ArrayRCP<const T>&
01111 ArrayRCP<const T>::assert_not_null() const
01112 {
01113   if (! ptr_) {
01114     throw_null_ptr_error (typeName (*this));
01115   }
01116   return *this;
01117 }
01118 
01119 
01120 template<class T> inline
01121 const ArrayRCP<T>& ArrayRCP<T>::assert_valid_ptr() const
01122 {
01123   if (ptr_) {
01124     node_.assert_valid_ptr (*this);
01125   }
01126   return *this;
01127 }
01128 
01129 template<class T> inline
01130 const ArrayRCP<const T>& ArrayRCP<const T>::assert_valid_ptr () const
01131 {
01132   if (ptr_) {
01133     node_.assert_valid_ptr (*this);
01134   }
01135   return *this;
01136 }
01137 
01138 
01139 template<class T> inline
01140 const ArrayRCP<T>&
01141 ArrayRCP<T>::assert_in_range( size_type lowerOffset_in, size_type size_in ) const
01142 {
01143   assert_not_null();
01144   TEUCHOS_TEST_FOR_EXCEPTION(
01145     !(
01146       (lowerOffset_ <= lowerOffset_in && lowerOffset_in+size_in-1 <= upperOffset_)
01147       &&
01148       size_in >= 0
01149       ),
01150     Teuchos::RangeError,
01151     typeName(*this)<<"::assert_in_range:"
01152     " Error, [lowerOffset,lowerOffset+size-1] = ["
01153     <<lowerOffset_in<<","<<(lowerOffset_in+size_in-1)<<"] does not lie in the"
01154     " range ["<<lowerOffset_<<","<<upperOffset_<<"]!"
01155     );
01156   return *this;
01157 }
01158 
01159 template<class T> inline
01160 const ArrayRCP<const T>&
01161 ArrayRCP<const T>::
01162 assert_in_range (size_type lowerOffset_in, size_type size_in) const
01163 {
01164   assert_not_null ();
01165   TEUCHOS_TEST_FOR_EXCEPTION(
01166     !(
01167       (lowerOffset_ <= lowerOffset_in && lowerOffset_in+size_in-1 <= upperOffset_)
01168       &&
01169       size_in >= 0
01170       ),
01171     Teuchos::RangeError,
01172     typeName (*this) << "::assert_in_range:"
01173     " Error, [lowerOffset,lowerOffset+size-1] = ["
01174     <<lowerOffset_in<<","<<(lowerOffset_in+size_in-1)<<"] does not lie in the"
01175     " range ["<<lowerOffset_<<","<<upperOffset_<<"]!"
01176     );
01177   return *this;
01178 }
01179 
01180 
01181 // Deprecated
01182 
01183 
01184 template<class T> inline
01185 int ArrayRCP<T>::count() const {
01186   return node_.count();
01187 }
01188 
01189 template<class T> inline
01190 int ArrayRCP<const T>::count() const {
01191   return node_.count();
01192 }
01193 
01194 
01195 // very bad public functions
01196 
01197 
01198 template<class T> inline
01199 ArrayRCP<T>::ArrayRCP(
01200   T* p, size_type lowerOffset_in, size_type size_in,
01201   const RCPNodeHandle& node
01202   )
01203   :ptr_(p),
01204    node_(node),
01205    lowerOffset_(lowerOffset_in),
01206    upperOffset_(size_in + lowerOffset_in - 1)
01207 {}
01208 
01209 template<class T> inline
01210 ArrayRCP<const T>::ArrayRCP(
01211   const T* p, size_type lowerOffset_in, size_type size_in,
01212   const RCPNodeHandle& node
01213   )
01214   :ptr_(p),
01215    node_(node),
01216    lowerOffset_(lowerOffset_in),
01217    upperOffset_(size_in + lowerOffset_in - 1)
01218 {}
01219 
01220 
01221 template<class T> inline
01222 T* ArrayRCP<T>::access_private_ptr() const
01223 {
01224   return ptr_;
01225 }
01226 
01227 template<class T> inline
01228 const T* ArrayRCP<const T>::access_private_ptr () const
01229 {
01230   return ptr_;
01231 }
01232 
01233 
01234 template<class T> inline
01235 RCPNodeHandle& ArrayRCP<T>::nonconst_access_private_node()
01236 {
01237   return node_;
01238 }
01239 
01240 template<class T> inline
01241 RCPNodeHandle& ArrayRCP<const T>::nonconst_access_private_node()
01242 {
01243   return node_;
01244 }
01245 
01246 
01247 template<class T> inline
01248 const RCPNodeHandle& ArrayRCP<T>::access_private_node() const
01249 {
01250   return node_;
01251 }
01252 
01253 template<class T> inline
01254 const RCPNodeHandle& ArrayRCP<const T>::access_private_node() const
01255 {
01256   return node_;
01257 }
01258 
01259 
01260 // Array<void> and Array<const void> specializations
01261 
01262 
01263 ArrayRCP<void>::ArrayRCP()
01264 {
01265   TEUCHOS_TEST_FOR_EXCEPT(true);
01266 }
01267 
01268 
01269 ArrayRCP<const void>::ArrayRCP()
01270 {
01271   TEUCHOS_TEST_FOR_EXCEPT(true);
01272 }
01273 
01274 
01275 }  // end namespace Teuchos
01276 
01277 
01278 // ///////////////////////////////////////////
01279 // Non-member functions for ArrayRCP
01280 
01281 
01282 namespace Teuchos {
01283 namespace Utilities {
01284 template<class T1, class T2>
01285 inline void assert_shares_resource(
01286   const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2
01287   )
01288 {
01289 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01290   TEUCHOS_TEST_FOR_EXCEPTION(
01291     !p1.shares_resource(p2), IncompatibleIteratorsError,
01292     "Error, these iterators are *not* pointing to the same valid memory!"
01293     );
01294 #endif
01295 }
01296 } // namespace Utilities
01297 } // namespace Teuchos
01298 
01299 
01300 template<class T> inline
01301 Teuchos::ArrayRCP<T>
01302 Teuchos::arcp(
01303 T* p, typename ArrayRCP<T>::size_type lowerOffset
01304   ,typename ArrayRCP<T>::size_type size_in
01305   ,bool owns_mem
01306   )
01307 {
01308   return ArrayRCP<T>(p, lowerOffset, size_in, owns_mem);
01309 }
01310 
01311 
01312 template<class T, class Dealloc_T>
01313 inline
01314 Teuchos::ArrayRCP<T>
01315 Teuchos::arcp(
01316 T* p, typename ArrayRCP<T>::size_type lowerOffset
01317   ,typename ArrayRCP<T>::size_type size_in
01318   ,Dealloc_T dealloc, bool owns_mem
01319   )
01320 {
01321   return ArrayRCP<T>(p, lowerOffset, size_in, dealloc, owns_mem);
01322 }
01323 
01324 
01325 template<class T> inline
01326 Teuchos::ArrayRCP<T>
01327 Teuchos::arcp( typename ArrayRCP<T>::size_type size )
01328 {
01329 #ifdef TEUCHOS_DEBUG
01330   TEUCHOS_ASSERT_INEQUALITY( size, >=, 0 );
01331 #endif
01332   if (size == 0) {
01333     return null;
01334   }
01335   return ArrayRCP<T>(new T[size], 0, size, true);
01336 }
01337 
01338 
01339 template<class T> inline
01340 Teuchos::ArrayRCP<T>
01341 Teuchos::arcpCloneNode(const ArrayRCP<T> &a)
01342 {
01343   if (is_null(a)) {
01344     return null;
01345   }
01346   return arcpWithEmbeddedObj(a.getRawPtr(), a.lowerOffset(), a.size(),
01347     a, false);
01348 }
01349 
01350 
01351 template<class T> inline
01352 Teuchos::ArrayRCP<T>
01353 Teuchos::arcpClone( const ArrayView<const T> &v )
01354 {
01355   const ArrayRCP<T> new_arcp = arcp<T>(v.size());
01356   std::copy( v.begin(), v.end(), new_arcp.begin() );
01357   return new_arcp;
01358 }
01359 
01360 
01361 template<class T, class Embedded>
01362 Teuchos::ArrayRCP<T>
01363 Teuchos::arcpWithEmbeddedObjPreDestroy(
01364   T* p,
01365   typename ArrayRCP<T>::size_type lowerOffset,
01366   typename ArrayRCP<T>::size_type size,
01367   const Embedded &embedded,
01368   bool owns_mem
01369   )
01370 {
01371   return arcp(
01372     p, lowerOffset, size,
01373     embeddedObjDeallocArrayDelete<T>(embedded, PRE_DESTROY),
01374     owns_mem
01375     );
01376 }
01377 
01378 
01379 template<class T, class Embedded>
01380 Teuchos::ArrayRCP<T>
01381 Teuchos::arcpWithEmbeddedObjPostDestroy(
01382   T* p,
01383   typename ArrayRCP<T>::size_type lowerOffset,
01384   typename ArrayRCP<T>::size_type size,
01385   const Embedded &embedded,
01386   bool owns_mem
01387   )
01388 {
01389   return arcp(
01390     p, lowerOffset, size,
01391     embeddedObjDeallocArrayDelete<T>(embedded, POST_DESTROY),
01392     owns_mem
01393     );
01394 }
01395 
01396 
01397 template<class T, class Embedded>
01398 Teuchos::ArrayRCP<T>
01399 Teuchos::arcpWithEmbeddedObj(
01400   T* p,
01401   typename ArrayRCP<T>::size_type lowerOffset,
01402   typename ArrayRCP<T>::size_type size,
01403   const Embedded &embedded,
01404   bool owns_mem
01405   )
01406 {
01407   return arcpWithEmbeddedObjPostDestroy<T,Embedded>(
01408     p, lowerOffset, size, embedded, owns_mem );
01409 }
01410 
01411 
01412 template<class T> inline
01413 Teuchos::ArrayRCP<T>
01414 Teuchos::arcp( const RCP<std::vector<T> > &v )
01415 {
01416   if ( is_null(v) || !v->size() )
01417     return null;
01418   return arcpWithEmbeddedObjPostDestroy<T,RCP<std::vector<T> > >(
01419     &(*v)[0], 0, v->size(),
01420     v, false
01421     );
01422 }
01423 
01424 
01425 template<class T> inline
01426 Teuchos::ArrayRCP<const T>
01427 Teuchos::arcp( const RCP<const std::vector<T> > &v )
01428 {
01429   if ( is_null(v) || !v->size() )
01430     return null;
01431   return arcpWithEmbeddedObjPostDestroy<const T,RCP<const std::vector<T> > >(
01432     &(*v)[0], 0, v->size(),
01433     v, false
01434     );
01435 }
01436 
01437 
01438 template<class T> inline
01439 Teuchos::ArrayRCP<T>
01440 Teuchos::arcpFromArrayView(const ArrayView<T> &av)
01441 {
01442 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01443   return av.access_private_arcp();
01444 #else
01445   return arcp(av.getRawPtr(), 0, av.size(), false);
01446 #endif
01447 }
01448 
01449 
01450 template<class T> inline
01451 Teuchos::RCP<std::vector<T> >
01452 Teuchos::get_std_vector( const ArrayRCP<T> &ptr )
01453 {
01454   return getEmbeddedObj<T, RCP<std::vector<T> > >(ptr);
01455 }
01456 
01457 
01458 template<class T> inline
01459 Teuchos::RCP<const std::vector<T> >
01460 Teuchos::get_std_vector( const ArrayRCP<const T> &ptr )
01461 {
01462   return getEmbeddedObj<const T, RCP<const std::vector<T> > >(ptr);
01463 }
01464 
01465 
01466 template<class T> inline
01467 bool Teuchos::is_null( const ArrayRCP<T> &p )
01468 {
01469   return p.is_null();
01470 }
01471 
01472 
01473 template<class T> inline
01474 bool Teuchos::nonnull( const ArrayRCP<T> &p )
01475 {
01476   return !p.is_null();
01477 }
01478 
01479 
01480 template<class T> inline
01481 bool Teuchos::operator==( const ArrayRCP<T> &p, ENull )
01482 {
01483   return p.is_null();
01484 }
01485 
01486 
01487 template<class T> inline
01488 bool Teuchos::operator!=( const ArrayRCP<T> &p, ENull )
01489 {
01490   return !p.is_null();
01491 }
01492 
01493 
01494 template<class T1, class T2>
01495 inline
01496 bool Teuchos::operator==( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01497 {
01498   return p1.access_private_ptr() == p2.access_private_ptr();
01499 }
01500 
01501 
01502 template<class T1, class T2>
01503 inline
01504 bool Teuchos::operator!=( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01505 {
01506   return p1.access_private_ptr() != p2.access_private_ptr();
01507 }
01508 
01509 
01510 template<class T1, class T2>
01511 inline
01512 bool Teuchos::operator<( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01513 {
01514   return p1.access_private_ptr() < p2.access_private_ptr();
01515 }
01516 
01517 
01518 template<class T1, class T2>
01519 inline
01520 bool Teuchos::operator<=( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01521 {
01522   Utilities::assert_shares_resource(p1,p2);
01523   return p1.access_private_ptr() <= p2.access_private_ptr();
01524 }
01525 
01526 
01527 template<class T1, class T2>
01528 inline
01529 bool Teuchos::operator>( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01530 {
01531   Utilities::assert_shares_resource(p1,p2);
01532   return p1.access_private_ptr() > p2.access_private_ptr();
01533 }
01534 
01535 
01536 template<class T1, class T2>
01537 inline
01538 bool Teuchos::operator>=( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
01539 {
01540   Utilities::assert_shares_resource(p1,p2);
01541   return p1.access_private_ptr() >= p2.access_private_ptr();
01542 }
01543 
01544 
01545 template<class T>
01546 typename Teuchos::ArrayRCP<T>::difference_type
01547 Teuchos::operator-( const ArrayRCP<T> &p1, const ArrayRCP<T> &p2 )
01548 {
01549   Utilities::assert_shares_resource(p1,p2);
01550   return p1.access_private_ptr() - p2.access_private_ptr();
01551 }
01552 
01553 
01554 template<class T2, class T1>
01555 inline
01556 Teuchos::ArrayRCP<T2>
01557 Teuchos::arcp_reinterpret_cast(const ArrayRCP<T1>& p1)
01558 {
01559   typedef typename ArrayRCP<T1>::size_type size_type;
01560   const int sizeOfT1 = sizeof(T1);
01561   const int sizeOfT2 = sizeof(T2);
01562   size_type lowerOffset2 = (p1.lowerOffset()*sizeOfT1) / sizeOfT2;
01563   size_type upperOffset2 = ((p1.upperOffset()+1)*sizeOfT1) / sizeOfT2 - 1;
01564   T2 *ptr2 = reinterpret_cast<T2*>(p1.get());
01565   return ArrayRCP<T2>(
01566     ptr2, lowerOffset2, upperOffset2 - lowerOffset2 + 1,
01567     p1.access_private_node()
01568     );
01569   // Note: Above is just fine even if p1.get()==NULL!
01570 }
01571 
01572 
01573 template<class T2, class T1>
01574 Teuchos::ArrayRCP<T2>
01575 Teuchos::arcp_reinterpret_cast_nonpod(const ArrayRCP<T1>& p1, const T2& val)
01576 {
01577   typedef typename ArrayRCP<T2>::iterator itr_t;
01578   ArrayRCP<T2> arcp2 = arcp_reinterpret_cast<T2>(p1);
01579   for (itr_t itr = arcp2.begin(); itr != arcp2.end(); ++itr) {
01580     new (&*itr) T2(val);
01581   }
01582   return arcpWithEmbeddedObj(
01583     arcp2.getRawPtr(), 0, arcp2.size(),
01584     ArcpReinterpretCastEmbeddedObj<T2, T1>(p1),
01585     false);
01586   // Above, the ownership of the memory is totally owned by the embedded
01587   // object and the default deallocator policy object does not do anything.
01588   // This is just fine.
01589 }
01590 
01591 
01592 template<class T2, class T1>
01593 inline
01594 Teuchos::ArrayRCP<T2>
01595 Teuchos::arcp_const_cast(const ArrayRCP<T1>& p1)
01596 {
01597   T2 *ptr2 = const_cast<T2*>(p1.get());
01598   return ArrayRCP<T2>(
01599     ptr2, p1.lowerOffset(), p1.size(),
01600     p1.access_private_node()
01601     );
01602   // Note: Above is just fine even if p1.get()==NULL!
01603 }
01604 
01605 
01606 template<class T2, class T1>
01607 inline
01608 Teuchos::ArrayRCP<T2>
01609 Teuchos::arcp_implicit_cast(const ArrayRCP<T1>& p1)
01610 {
01611   T2 * raw_ptr2 = p1.get();
01612   return ArrayRCP<T2>(
01613     raw_ptr2, p1.lowerOffset(), p1.size(),
01614     p1.access_private_node()
01615     );
01616   // Note: Above is just fine even if p1.get()==NULL!
01617 }
01618 
01619 
01620 template<class T1, class T2>
01621 inline
01622 void Teuchos::set_extra_data(
01623   const T1 &extra_data, const std::string& name,
01624   const Ptr<ArrayRCP<T2> > &p, EPrePostDestruction destroy_when,
01625   bool force_unique
01626   )
01627 {
01628   p->assert_not_null();
01629   p->nonconst_access_private_node().set_extra_data( any(extra_data), name, destroy_when,
01630     force_unique );
01631 }
01632 
01633 
01634 template<class T1, class T2>
01635 inline
01636 T1& Teuchos::get_extra_data( ArrayRCP<T2>& p, const std::string& name )
01637 {
01638   p.assert_not_null();
01639   return any_cast<T1>(
01640     p.nonconst_access_private_node().get_extra_data(
01641       TypeNameTraits<T1>::name(), name
01642       )
01643     );
01644 }
01645 
01646 
01647 template<class T1, class T2>
01648 inline
01649 const T1& Teuchos::get_extra_data( const ArrayRCP<T2>& p, const std::string& name )
01650 {
01651   p.assert_not_null();
01652   return any_cast<T1>(
01653     p.access_private_node().get_extra_data(
01654       TypeNameTraits<T1>::name() ,name
01655       )
01656     );
01657 }
01658 
01659 
01660 template<class T1, class T2>
01661 inline
01662 T1* Teuchos::get_optional_extra_data( ArrayRCP<T2>& p, const std::string& name )
01663 {
01664   p.assert_not_null();
01665   any *extra_data = p.nonconst_access_private_node().get_optional_extra_data(
01666     TypeNameTraits<T1>::name(), name);
01667   if( extra_data ) return &any_cast<T1>(*extra_data);
01668   return NULL;
01669 }
01670 
01671 
01672 template<class T1, class T2>
01673 inline
01674 const T1* Teuchos::get_optional_extra_data( const ArrayRCP<T2>& p, const std::string& name )
01675 {
01676   p.assert_not_null();
01677   any *extra_data = p.access_private_node().get_optional_extra_data(
01678     TypeNameTraits<T1>::name(), name);
01679   if( extra_data ) return &any_cast<T1>(*extra_data);
01680   return NULL;
01681 }
01682 
01683 
01684 template<class Dealloc_T, class T>
01685 inline
01686 const Dealloc_T&
01687 Teuchos::get_dealloc( const ArrayRCP<T>& p )
01688 {
01689   return get_nonconst_dealloc<Dealloc_T>(p);
01690 }
01691 
01692 
01693 template<class Dealloc_T, class T>
01694 inline
01695 Dealloc_T&
01696 Teuchos::get_nonconst_dealloc( const Teuchos::ArrayRCP<T>& p )
01697 {
01698   typedef RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>  requested_type;
01699   p.assert_not_null();
01700   RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>
01701     *dnode = dynamic_cast<RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>*>(
01702       p.access_private_node().node_ptr());
01703   TEUCHOS_TEST_FOR_EXCEPTION(
01704     dnode==NULL, NullReferenceError
01705     ,"get_dealloc<" << TypeNameTraits<Dealloc_T>::name()
01706     << "," << TypeNameTraits<T>::name() << ">(p): "
01707     << "Error, requested type \'" << TypeNameTraits<requested_type>::name()
01708     << "\' does not match actual type of the node \'"
01709     << typeName(*p.access_private_node().node_ptr()) << "!"
01710     );
01711   return dnode->get_nonconst_dealloc();
01712 }
01713 
01714 
01715 template<class Dealloc_T, class T>
01716 inline
01717 const Dealloc_T*
01718 Teuchos::get_optional_dealloc( const ArrayRCP<T>& p )
01719 {
01720   return get_optional_dealloc<Dealloc_T>(p);
01721 }
01722 
01723 
01724 template<class Dealloc_T, class T>
01725 inline
01726 Dealloc_T*
01727 Teuchos::get_optional_nonconst_dealloc( const Teuchos::ArrayRCP<T>& p )
01728 {
01729   p.assert_not_null();
01730   typedef RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>
01731     RCPNT;
01732   RCPNT *dnode = dynamic_cast<RCPNT*>(p.access_private_node().node_ptr());
01733   if (dnode)
01734     return &dnode->get_nonconst_dealloc();
01735   return 0;
01736 }
01737 
01738 
01739 template<class TOrig, class Embedded, class T>
01740 const Embedded& Teuchos::getEmbeddedObj( const ArrayRCP<T>& p )
01741 {
01742   typedef EmbeddedObjDealloc<TOrig,Embedded,DeallocArrayDelete<TOrig> > Dealloc_t;
01743   return get_dealloc<Dealloc_t>(p).getObj();
01744 }
01745 
01746 
01747 template<class TOrig, class Embedded, class T>
01748 Embedded& Teuchos::getNonconstEmbeddedObj( const ArrayRCP<T>& p )
01749 {
01750   typedef EmbeddedObjDealloc<TOrig,Embedded,DeallocArrayDelete<TOrig> > Dealloc_t;
01751   return get_nonconst_dealloc<Dealloc_t>(p).getNonconstObj();
01752 }
01753 
01754 
01755 template<class T>
01756 std::ostream& Teuchos::operator<<( std::ostream& out, const ArrayRCP<T>& p )
01757 {
01758   out
01759     << TypeNameTraits<ArrayRCP<T> >::name() << "{"
01760     << "ptr="<<(const void*)(p.access_private_ptr())
01761     <<",lowerOffset="<<p.lowerOffset()
01762     <<",upperOffset="<<p.upperOffset()
01763     <<",size="<<p.size()
01764     <<",node="<<p.access_private_node()
01765     <<",strong_count="<<p.strong_count()
01766     <<",weak_count="<<p.weak_count()
01767     <<"}";
01768   return out;
01769   // NOTES:
01770   // * I can't find any alternative to this C cast (problems with char data)
01771   // * Don't range check the pointer since this code does not dereference it.
01772   //   This is needed to allow printing the end() or past end() for debugging.
01773 }
01774 
01775 
01776 #endif // TEUCHOS_ARRAY_RCP_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines