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