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