Teuchos - Trilinos Tools Package Version of the Day
Loading...
Searching...
No Matches
Teuchos_ArrayRCP.hpp
1// @HEADER
2// *****************************************************************************
3// Teuchos: Common Tools Package
4//
5// Copyright 2004 NTESS and the Teuchos contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef TEUCHOS_ARRAY_RCP_HPP
11#define TEUCHOS_ARRAY_RCP_HPP
12
13
14#include "Teuchos_ArrayRCPDecl.hpp"
15#include "Teuchos_ArrayView.hpp"
16#include "Teuchos_Assert.hpp"
17#include "Teuchos_dyn_cast.hpp"
18#include "Teuchos_as.hpp"
19
20
21namespace Teuchos {
22
23
24// Helper code (not for general clients)
25
26
27template<class T> inline
28RCPNode* ArrayRCP_createNewRCPNodeRawPtr( T* p, bool has_ownership_in )
29{
30 return new RCPNodeTmpl<T,DeallocArrayDelete<T> >(
31 p, DeallocArrayDelete<T>(), has_ownership_in
32 );
33}
34
35
36template<class T, class Dealloc_T>
37inline
38RCPNode* ArrayRCP_createNewDeallocRCPNodeRawPtr(
39 T* p, Dealloc_T dealloc, bool has_ownership_in
40 )
41{
42 return new RCPNodeTmpl<T,Dealloc_T>(p, dealloc, has_ownership_in);
43}
44
45
46template<class T2, class T1>
47class ArcpReinterpretCastEmbeddedObj
48{
49public:
50 typedef T2 ptr_t;
51 ArcpReinterpretCastEmbeddedObj()
52 : arcp_pod_(null)
53 {}
54 ArcpReinterpretCastEmbeddedObj(const ArrayRCP<T1> &arcp_pod)
55 : arcp_pod_(arcpCloneNode(arcp_pod)) // Unique reference count!
56 {}
57 // NOTE: The default copy constructor is allowed and does the right thing
58 ~ArcpReinterpretCastEmbeddedObj()
59 { freeMemory(); }
60 ArcpReinterpretCastEmbeddedObj&
61 operator=(const ArcpReinterpretCastEmbeddedObj& arceo)
62 {
63 assert(is_null(arceo.arcp_pod_)); // Can only be a catestrophic programming error!
64 freeMemory();
65 return *this;
66 }
67private:
68 ArrayRCP<T1> arcp_pod_;
69 void freeMemory()
70 {
71 typedef typename ArrayRCP<T2>::iterator itr_t;
72 if (arcp_pod_.strong_count() == 1) {
73 ArrayRCP<T2> arcp2 = arcp_reinterpret_cast<T2>(arcp_pod_);
74 for (itr_t itr = arcp2.begin(); itr != arcp2.end(); ++itr) {
75 itr->~T2();
76 }
77 arcp_pod_ = null;
78 }
79 }
80};
81
82
83// Constructors/Destructors/Initializers
84
85template<class T> inline
87 : ptr_(NULL), lowerOffset_(0), upperOffset_(-1)
88{}
89
90template<class T> inline
92 : ptr_(NULL), lowerOffset_(0), upperOffset_(-1)
93{}
94
95
96template<class T> inline
98 : ptr_(0), lowerOffset_(0), upperOffset_(-1)
99{
100 *this = arcp<T>(n);
101 std::fill_n(begin(), n, val);
102}
103
104template<class T> inline
105ArrayRCP<const T>::ArrayRCP (size_type n, const T& val)
106 : ptr_(0), lowerOffset_(0), upperOffset_(-1)
107{
108 // We can't call std::fill_n on a const T*, so we have to create a
109 // nonconst array first, fill it, and then convert to const.
112}
113
114
115template<class T> inline
119 )
120 : ptr_(p),
122 node_(ArrayRCP_createNewRCPNodeRawPtr(p, has_ownership_in)),
123#endif // TEUCHOS_DEBUG
124 lowerOffset_(lowerOffset_in),
125 upperOffset_(size_in + lowerOffset_in - 1)
126{
127#ifdef TEUCHOS_DEBUG
128 if (p) {
130 if (!has_ownership_in && rcpNodeLookup==RCP_ENABLE_NODE_LOOKUP) {
132 }
133 if (existing_RCPNode) {
134 // Will not call add_new_RCPNode(...)
135 node_ = RCPNodeHandle(existing_RCPNode, RCP_WEAK, false);
136 }
137 else {
138 // Will call add_new_RCPNode(...)
139 RCPNodeThrowDeleter nodeDeleter(ArrayRCP_createNewRCPNodeRawPtr(p, has_ownership_in));
140 node_ = RCPNodeHandle(
144 );
146 }
147 }
148#else // NOT TEUCHOS_DEBUG
149 (void) rcpNodeLookup; // Silence "unused variable" compiler warning.
150#endif // TEUCHOS_DEBUG
151}
152
153template<class T> inline
155ArrayRCP (const T* p, size_type lowerOffset_in, size_type size_in,
157 : ptr_(p),
159 node_(ArrayRCP_createNewRCPNodeRawPtr(p, has_ownership_in)),
160#endif // TEUCHOS_DEBUG
161 lowerOffset_(lowerOffset_in),
162 upperOffset_(size_in + lowerOffset_in - 1)
163{
164#ifdef TEUCHOS_DEBUG
165 if (p) {
167 if (! has_ownership_in && rcpNodeLookup == RCP_ENABLE_NODE_LOOKUP) {
169 }
170 if (existing_RCPNode) {
171 // Will not call add_new_RCPNode(...)
172 node_ = RCPNodeHandle(existing_RCPNode, RCP_WEAK, false);
173 }
174 else {
175 // Will call add_new_RCPNode(...)
176 RCPNodeThrowDeleter nodeDeleter (ArrayRCP_createNewRCPNodeRawPtr (p, has_ownership_in));
177 node_ = RCPNodeHandle(
178 nodeDeleter.get (),
179 p, typeName (*p), concreteTypeName (*p),
181 );
184 }
185#else // NOT TEUCHOS_DEBUG
186 (void) rcpNodeLookup; // Silence "unused variable" compiler warning.
187#endif // TEUCHOS_DEBUG
188}
189
190
191template<class T>
192template<class Dealloc_T>
193inline
197 )
198 : ptr_(p),
200 node_(ArrayRCP_createNewDeallocRCPNodeRawPtr(p, dealloc, has_ownership_in)),
201#endif // TEUCHOS_DEBUG
202 lowerOffset_(lowerOffset_in),
203 upperOffset_(size_in + lowerOffset_in - 1)
204{
205#ifdef TEUCHOS_DEBUG
206 if (p) {
207 node_ = RCPNodeHandle(
208 ArrayRCP_createNewDeallocRCPNodeRawPtr(p, dealloc, has_ownership_in),
211 //, RCP_STRONG, false
212 );
213 }
214#endif // TEUCHOS_DEBUG
215}
216
217template<class T>
218template<class Dealloc_T>
219inline
221 const T* p, size_type lowerOffset_in, size_type size_in,
222 Dealloc_T dealloc, bool has_ownership_in
223 )
224 : ptr_(p),
225#ifndef TEUCHOS_DEBUG
226 node_(ArrayRCP_createNewDeallocRCPNodeRawPtr(p, dealloc, has_ownership_in)),
227#endif // TEUCHOS_DEBUG
228 lowerOffset_(lowerOffset_in),
229 upperOffset_(size_in + lowerOffset_in - 1)
230{
231#ifdef TEUCHOS_DEBUG
232 if (p) {
233 node_ = RCPNodeHandle(
234 ArrayRCP_createNewDeallocRCPNodeRawPtr(p, dealloc, has_ownership_in),
237 //, RCP_STRONG, false
238 );
239 }
240#endif // TEUCHOS_DEBUG
241}
242
243
244template<class T> inline
246 :ptr_(r_ptr.ptr_),
247 node_(r_ptr.node_),
248 lowerOffset_(r_ptr.lowerOffset_),
249 upperOffset_(r_ptr.upperOffset_)
250{}
251
252template<class T> inline
254 :ptr_(r_ptr.ptr_),
255 node_(r_ptr.node_),
256 lowerOffset_(r_ptr.lowerOffset_),
257 upperOffset_(r_ptr.upperOffset_)
258{}
260
261template<class T> inline
263
264template<class T> inline
266
267
268template<class T> inline
270{
271 if( this == &r_ptr )
272 return *this; // Assignment to self
273 node_ = r_ptr.access_private_node(); // May throw in debug mode!
274 ptr_ = r_ptr.ptr_;
275 lowerOffset_ = r_ptr.lowerOffset_;
276 upperOffset_ = r_ptr.upperOffset_;
277 return *this;
278 // NOTE: It is critical that the assignment of ptr_ come *after* the
279 // assignment of node_ since node_ might throw an exception!
280}
281
282template<class T> inline
285{
286 if (this == &r_ptr) {
287 return *this; // Assignment to self
289 node_ = r_ptr.access_private_node (); // May throw in debug mode!
290 ptr_ = r_ptr.ptr_;
291 lowerOffset_ = r_ptr.lowerOffset_;
292 upperOffset_ = r_ptr.upperOffset_;
293 return *this;
294 // NOTE: The assignment of ptr_ MUST come after the assignment of
295 // node_, since that line of code might throw an exception!
296}
297
298
299// Object/Pointer Access Functions
300
301
302template<class T> inline
304 return ptr_ == 0;
305}
306
307template<class T> inline
308bool ArrayRCP<const T>::is_null() const {
309 return ptr_ == 0;
310}
311
312
313template<class T> inline
315{
316 debug_assert_valid_ptr();
317 debug_assert_in_range(0,1);
318 return ptr_;
319}
321template<class T> inline
322const T* ArrayRCP<const T>::operator->() const
323{
324 debug_assert_valid_ptr();
325 debug_assert_in_range(0,1);
326 return ptr_;
328
329
330template<class T> inline
332{
333 debug_assert_valid_ptr();
334 debug_assert_in_range(0,1);
335 return *ptr_;
336}
337
338template<class T> inline
339const T& ArrayRCP<const T>::operator*() const
340{
341 debug_assert_valid_ptr();
342 debug_assert_in_range(0,1);
343 return *ptr_;
344}
345
346
347template<class T> inline
349{
350 if (ptr_) {
351 debug_assert_valid_ptr();
352 debug_assert_in_range(0,1);
353 }
354 return ptr_;
355}
356
357template<class T> inline
359{
360 if (ptr_) {
361 debug_assert_valid_ptr();
362 debug_assert_in_range(0,1);
363 }
364 return ptr_;
365}
366
367
368template<class T> inline
370 return this->get();
371}
372
373template<class T> inline
374const T* ArrayRCP<const T>::getRawPtr() const {
375 return this->get();
376}
377
379template<class T> inline
381{
382 debug_assert_valid_ptr();
383 debug_assert_in_range(offset,1);
384 return ptr_[offset];
385}
386
387template<class T> inline
389{
390 debug_assert_valid_ptr();
391 debug_assert_in_range(offset,1);
392 return ptr_[offset];
393}
394
395
396// Pointer Arithmetic Functions
397
399template<class T> inline
401{
402 debug_assert_valid_ptr();
403 ++ptr_;
404 --lowerOffset_;
405 --upperOffset_;
406 return *this;
407}
408
409template<class T> inline
411{
412 debug_assert_valid_ptr();
413 ++ptr_;
414 --lowerOffset_;
415 --upperOffset_;
416 return *this;
417}
418
419
420template<class T> inline
422{
423 debug_assert_valid_ptr();
424 ArrayRCP<T> r_ptr = *this;
425 ++(*this);
426 return r_ptr;
427}
428
429template<class T> inline
431{
432 debug_assert_valid_ptr();
433 ArrayRCP<const T> r_ptr = *this;
434 ++(*this);
435 return r_ptr;
436}
437
438
439template<class T> inline
441{
442 debug_assert_valid_ptr();
443 --ptr_;
444 ++lowerOffset_;
445 ++upperOffset_;
446 return *this;
447}
448
449template<class T> inline
451{
452 debug_assert_valid_ptr();
453 --ptr_;
454 ++lowerOffset_;
455 ++upperOffset_;
456 return *this;
457}
458
459
460template<class T> inline
462{
463 debug_assert_valid_ptr();
464 ArrayRCP<T> r_ptr = *this;
465 --(*this);
466 return r_ptr;
467}
468
469template<class T> inline
471{
472 debug_assert_valid_ptr();
473 ArrayRCP<const T> r_ptr = *this;
474 --(*this);
475 return r_ptr;
476}
477
478
479template<class T> inline
481{
482 debug_assert_valid_ptr();
483 ptr_ += offset;
484 lowerOffset_ -= offset;
485 upperOffset_ -= offset;
486 return *this;
488
489template<class T> inline
491{
492 debug_assert_valid_ptr();
493 ptr_ += offset;
494 lowerOffset_ -= offset;
495 upperOffset_ -= offset;
496 return *this;
497}
498
499
500template<class T> inline
502{
503 debug_assert_valid_ptr();
504 ptr_ -= offset;
505 lowerOffset_ += offset;
506 upperOffset_ += offset;
507 return *this;
508}
509
510template<class T> inline
512{
513 debug_assert_valid_ptr();
514 ptr_ -= offset;
515 lowerOffset_ += offset;
516 upperOffset_ += offset;
517 return *this;
518}
519
520
521template<class T> inline
528
529template<class T> inline
531{
532 ArrayRCP<const T> r_ptr = *this;
533 r_ptr+=(offset);
534 return r_ptr;
535}
536
537
538template<class T> inline
540{
541 ArrayRCP<T> r_ptr = *this;
542 r_ptr-=offset;
543 return r_ptr;
544}
545
546template<class T> inline
548{
550 r_ptr-=offset;
551 return r_ptr;
552}
553
554
555// Standard Container-Like Functions
556
557
558template<class T> inline
560{
561 debug_assert_valid_ptr();
562#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
563 return *this;
564#else
565 return ptr_;
566#endif
567}
568
569template<class T> inline
571{
572 debug_assert_valid_ptr();
573#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
574 return *this;
575#else
576 return ptr_;
577#endif
578}
579
580
581template<class T> inline
583{
584 debug_assert_valid_ptr();
585#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
586 return *this + (upperOffset_ + 1);
587#else
588 return ptr_ + (upperOffset_ + 1);
589#endif
590}
591
592template<class T> inline
594{
595 debug_assert_valid_ptr();
596#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
597 return *this + (upperOffset_ + 1);
598#else
599 return ptr_ + (upperOffset_ + 1);
600#endif
601}
602
604// ArrayRCP Views
605
606
607template<class T> inline
609{
610 if (ptr_) {
611 debug_assert_valid_ptr();
612 const T *cptr = ptr_; // Will not compile if not legal!
613 return ArrayRCP<const T>(cptr, lowerOffset_, size(), node_);
614 }
615 return null;
616}
618template<class T> inline
620 // Trivial implementation, since no need for conversion.
621 return *this;
622}
623
624
625template<class T> inline
628{
629 if (size_in == 0) {
630 return null;
631 }
632 debug_assert_valid_ptr();
633 debug_assert_in_range(lowerOffset_in, size_in);
634 ArrayRCP<T> ptr = *this;
635 ptr.ptr_ = ptr.ptr_ + lowerOffset_in;
636 ptr.lowerOffset_ = 0;
637 ptr.upperOffset_ = size_in - 1;
638 return ptr;
640
641template<class T> inline
644{
645 if (size_in == 0) {
646 return null;
647 }
648 debug_assert_valid_ptr();
649 debug_assert_in_range(lowerOffset_in, size_in);
650 ArrayRCP<const T> ptr = *this;
651 ptr.ptr_ = ptr.ptr_ + lowerOffset_in;
652 ptr.lowerOffset_ = 0;
653 ptr.upperOffset_ = size_in - 1;
654 return ptr;
655}
656
657
658// Size and extent query functions
659
660
661template<class T> inline
664{
665 debug_assert_valid_ptr();
666 return lowerOffset_;
667}
668
669template<class T> inline
672{
673 debug_assert_valid_ptr();
674 return lowerOffset_;
675}
676
677
678template<class T> inline
681{
682 debug_assert_valid_ptr();
683 return upperOffset_;
684}
685
686template<class T> inline
689{
690 debug_assert_valid_ptr();
691 return upperOffset_;
692}
693
694
695template<class T> inline
698{
699 debug_assert_valid_ptr();
700 return upperOffset_ - lowerOffset_ + 1;
701}
702
703template<class T> inline
706{
707 debug_assert_valid_ptr();
708 return upperOffset_ - lowerOffset_ + 1;
709}
710
711
712// ArrayView views
713
714
715template<class T> inline
717{
718 if (size_in == 0) {
719 return null;
720 }
721 debug_assert_valid_ptr();
722 debug_assert_in_range(lowerOffset_in,size_in);
723#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
724 return ArrayView<T>(persistingView(lowerOffset_in, size_in).create_weak());
725#else
726 return arrayView(ptr_ + lowerOffset_in, size_in);
727#endif
728 // ToDo: Implement checks for dangling references!
729}
730
731template<class T> inline
734{
735 if (size_in == 0) {
736 return null;
737 }
738 debug_assert_valid_ptr();
739 debug_assert_in_range(lowerOffset_in,size_in);
740#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
741 return ArrayView<const T>(persistingView(lowerOffset_in, size_in).create_weak());
742#else
743 return arrayView(ptr_ + lowerOffset_in, size_in);
744#endif
745 // ToDo: Implement checks for dangling references!
746}
747
748
749template<class T> inline
754
755template<class T> inline
757ArrayRCP<const T>::operator() (size_type lowerOffset_in, size_type size_in) const
758{
759 return view (lowerOffset_in, size_in);
760}
761
762
763template<class T> inline
765{
766 if (size()) {
767 return view(lowerOffset_, size());
768 }
769 return null;
770}
771
772template<class T> inline
774{
775 if (size()) {
776 return view(lowerOffset_, size());
777 }
778 return null;
779}
780
781
782// Implicit conversions
783
784
785template<class T> inline
787{
788 if (size()) {
789 return ArrayRCP<const T>(ptr_, lowerOffset_, size(), node_);
790 }
791 return null;
792}
793// The above operator does not exist in the partial specialization for
794// const T, because it doesn't make sense in that case. (Many
795// compilers warn if one tries to implement that operator, because
796// that code would never get called.)
797
798
799// std::vector like functions
800//
801// Assignment (deep copy) doesn't make sense for the "const T" partial
802// specialization, so the assignment methods (assign() and deepCopy())
803// are omitted in that case.
804
805
806template<class T> inline
808 *this = arcp<T> (n);
809 std::fill_n (this->begin (), n, val);
810}
811
812
813template<class T>
814template<class Iter>
815inline
817 const size_type new_n = std::distance (first, last);
818 if (new_n != size ()) {
819 *this = arcp<T> (new_n);
820 }
821 std::copy (first, last, begin ());
822}
823
824
825template<class T> inline
826void ArrayRCP<T>::resize(const size_type n, const T &val)
827{
828#ifdef TEUCHOS_DEBUG
829 TEUCHOS_ASSERT_EQUALITY(lowerOffset(), 0);
830#endif
831 if (n == 0) {
832 clear();
833 return;
834 }
835 const size_type orig_n = size();
836 if (n != orig_n) {
837 ArrayRCP<T> tmp = *this;
838 *this = arcp<T>(n);
839 const size_type small_n = std::min(n, orig_n);
840 for (size_type i = 0; i < small_n; ++i)
841 (*this)[i] = tmp[i];
842 for (size_type i = orig_n; i < n; ++i)
843 (*this)[i] = val;
844 upperOffset_ = n-1;
845 }
846}
847
848template<class T> inline
849void ArrayRCP<const T>::resize (const size_type n, const T& val)
850{
851#ifdef TEUCHOS_DEBUG
852 TEUCHOS_ASSERT_EQUALITY(lowerOffset(), 0);
853#endif
854 if (n == 0) {
855 clear ();
856 return;
857 }
858 const size_type orig_n = size ();
859 if (n != orig_n) {
860 ArrayRCP<const T> tmp = *this;
861 // It's not allowed to assign to the result of operator[] for a
862 // const right-hand side, so we have to assign to a temporary
863 // nonconst ArrayRCP (nonconstThis) first.
864 ArrayRCP<T> nonconstThis = arcp<T> (n);
865 const size_type small_n = std::min (n, orig_n);
866 for (size_type i = 0; i < small_n; ++i) {
867 nonconstThis[i] = tmp[i];
868 }
869 for (size_type i = orig_n; i < n; ++i) {
870 nonconstThis[i] = val;
871 }
872 *this = arcp_const_cast<const T> (nonconstThis);
873 upperOffset_ = n-1;
874 }
875}
876
877
878template<class T> inline
880 *this = null;
881}
882
883template<class T> inline
885 *this = null;
886}
887
888
889// Misc functions
890
891
892template<class T> inline
894{
895 if (av.size() == 0) {
896 *this = null;
897 return;
898 }
899 assign(av.begin(), av.end());
900}
901
902
903// Reference counting
904
905
906template<class T> inline
908 return node_.strength();
909}
910
911template<class T> inline
913 return node_.strength();
914}
915
916
917template<class T> inline
919{
920 if (ptr_)
921 return node_.is_valid_ptr();
922 return true;
923}
924
925template<class T> inline
927{
928 if (ptr_)
929 return node_.is_valid_ptr();
930 return true;
931}
932
933
934template<class T> inline
936{
937 return node_.strong_count();
938}
939
940template<class T> inline
942{
943 return node_.strong_count();
944}
945
946
947template<class T> inline
949{
950 return node_.weak_count();
951}
952
953template<class T> inline
955{
956 return node_.weak_count();
957}
958
959
960template<class T> inline
962{
963 return node_.total_count();
964}
965
966template<class T> inline
968{
969 return node_.total_count();
970}
971
972
973template<class T> inline
975{
976 node_.has_ownership(true);
977}
978
979template<class T> inline
981{
982 node_.has_ownership(true);
983}
984
985
986template<class T> inline
988{
989 return node_.has_ownership();
990}
991
992template<class T> inline
994{
995 return node_.has_ownership();
996}
997
998
999template<class T> inline
1001{
1002 debug_assert_valid_ptr();
1003 node_.has_ownership(false);
1004 return ptr_;
1005}
1006
1007template<class T> inline
1009{
1010 debug_assert_valid_ptr();
1011 node_.has_ownership(false);
1012 return ptr_;
1013}
1014
1015
1016template<class T> inline
1018 debug_assert_valid_ptr ();
1019 return ArrayRCP<T> (ptr_, lowerOffset_, size (), node_.create_weak ());
1020}
1021
1022template<class T> inline
1024 debug_assert_valid_ptr ();
1025 return ArrayRCP<const T> (ptr_, lowerOffset_, size (), node_.create_weak ());
1026}
1027
1028
1029template<class T> inline
1031 debug_assert_valid_ptr ();
1032 return ArrayRCP<T> (ptr_, lowerOffset_, size (), node_.create_strong ());
1033}
1034
1035template<class T> inline
1037 debug_assert_valid_ptr ();
1038 return ArrayRCP<const T> (ptr_, lowerOffset_, size (), node_.create_strong ());
1039}
1040
1041
1042template<class T>
1043template <class T2>
1044inline
1046{
1047 return node_.same_node (r_ptr.access_private_node ());
1048 // Note: above, r_ptr is *not* the same class type as *this so we can not
1049 // access its node_ member directly! This is an interesting detail to the
1050 // C++ protected/private protection mechanism!
1051}
1052
1053template<class T>
1054template <class T2>
1055inline
1057{
1058 return node_.same_node (r_ptr.access_private_node ());
1059 // Note: above, r_ptr is *not* the same class type as *this so we can not
1060 // access its node_ member directly! This is an interesting detail to the
1061 // C++ protected/private protection mechanism!
1062}
1063
1064
1065// Assertion Functions
1066
1067
1068template<class T> inline
1069const ArrayRCP<T>&
1071{
1072 if(!ptr_)
1073 throw_null_ptr_error(typeName(*this));
1074 return *this;
1075}
1076
1077template<class T> inline
1078const ArrayRCP<const T>&
1080{
1081 if (! ptr_) {
1082 throw_null_ptr_error (typeName (*this));
1083 }
1084 return *this;
1085}
1086
1087
1088template<class T> inline
1090{
1091 if (ptr_) {
1092 node_.assert_valid_ptr (*this);
1093 }
1094 return *this;
1095}
1096
1097template<class T> inline
1099{
1100 if (ptr_) {
1101 node_.assert_valid_ptr (*this);
1102 }
1103 return *this;
1104}
1105
1106
1107template<class T> inline
1108const ArrayRCP<T>&
1110{
1111 assert_not_null();
1113 !(
1114 (lowerOffset_ <= lowerOffset_in && lowerOffset_in+size_in-1 <= upperOffset_)
1115 &&
1116 size_in >= 0
1117 ),
1119 typeName(*this)<<"::assert_in_range:"
1120 " Error, [lowerOffset,lowerOffset+size-1] = ["
1121 <<lowerOffset_in<<","<<(lowerOffset_in+size_in-1)<<"] does not lie in the"
1122 " range ["<<lowerOffset_<<","<<upperOffset_<<"]!"
1123 );
1124 return *this;
1125}
1126
1127template<class T> inline
1128const ArrayRCP<const T>&
1130assert_in_range (size_type lowerOffset_in, size_type size_in) const
1131{
1132 assert_not_null ();
1134 !(
1135 (lowerOffset_ <= lowerOffset_in && lowerOffset_in+size_in-1 <= upperOffset_)
1136 &&
1137 size_in >= 0
1138 ),
1140 typeName (*this) << "::assert_in_range:"
1141 " Error, [lowerOffset,lowerOffset+size-1] = ["
1142 <<lowerOffset_in<<","<<(lowerOffset_in+size_in-1)<<"] does not lie in the"
1143 " range ["<<lowerOffset_<<","<<upperOffset_<<"]!"
1144 );
1145 return *this;
1146}
1147
1148
1149// very bad public functions
1150
1151
1152template<class T> inline
1153ArrayRCP<T>::ArrayRCP(
1154 T* p, size_type lowerOffset_in, size_type size_in,
1155 const RCPNodeHandle& node
1156 )
1157 :ptr_(p),
1158 node_(node),
1159 lowerOffset_(lowerOffset_in),
1160 upperOffset_(size_in + lowerOffset_in - 1)
1161{}
1162
1163template<class T> inline
1165 const T* p, size_type lowerOffset_in, size_type size_in,
1166 const RCPNodeHandle& node
1167 )
1168 :ptr_(p),
1169 node_(node),
1170 lowerOffset_(lowerOffset_in),
1171 upperOffset_(size_in + lowerOffset_in - 1)
1172{}
1173
1174
1175template<class T> inline
1176T* ArrayRCP<T>::access_private_ptr() const
1177{
1178 return ptr_;
1179}
1180
1181template<class T> inline
1182const T* ArrayRCP<const T>::access_private_ptr () const
1183{
1184 return ptr_;
1185}
1186
1187
1188template<class T> inline
1189RCPNodeHandle& ArrayRCP<T>::nonconst_access_private_node()
1190{
1191 return node_;
1192}
1193
1194template<class T> inline
1195RCPNodeHandle& ArrayRCP<const T>::nonconst_access_private_node()
1196{
1197 return node_;
1198}
1199
1200
1201template<class T> inline
1202const RCPNodeHandle& ArrayRCP<T>::access_private_node() const
1203{
1204 return node_;
1205}
1206
1207template<class T> inline
1208const RCPNodeHandle& ArrayRCP<const T>::access_private_node() const
1209{
1210 return node_;
1211}
1212
1213
1214// Array<void> and Array<const void> specializations
1215
1216
1221
1222
1224{
1226}
1227
1228
1229} // end namespace Teuchos
1230
1231
1232// ///////////////////////////////////////////
1233// Non-member functions for ArrayRCP
1234
1235
1236namespace Teuchos {
1237namespace Utilities {
1238template<class T1, class T2>
1239inline void assert_shares_resource(
1240 const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2
1241 )
1242{
1243#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1245 !p1.shares_resource(p2), IncompatibleIteratorsError,
1246 "Error, these iterators are *not* pointing to the same valid memory!"
1247 );
1248#endif
1249}
1250} // namespace Utilities
1251} // namespace Teuchos
1252
1253
1254template<class T> inline
1256Teuchos::arcp(
1257T* p, typename ArrayRCP<T>::size_type lowerOffset
1258 ,typename ArrayRCP<T>::size_type size_in
1259 ,bool owns_mem
1260 )
1261{
1262 return ArrayRCP<T>(p, lowerOffset, size_in, owns_mem);
1263}
1264
1265
1266template<class T, class Dealloc_T>
1267inline
1269Teuchos::arcp(
1270T* p, typename ArrayRCP<T>::size_type lowerOffset
1271 ,typename ArrayRCP<T>::size_type size_in
1272 ,Dealloc_T dealloc, bool owns_mem
1273 )
1274{
1275 return ArrayRCP<T>(p, lowerOffset, size_in, dealloc, owns_mem);
1276}
1277
1278
1279template<class T> inline
1281Teuchos::arcp( typename ArrayRCP<T>::size_type size )
1282{
1283#ifdef TEUCHOS_DEBUG
1284 TEUCHOS_ASSERT_INEQUALITY( size, >=, 0 );
1285#endif
1286 if (size == 0) {
1287 return null;
1288 }
1289 return ArrayRCP<T>(new T[size], 0, size, true);
1290}
1291
1292
1293template<class T> inline
1295Teuchos::arcpCloneNode(const ArrayRCP<T> &a)
1296{
1297 if (is_null(a)) {
1298 return null;
1299 }
1300 return arcpWithEmbeddedObj(a.getRawPtr(), a.lowerOffset(), a.size(),
1301 a, false);
1302}
1303
1304
1305template<class T> inline
1307Teuchos::arcpClone( const ArrayView<const T> &v )
1308{
1309 const ArrayRCP<T> new_arcp = arcp<T>(v.size());
1310 std::copy( v.begin(), v.end(), new_arcp.begin() );
1311 return new_arcp;
1312}
1313
1314
1315template<class T, class Embedded>
1317Teuchos::arcpWithEmbeddedObjPreDestroy(
1318 T* p,
1319 typename ArrayRCP<T>::size_type lowerOffset,
1320 typename ArrayRCP<T>::size_type size,
1321 const Embedded &embedded,
1322 bool owns_mem
1323 )
1324{
1325 return arcp(
1326 p, lowerOffset, size,
1327 embeddedObjDeallocArrayDelete<T>(embedded, PRE_DESTROY),
1328 owns_mem
1329 );
1330}
1331
1332
1333template<class T, class Embedded>
1335Teuchos::arcpWithEmbeddedObjPostDestroy(
1336 T* p,
1337 typename ArrayRCP<T>::size_type lowerOffset,
1338 typename ArrayRCP<T>::size_type size,
1339 const Embedded &embedded,
1340 bool owns_mem
1341 )
1342{
1343 return arcp(
1344 p, lowerOffset, size,
1345 embeddedObjDeallocArrayDelete<T>(embedded, POST_DESTROY),
1346 owns_mem
1347 );
1348}
1349
1350
1351template<class T, class Embedded>
1353Teuchos::arcpWithEmbeddedObj(
1354 T* p,
1355 typename ArrayRCP<T>::size_type lowerOffset,
1356 typename ArrayRCP<T>::size_type size,
1357 const Embedded &embedded,
1358 bool owns_mem
1359 )
1360{
1361 return arcpWithEmbeddedObjPostDestroy<T,Embedded>(
1362 p, lowerOffset, size, embedded, owns_mem );
1363}
1364
1365
1366template<class T> inline
1368Teuchos::arcp( const RCP<std::vector<T> > &v )
1369{
1370 if ( is_null(v) || !v->size() )
1371 return null;
1372 return arcpWithEmbeddedObjPostDestroy<T,RCP<std::vector<T> > >(
1373 &(*v)[0], 0, v->size(),
1374 v, false
1375 );
1376}
1377
1378
1379template<class T> inline
1381Teuchos::arcp( const RCP<const std::vector<T> > &v )
1382{
1383 if ( is_null(v) || !v->size() )
1384 return null;
1385 return arcpWithEmbeddedObjPostDestroy<const T,RCP<const std::vector<T> > >(
1386 &(*v)[0], 0, v->size(),
1387 v, false
1388 );
1389}
1390
1391
1392template<class T> inline
1394Teuchos::arcpFromArrayView(const ArrayView<T> &av)
1395{
1396#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
1397 return av.access_private_arcp();
1398#else
1399 return arcp(av.getRawPtr(), 0, av.size(), false);
1400#endif
1401}
1402
1403
1404template<class T> inline
1406Teuchos::get_std_vector( const ArrayRCP<T> &ptr )
1407{
1408 return getEmbeddedObj<T, RCP<std::vector<T> > >(ptr);
1409}
1410
1411
1412template<class T> inline
1414Teuchos::get_std_vector( const ArrayRCP<const T> &ptr )
1415{
1416 return getEmbeddedObj<const T, RCP<const std::vector<T> > >(ptr);
1417}
1418
1419
1420template<class T> inline
1421bool Teuchos::is_null( const ArrayRCP<T> &p )
1422{
1423 return p.is_null();
1424}
1425
1426
1427template<class T> inline
1428bool Teuchos::nonnull( const ArrayRCP<T> &p )
1429{
1430 return !p.is_null();
1431}
1432
1433
1434template<class T> inline
1435bool Teuchos::operator==( const ArrayRCP<T> &p, ENull )
1436{
1437 return p.is_null();
1438}
1439
1440
1441template<class T> inline
1442bool Teuchos::operator!=( const ArrayRCP<T> &p, ENull )
1443{
1444 return !p.is_null();
1445}
1446
1447
1448template<class T1, class T2>
1449inline
1450bool Teuchos::operator==( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
1451{
1452 return p1.access_private_ptr() == p2.access_private_ptr();
1453}
1454
1455
1456template<class T1, class T2>
1457inline
1458bool Teuchos::operator!=( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
1459{
1460 return p1.access_private_ptr() != p2.access_private_ptr();
1461}
1462
1463
1464template<class T1, class T2>
1465inline
1466bool Teuchos::operator<( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
1467{
1468 return p1.access_private_ptr() < p2.access_private_ptr();
1469}
1470
1471
1472template<class T1, class T2>
1473inline
1474bool Teuchos::operator<=( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
1475{
1476 Utilities::assert_shares_resource(p1,p2);
1477 return p1.access_private_ptr() <= p2.access_private_ptr();
1478}
1479
1480
1481template<class T1, class T2>
1482inline
1483bool Teuchos::operator>( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
1484{
1485 Utilities::assert_shares_resource(p1,p2);
1486 return p1.access_private_ptr() > p2.access_private_ptr();
1487}
1488
1489
1490template<class T1, class T2>
1491inline
1492bool Teuchos::operator>=( const ArrayRCP<T1> &p1, const ArrayRCP<T2> &p2 )
1493{
1494 Utilities::assert_shares_resource(p1,p2);
1495 return p1.access_private_ptr() >= p2.access_private_ptr();
1496}
1497
1498
1499template<class T>
1501Teuchos::operator-( const ArrayRCP<T> &p1, const ArrayRCP<T> &p2 )
1502{
1503 Utilities::assert_shares_resource(p1,p2);
1504 return p1.access_private_ptr() - p2.access_private_ptr();
1505}
1506
1507
1508template<class T2, class T1>
1509inline
1511Teuchos::arcp_reinterpret_cast(const ArrayRCP<T1>& p1)
1512{
1513 typedef typename ArrayRCP<T1>::size_type size_type;
1514 const int sizeOfT1 = sizeof(T1);
1515 const int sizeOfT2 = sizeof(T2);
1516 size_type lowerOffset2 = (p1.lowerOffset()*sizeOfT1) / sizeOfT2;
1517 size_type upperOffset2 = ((p1.upperOffset()+1)*sizeOfT1) / sizeOfT2 - 1;
1518 T2 *ptr2 = reinterpret_cast<T2*>(p1.get());
1519 return ArrayRCP<T2>(
1520 ptr2, lowerOffset2, upperOffset2 - lowerOffset2 + 1,
1521 p1.access_private_node()
1522 );
1523 // Note: Above is just fine even if p1.get()==NULL!
1524}
1525
1526
1527template<class T2, class T1>
1529Teuchos::arcp_reinterpret_cast_nonpod(const ArrayRCP<T1>& p1, const T2& val)
1530{
1531 typedef typename ArrayRCP<T2>::iterator itr_t;
1532 ArrayRCP<T2> arcp2 = arcp_reinterpret_cast<T2>(p1);
1533 for (itr_t itr = arcp2.begin(); itr != arcp2.end(); ++itr) {
1534 new (&*itr) T2(val);
1535 }
1536 return arcpWithEmbeddedObj(
1537 arcp2.getRawPtr(), 0, arcp2.size(),
1538 ArcpReinterpretCastEmbeddedObj<T2, T1>(p1),
1539 false);
1540 // Above, the ownership of the memory is totally owned by the embedded
1541 // object and the default deallocator policy object does not do anything.
1542 // This is just fine.
1543}
1544
1545
1546template<class T2, class T1>
1547inline
1549Teuchos::arcp_const_cast(const ArrayRCP<T1>& p1)
1550{
1551 T2 *ptr2 = const_cast<T2*>(p1.get());
1552 return ArrayRCP<T2>(
1553 ptr2, p1.lowerOffset(), p1.size(),
1554 p1.access_private_node()
1555 );
1556 // Note: Above is just fine even if p1.get()==NULL!
1557}
1558
1559
1560template<class T2, class T1>
1561inline
1563Teuchos::arcp_implicit_cast(const ArrayRCP<T1>& p1)
1564{
1565 T2 * raw_ptr2 = p1.get();
1566 return ArrayRCP<T2>(
1567 raw_ptr2, p1.lowerOffset(), p1.size(),
1568 p1.access_private_node()
1569 );
1570 // Note: Above is just fine even if p1.get()==NULL!
1571}
1572
1573
1574template<class T1, class T2>
1575inline
1576void Teuchos::set_extra_data(
1577 const T1 &extra_data, const std::string& name,
1578 const Ptr<ArrayRCP<T2> > &p, EPrePostDestruction destroy_when,
1579 bool force_unique
1580 )
1581{
1582 p->assert_not_null();
1583 p->nonconst_access_private_node().set_extra_data( any(extra_data), name, destroy_when,
1584 force_unique );
1585}
1586
1587
1588template<class T1, class T2>
1589inline
1590T1& Teuchos::get_extra_data( ArrayRCP<T2>& p, const std::string& name )
1591{
1592 p.assert_not_null();
1593 return any_cast<T1>(
1594 p.nonconst_access_private_node().get_extra_data(
1595 TypeNameTraits<T1>::name(), name
1596 )
1597 );
1598}
1599
1600
1601template<class T1, class T2>
1602inline
1603const T1& Teuchos::get_extra_data( const ArrayRCP<T2>& p, const std::string& name )
1604{
1605 p.assert_not_null();
1606 return any_cast<T1>(
1607 p.access_private_node().get_extra_data(
1608 TypeNameTraits<T1>::name() ,name
1609 )
1610 );
1611}
1612
1613
1614template<class T1, class T2>
1615inline
1616T1* Teuchos::get_optional_extra_data( ArrayRCP<T2>& p, const std::string& name )
1617{
1618 p.assert_not_null();
1619 any *extra_data = p.nonconst_access_private_node().get_optional_extra_data(
1620 TypeNameTraits<T1>::name(), name);
1621 if( extra_data ) return &any_cast<T1>(*extra_data);
1622 return NULL;
1623}
1624
1625
1626template<class T1, class T2>
1627inline
1628const T1* Teuchos::get_optional_extra_data( const ArrayRCP<T2>& p, const std::string& name )
1629{
1630 p.assert_not_null();
1631 any *extra_data = p.access_private_node().get_optional_extra_data(
1632 TypeNameTraits<T1>::name(), name);
1633 if( extra_data ) return &any_cast<T1>(*extra_data);
1634 return NULL;
1635}
1636
1637
1638template<class Dealloc_T, class T>
1639inline
1640const Dealloc_T&
1641Teuchos::get_dealloc( const ArrayRCP<T>& p )
1642{
1643 return get_nonconst_dealloc<Dealloc_T>(p);
1644}
1645
1646
1647template<class Dealloc_T, class T>
1648inline
1649Dealloc_T&
1650Teuchos::get_nonconst_dealloc( const Teuchos::ArrayRCP<T>& p )
1651{
1652 typedef RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T> requested_type;
1653 p.assert_not_null();
1654 RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>
1655 *dnode = dynamic_cast<RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>*>(
1656 p.access_private_node().node_ptr());
1658 dnode==NULL, NullReferenceError
1659 ,"get_dealloc<" << TypeNameTraits<Dealloc_T>::name()
1660 << "," << TypeNameTraits<T>::name() << ">(p): "
1661 << "Error, requested type \'" << TypeNameTraits<requested_type>::name()
1662 << "\' does not match actual type of the node \'"
1663 << typeName(*p.access_private_node().node_ptr()) << "!"
1664 );
1665 return dnode->get_nonconst_dealloc();
1666}
1667
1668
1669template<class Dealloc_T, class T>
1670inline
1671const Dealloc_T*
1672Teuchos::get_optional_dealloc( const ArrayRCP<T>& p )
1673{
1674 return get_optional_dealloc<Dealloc_T>(p);
1675}
1676
1677
1678template<class Dealloc_T, class T>
1679inline
1680Dealloc_T*
1681Teuchos::get_optional_nonconst_dealloc( const Teuchos::ArrayRCP<T>& p )
1682{
1683 p.assert_not_null();
1684 typedef RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>
1685 RCPNT;
1686 RCPNT *dnode = dynamic_cast<RCPNT*>(p.access_private_node().node_ptr());
1687 if (dnode)
1688 return &dnode->get_nonconst_dealloc();
1689 return 0;
1690}
1691
1692
1693template<class TOrig, class Embedded, class T>
1694const Embedded& Teuchos::getEmbeddedObj( const ArrayRCP<T>& p )
1695{
1696 typedef EmbeddedObjDealloc<TOrig,Embedded,DeallocArrayDelete<TOrig> > Dealloc_t;
1697 return get_dealloc<Dealloc_t>(p).getObj();
1698}
1699
1700
1701template<class TOrig, class Embedded, class T>
1702Embedded& Teuchos::getNonconstEmbeddedObj( const ArrayRCP<T>& p )
1703{
1704 typedef EmbeddedObjDealloc<TOrig,Embedded,DeallocArrayDelete<TOrig> > Dealloc_t;
1705 return get_nonconst_dealloc<Dealloc_t>(p).getNonconstObj();
1706}
1707
1708
1709template<class T>
1710std::ostream& Teuchos::operator<<( std::ostream& out, const ArrayRCP<T>& p )
1711{
1712 // mfh 15 Sep 2015: Make sure that NULL pointers print consistently.
1713 // Clang 3.5 likes to print an empty string in that case, while GCC
1714 // prints 0. Thus, we test if the pointer is NULL and print 0 in
1715 // that case. This is important for MueLu tests, which compare
1716 // string print-outs.
1717 out
1718 << TypeNameTraits<ArrayRCP<T> >::name() << "{"
1719 << "ptr=";
1720 if (p.access_private_ptr () == NULL) {
1721 out << "0";
1722 } else {
1723 out << (const void*) (p.access_private_ptr ());
1724 }
1725 out
1726 <<",lowerOffset="<<p.lowerOffset()
1727 <<",upperOffset="<<p.upperOffset()
1728 <<",size="<<p.size()
1729 <<",node=" << p.access_private_node ()
1730 <<",strong_count="<<p.strong_count()
1731 <<",weak_count="<<p.weak_count()
1732 <<"}";
1733 return out;
1734 // NOTES:
1735 // * I can't find any alternative to this C cast (problems with char data)
1736 // * Don't range check the pointer since this code does not dereference it.
1737 // This is needed to allow printing the end() or past end() for debugging.
1738}
1739
1740
1741#endif // TEUCHOS_ARRAY_RCP_HPP
Definition of Teuchos::as, for conversions between types.
Reference-counted smart pointer for managing arrays.
Ordinal size_type
Type representing the number of elements in an ArrayRCP or view thereof.
Ordinal difference_type
Type representing the difference between two size_type values.
bool has_ownership() const
Returns true if this has ownership of object pointed to by this->get() in order to deallocate it.
T * iterator
Nonconstant iterator type used if bounds checking is disabled.
ArrayRCP(ENull null_arg=null)
Default constructor; initialize to an empty array.
int strong_count() const
Return the number of active RCP<> objects that have a "strong" reference to the underlying reference-...
bool is_valid_ptr() const
Return whether the underlying object pointer is still valid.
iterator begin() const
Return an iterator to beginning of the array of data.
ERCPStrength strength() const
Strength of the pointer.
const ArrayRCP< T > & assert_valid_ptr() const
If the object pointer is non-null, assert that it is still valid.
int weak_count() const
Return the number of active RCP<> objects that have a "weak" reference to the underlying reference-co...
int total_count() const
Total count (strong_count() + weak_count()).
Handle class that manages the RCPNode's reference counting.
Deletes a (non-owning) RCPNode but not it's underlying object in case of a throw.
static RCPNode * getExistingRCPNode(T *p)
Return a raw pointer to an existing owning RCPNode given the address to the underlying object if it e...
Node class to keep track of address and the reference count for a reference-counted utility class and...
Smart reference counting pointer class for automatic garbage collection.
RCP< T > create_weak() const
Create a new weak RCP object from another (strong) RCP object.
Ptr< T > release()
Release the ownership of the underlying dynamically allocated object.
Dealloc_T & get_nonconst_dealloc(const RCP< T > &p)
Return a non-const reference to the underlying deallocator object.
bool is_null() const
Returns true if the underlying pointer is null.
const RCP< T > & assert_not_null() const
Throws NullReferenceError if this->get()==NULL, otherwise returns reference to *this.
RCP< T > create_strong() const
Create a new strong RCP object from another (weak) RCP object.
T * get() const
Get the raw C++ pointer to the underlying object.
int weak_count() const
Return the number of active RCP<> objects that have a "weak" reference to the underlying reference-co...
int strong_count() const
Return the number of active RCP<> objects that have a "strong" reference to the underlying reference-...
Range error exception class.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
This macro is designed to be a short version of TEUCHOS_TEST_FOR_EXCEPTION() that is easier to call.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
#define TEUCHOS_ASSERT_INEQUALITY(val1, comp, val2)
This macro is checks that an inequality between two numbers is satisified and if not then throws a go...
#define TEUCHOS_ASSERT_EQUALITY(val1, val2)
This macro is checks that to numbers are equal and if not then throws an exception with a good error ...
bool is_null(const std::shared_ptr< T > &p)
Returns true if p.get()==NULL.
bool nonnull(const std::shared_ptr< T > &p)
Returns true if p.get()!=NULL.
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.
std::string concreteTypeName(const T &t)
Template function for returning the type name of the actual concrete name of a passed-in object.
ERCPStrength
Used to specify if the pointer is weak or strong.
ERCPNodeLookup
Used to determine if RCPNode lookup is performed or not.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...