Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RCP_test.cpp
Go to the documentation of this file.
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 #include "Teuchos_RCP.hpp"
15 #include "Teuchos_Assert.hpp"
16 #include "Teuchos_getConst.hpp"
17 #include "Teuchos_Version.hpp"
18 
19 #ifdef HAVE_TEUCHOS_BOOST
21 #endif
22 
23 #include "TestClasses.hpp"
24 
25 
26 //
27 // Uncomment these macros to see example errors
28 //
29 
30 //#define SHOW_COMPILE_TIME_ERRORS
31 //#define SHOW_RUN_TIME_ERROR_1
32 //#define SHOW_RUN_TIME_ERROR_2
33 //#define SHOW_RUN_TIME_ERROR_3
34 //#define SHOW_RUN_TIME_ERROR_4
35 #define SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS
36 #define SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS_PRINT
37 //#define SHOW_MEMORY_LEAK_1
38 
39 //
40 // This program prints minimal output to standard error
41 //
42 
43 int main( int argc, char* argv[] ) {
44 
45  using Teuchos::RCP;
47  using Teuchos::deallocFunctorDelete;
48  using Teuchos::deallocFunctorHandleDelete;
49  using Teuchos::null;
50  using Teuchos::rcp;
51  using Teuchos::rcpFromRef;
52  using Teuchos::inOutArg;
53  using Teuchos::is_null;
54  using Teuchos::rcp_implicit_cast;
55  using Teuchos::rcp_const_cast;
56  using Teuchos::rcp_static_cast;
57  using Teuchos::rcp_dynamic_cast;
58  using Teuchos::set_extra_data;
59  using Teuchos::get_extra_data;
60  using Teuchos::get_nonconst_extra_data;
61  using Teuchos::get_optional_extra_data;
62  using Teuchos::get_optional_nonconst_extra_data;
63  using Teuchos::get_dealloc;
64  using Teuchos::get_nonconst_dealloc;
65  using Teuchos::get_optional_dealloc;
66  using Teuchos::get_optional_nonconst_dealloc;
67  using Teuchos::rcpWithEmbeddedObj;
68  using Teuchos::rcpWithEmbeddedObjPreDestroy;
69  using Teuchos::rcpWithEmbeddedObjPostDestroy;
70  using Teuchos::getEmbeddedObj;
71  using Teuchos::getNonconstEmbeddedObj;
72  using Teuchos::getConst;
74 
75  bool success = true;
76  bool createCircRefs = false; // Don't create memory leak by default!
77 
78  Teuchos::GlobalMPISession mpiSession(&argc,&argv);
79  const int procRank = Teuchos::GlobalMPISession::getRank();
80 
81  Teuchos::oblackholestream blackhole;
82  std::ostream &out = ( procRank == 0 ? std::cout : blackhole );
83 
84  try {
85 
86  // Read options from the commandline
87  CommandLineProcessor clp(false); // Don't throw exceptions
88  clp.setOption( "create-circ-refs", "no-create-circ-refs", &createCircRefs,
89  "Set if output is printed or not." );
90  CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
91  if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) {
92  out << "\nEnd Result: TEST FAILED" << std::endl;
93  return parse_return;
94  }
95 
96  blackhole << "\nThis should not print anywhere.\n";
97 
98  out << std::endl << Teuchos::Teuchos_Version() << std::endl;
99 
100  out << "\nTesting basic RCP functionality ...\n";
101 
102  // Create some smart pointers
103 
104  RCP<A> a_ptr1 = rcp(new C);
105  out << "\na_ptr1 = " << a_ptr1 << "\n";
106  // RAB: 2003/11/24: The Sun compiler ("Forte Developer 7 C++
107  // 5.4 2002/03/09" returned from CC -V) does not seem to be
108  // following the standard when it comes to the handling of
109  // temporary objects and therefore the count() is not currect.
110  // In the above statement, at least one and perhaps two
111  // temporary RCP objects are created before the object
112  // a_ptr1 is initialized. However, the standard says that the
113  // lifetime of temprary objects must not extend past the
114  // statement in which it was created (see section 10.4.10 in
115  // Stroustroup, 3ed edition). This compiler stinks!!!!!
116  TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.strong_count() != 1 );
117  TEUCHOS_TEST_FOR_EXCEPT( !a_ptr1.shares_resource(a_ptr1) );
118  TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.ptr() == null );
119  TEUCHOS_TEST_FOR_EXCEPT( a_ptr1 == null );
120  TEUCHOS_TEST_FOR_EXCEPT( !(a_ptr1 != null) );
121  TEUCHOS_TEST_FOR_EXCEPT( is_null(a_ptr1) );
122  RCP<D> d_ptr1 = rcp(new E);
123  TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.shares_resource(a_ptr1) );
124  TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.strong_count() != 1 );
125  TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.get() == NULL);
126  TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.getRawPtr() == NULL);
127 
128  {
129 
130  // Create some more smart points (no new memory!)
131 
132  const RCP<const A> ca_ptr1 = rcp_const_cast<const A>(a_ptr1);
133  TEUCHOS_TEST_FOR_EXCEPT( !(ca_ptr1 == a_ptr1) );
134  TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1 != a_ptr1 );
135  TEUCHOS_TEST_FOR_EXCEPT( !ca_ptr1.shares_resource(a_ptr1) );
136  TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.strong_count() != 2 );
137  TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1.ptr() == null );
138  TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1.strong_count() != 2 );
139  const RCP<const D> cd_ptr1 = rcp_const_cast<const D>(d_ptr1);
140  TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.strong_count() != 2 );
141  TEUCHOS_TEST_FOR_EXCEPT( cd_ptr1.ptr() == null );
142  TEUCHOS_TEST_FOR_EXCEPT( cd_ptr1.strong_count() != 2 );
143 
144 #ifdef SHOW_RUN_TIME_ERROR_1
145  // Conversion using get() is a no no! When a_ptr2 is deleted so will the allocated
146  // object and then a_ptr1 will be corrupted after this block ends!
147  const RCP<A> a_ptr2 = a_ptr1.get();
148 #endif
149 
150  // Test assignment functions
151 
152  a_ptr1 = rcp_const_cast<A>(ca_ptr1.assert_not_null()); // Should be okay, assignment to self
153 
154 #ifdef SHOW_COMPILE_TIME_ERRORS
155  ca_ptr1 = ca_ptr1; // Should not compile since ca_ptr1 is declared constant
156  ca_ptr1->A_g(); // Should not compile since A_g() is a non-const member function
157 #endif
158 
159  // Test function calls through operaor->(...)
160 
161  TEUCHOS_TEST_FOR_EXCEPT( a_ptr1->A_g() != A_g_return );
162  TEUCHOS_TEST_FOR_EXCEPT( a_ptr1->A_f() != A_f_return );
163  TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1->A_f() != A_f_return );
164  TEUCHOS_TEST_FOR_EXCEPT( d_ptr1->D_g() != D_g_return );
165  TEUCHOS_TEST_FOR_EXCEPT( d_ptr1->D_f() != D_f_return );
166  TEUCHOS_TEST_FOR_EXCEPT( cd_ptr1->D_f() != D_f_return );
167 
168  // Test funciton calls through operator*(...)
169 
170  TEUCHOS_TEST_FOR_EXCEPT( (*a_ptr1).A_g() != A_g_return );
171  TEUCHOS_TEST_FOR_EXCEPT( (*a_ptr1).A_f() != A_f_return );
172  TEUCHOS_TEST_FOR_EXCEPT( (*ca_ptr1).A_f() != A_f_return );
173  TEUCHOS_TEST_FOR_EXCEPT( (*d_ptr1).D_g() != D_g_return );
174  TEUCHOS_TEST_FOR_EXCEPT( (*d_ptr1).D_f() != D_f_return );
175  TEUCHOS_TEST_FOR_EXCEPT( (*cd_ptr1).D_f() != D_f_return );
176 
177  // Test dynamic and static conversions
178 
179  // Cast down the inheritance hiearchy (const A -> const B1)
180  const RCP<const B1> cb1_ptr1 = rcp_dynamic_cast<const B1>(ca_ptr1);
181  TEUCHOS_TEST_FOR_EXCEPT( cb1_ptr1.ptr() == null );
182  TEUCHOS_TEST_FOR_EXCEPT( cb1_ptr1.strong_count() != 3 );
183  TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1.strong_count() != 3 );
184  TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.strong_count() != 3 );
185 
186  // Cast up the inheritance hiearchy (const B1 -> const A)
187  TEUCHOS_TEST_FOR_EXCEPT( rcp_implicit_cast<const A>(cb1_ptr1)->A_f() != A_f_return );
188  TEUCHOS_TEST_FOR_EXCEPT( RCP<const A>(cb1_ptr1)->A_f() != A_f_return );
189  // Implicit cast from const to non-const (A -> const A)
190  TEUCHOS_TEST_FOR_EXCEPT( rcp_implicit_cast<const A>(a_ptr1)->A_f() != A_f_return );
191  TEUCHOS_TEST_FOR_EXCEPT( RCP<const A>(a_ptr1)->A_f() != A_f_return );
192  // Cast away constantness (const B1 -> B1)
193  TEUCHOS_TEST_FOR_EXCEPT( rcp_const_cast<B1>(cb1_ptr1)->B1_g() != B1_g_return );
194  // Cast across the inheritance hiearchy (const B1 -> const B2)
195  TEUCHOS_TEST_FOR_EXCEPT( rcp_dynamic_cast<const B2>(cb1_ptr1)->B2_f() != B2_f_return );
196  // Cast down the inheritance hiearchy (const B1 -> const C)
197  TEUCHOS_TEST_FOR_EXCEPT( rcp_dynamic_cast<const C>(cb1_ptr1)->C_f() != C_f_return );
198 
199  // Cast away constantness (const C -> C)
200  const RCP<C>
201  c_ptr1 = rcp_const_cast<C>(rcp_dynamic_cast<const C>(ca_ptr1));
202  TEUCHOS_TEST_FOR_EXCEPT( c_ptr1.ptr() == null );
203  TEUCHOS_TEST_FOR_EXCEPT( c_ptr1.strong_count() != 4 );
204  TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1.strong_count() != 4 );
205  TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.strong_count() != 4 );
206 
207  // Cast down the inheritance hiearchy using static_cast<...> (const D -> const E)
208  const RCP<const E>
209  ce_ptr1 = rcp_static_cast<const E>(cd_ptr1); // This is not checked at runtime!
210  TEUCHOS_TEST_FOR_EXCEPT( ce_ptr1.ptr() == null);
211  TEUCHOS_TEST_FOR_EXCEPT( ce_ptr1.strong_count() != 3 );
212  TEUCHOS_TEST_FOR_EXCEPT( cd_ptr1.strong_count() != 3 );
213  TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.strong_count() != 3 );
214 
215  // Cast up the inheritance hiearchy (const E -> const D)
216  TEUCHOS_TEST_FOR_EXCEPT( rcp_implicit_cast<const D>(ce_ptr1)->D_f() != D_f_return );
217  // Cast away constantness (const E -> E)
218  TEUCHOS_TEST_FOR_EXCEPT( rcp_const_cast<E>(ce_ptr1)->E_g() != E_g_return );
219  TEUCHOS_TEST_FOR_EXCEPT( ce_ptr1->D_f() != D_f_return );
220 
221 #ifdef SHOW_COMPILE_TIME_ERRORS
222  // Try to cast down inheritance hiearchy using dynamic_cast<...> (const D -> const E)
223  rcp_dynamic_cast<const E>( cd_ptr1 )->E_f(); // This should not compile since D and E are not polymophic
224 #endif
225 
226 #ifndef _INTEL // Intel compiler does not seem to be doing dynamic cast correctly?
227 #ifdef TEUCHOS_DEBUG // operator->() only throws std::exception when TEUCHOS_DEBUG is defined
228  try {
229  // Try to cast form one interface to another that is not supported (B2 -> B1).
230  // The RCP<B1> returned from rcp_dynamic_cast<...> should be null!
231  // Note that RCP<...>::optertor->() should throw an std::exception in debug
232  // mode (i.e. TEUCHOS_DEBUG is defined) but even so no memory leak occurs. If you
233  // don't believe me then step through with a debugger and see for yourself.
234  TEUCHOS_TEST_FOR_EXCEPT( rcp_dynamic_cast<B1>( rcp(new B2) )->B1_g() != B1_g_return );
235  return -1; // Should not be executed!
236  }
237  catch( const std::logic_error &excpt )
238  {}
239 #endif
240  try {
241  // Try to cast form one interface to another that is not supported (B2 -> B1).
242  // Note that rcp_dynamic_cast<B1>(...,true) should throw an std::exception but even
243  // so no memory leak occurs. If you don't believe me then step through with a
244  // debugger and see for yourself.
245  rcp_dynamic_cast<B1>( rcp(new B2), true );
246  return -1; // Should not be executed!
247  }
248  catch( const std::bad_cast &excpt )
249  {}
250 #endif
251 
252  // Manually clean up some memory
253 
254  delete d_ptr1.release().get(); // Now d_ptr1.get() no longer points to a valid object but okay
255  // as long as no other access to this object is attempted! (see below)
256 #ifdef SHOW_RUN_TIME_ERROR_2
257  TEUCHOS_TEST_FOR_EXCEPT( d_ptr1->D_g() == D_g_return ); // Should cause a segmentation fault since d_ptr.get() was deleted!
258 #endif
259 
260 #ifdef SHOW_MEMORY_LEAK_1
261  a_ptr1.release(); // If we release but do not delete manually then this is a memory leak!
262 #endif
263 
264  // Here at the end of the block, all of the other smart pointers are deleted!
265  }
266  // Check that all of the other references where removed but these
267  TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.strong_count() != 1 );
268  TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.strong_count() != 1 );
269 
270  // Assign some other dynamically created objects.
271 
272  a_ptr1 = rcp(new A); // In each case the current dynamically allocated object is deleted ...
273  a_ptr1 = rcp(new B1); // before the new reference is set.
274  a_ptr1 = rcp(new B2); // ""
275  a_ptr1 = rcp(new C); // ""
276  d_ptr1 = rcp(new D); // ""
277  d_ptr1 = rcp(new E); // ""
278 
279  // Assign pointers to some automatic objects that do not need deleted.
280  // We can do this but we need to remove ownership of the pointer
281  // from the smart pointer objects so that they do not try to
282  // delete them. If we forget then delete will be called on these
283  // pointers and will cause a runtime error.
284 
285  C c; // Automatic object what will be deleted by compiler at end of block
286  a_ptr1 = rcp(&c);
287 #ifndef SHOW_RUN_TIME_ERROR_3
288  // Release ownership so that a_ptr1 will not try to delete &c when a_ptr1 goes out of scope
289  a_ptr1.release();
290 #endif
291 
292  E e; // Automatic object what will be deleted by compiler at end of block
293  d_ptr1 = rcp(&e);
294 #ifndef SHOW_RUN_TIME_ERROR_4
295  // Release ownership so that d_ptr1 will not try to delete &e when a_ptr1 goes out of scope
296  d_ptr1.release();
297 #endif
298 
299 #ifdef SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS
300  // Allocate an using new and then store the non-base address in in
301  // a RCP and then try to delete (this is a no-no usually).
302  C *c_ptr5 = new C; // Okay, no type info lost and address should be same as returned from malloc(...)
303 #ifdef SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS_PRINT
304  const void *c_ptr5_base = dynamic_cast<void*>(c_ptr5);
305  out << "\nSize of C = " << sizeof(C) << std::endl;
306  out << "Base address of object of type C = " << dynamic_cast<void*>(c_ptr5) << std::endl;
307  out << "Offset to address of object of type C = " << ((long int)c_ptr5 - (long int)c_ptr5_base) << std::endl;
308  out << "Offset of B1 object in object of type C = " << ((long int)static_cast<B1*>(c_ptr5) - (long int)c_ptr5_base) << std::endl;
309  out << "Offset of B2 object in object of type C = " << ((long int)static_cast<B2*>(c_ptr5) - (long int)c_ptr5_base) << std::endl;
310  out << "Offset of A object in object of type C = " << ((long int)static_cast<A*>(c_ptr5) - (long int)c_ptr5_base) << std::endl;
311 #endif // SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS_PRINT
312  A *a_rptr5 = c_ptr5; // Here the address has changed and is no longer the same as the base address
313  a_ptr1 = rcp(a_rptr5); // This is a no-no and could cause trouble!
314  a_ptr1 = null; // This will cause a segmentation fault in free(...) on many platforms
315 #endif // SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS
316 
317  // Test out getting the deallocator object
318  a_ptr1 = rcpWithDealloc( new C, DeallocDelete<C>() );
319  get_dealloc<DeallocDelete<C> >(a_ptr1);
320  get_nonconst_dealloc<DeallocDelete<C> >(a_ptr1);
321  TEUCHOS_TEST_FOR_EXCEPT( get_optional_nonconst_dealloc<DeallocDelete<C> >(a_ptr1)==null );
322  TEUCHOS_TEST_FOR_EXCEPT( get_optional_nonconst_dealloc<DeallocDelete<A> >(a_ptr1)!=null );
323  TEUCHOS_TEST_FOR_EXCEPT( get_optional_dealloc<DeallocDelete<C> >(const_cast<const RCP<A>&>(a_ptr1))==null );
324  TEUCHOS_TEST_FOR_EXCEPT( get_optional_dealloc<DeallocDelete<A> >(const_cast<const RCP<A>&>(a_ptr1))!=null );
325 
326  // Test storing extra data and then getting it out again
327  TEUCHOS_TEST_FOR_EXCEPT( get_optional_nonconst_extra_data<RCP<B1> >(a_ptr1,"blahblah") != null );
328  TEUCHOS_TEST_FOR_EXCEPT( get_optional_extra_data<int>(const_cast<const RCP<A>&>(a_ptr1),"blahblah") != null ); // test const version
329  set_extra_data( int(-5), "int", inOutArg(a_ptr1) );
330  TEUCHOS_TEST_FOR_EXCEPT( get_extra_data<int>(a_ptr1,"int") != -5 );
331  TEUCHOS_TEST_FOR_EXCEPT( get_nonconst_extra_data<int>(a_ptr1,"int") != -5 );
332  set_extra_data( rcp(new B1), "B1", inOutArg(a_ptr1) );
333  TEUCHOS_TEST_FOR_EXCEPT( get_extra_data<RCP<B1> >(a_ptr1,"B1")->B1_f() != B1_f_return );
334  TEUCHOS_TEST_FOR_EXCEPT( get_extra_data<int>(const_cast<const RCP<A>&>(a_ptr1),"int") != -5 ); // test const version
335  TEUCHOS_TEST_FOR_EXCEPT( (*get_optional_extra_data<RCP<B1> >(a_ptr1,"B1"))->B1_f() != B1_f_return );
336  TEUCHOS_TEST_FOR_EXCEPT( *get_optional_extra_data<int>(const_cast<const RCP<A>&>(a_ptr1),"int") != -5 ); // test const version
337  TEUCHOS_TEST_FOR_EXCEPT( get_optional_extra_data<RCP<B1> >(a_ptr1,"blahblah") != null );
338  TEUCHOS_TEST_FOR_EXCEPT( get_optional_extra_data<int>(const_cast<const RCP<A>&>(a_ptr1),"blahblah") != null ); // test const version
339 
340  // Test storage of extra data as embedded objects and then getting it out
341  // again
342 
343  {
344  RCP<A> a_ptr = rcpWithEmbeddedObj(new C,int(-5));
345  const int intRtn1 = getEmbeddedObj<C,int>(a_ptr);
346  TEUCHOS_TEST_FOR_EXCEPT( intRtn1 != -5 );
347  getNonconstEmbeddedObj<C,int>(a_ptr) = -4;
348  const int intRtn2 = getEmbeddedObj<C,int>(a_ptr);
349  TEUCHOS_TEST_FOR_EXCEPT( intRtn2 != -4 );
350  }
351 
352  {
353  RCP<A> a_ptr = rcpWithEmbeddedObjPreDestroy(new C,int(-5));
354  const int intRtn1 = getEmbeddedObj<C,int>(a_ptr);
355  TEUCHOS_TEST_FOR_EXCEPT( intRtn1 != -5 );
356  getNonconstEmbeddedObj<C,int>(a_ptr) = -4;
357  const int intRtn2 = getEmbeddedObj<C,int>(a_ptr);
358  TEUCHOS_TEST_FOR_EXCEPT( intRtn2 != -4 );
359  }
360 
361  {
362  RCP<A> a_ptr = rcpWithEmbeddedObjPostDestroy(new C,int(-5));
363  const int intRtn1 = getEmbeddedObj<C,int>(a_ptr);
364  TEUCHOS_TEST_FOR_EXCEPT( intRtn1 != -5 );
365  getNonconstEmbeddedObj<C,int>(a_ptr) = -4;
366  const int intRtn2 = getEmbeddedObj<C,int>(a_ptr);
367  TEUCHOS_TEST_FOR_EXCEPT( intRtn2 != -4 );
368  }
369 
370  // Test pre-destruction of extra data
371  int a_f_return = -2;
372  set_extra_data( rcp(new Get_A_f_return(&*a_ptr1,&a_f_return)),
373  "a_f_return", inOutArg(a_ptr1), Teuchos::PRE_DESTROY );
374 
375  // Set pointers to null to force releasing any owned memory
376  a_ptr1 = null;
377  d_ptr1 = null;
378 
379  // RAB: 2004/08/12: It appears that SUN compiler is not deleting the piece of extra
380  // data properly and therefore the destructor of the above Get_A_f_return object
381  // is not being called (which sets the value of af_return). This compiler stinks!
382  TEUCHOS_TEST_FOR_EXCEPT( a_f_return != A_f_return ); // Should be been called in destructor of a_ptr1 but before the A object is destroyed!
383 
384  // Testing the deallocFunctorDelete function and DeallocFunctorDelete class
385  a_ptr1 = rcpWithDealloc( new C, deallocFunctorDelete<A>(deallocA) );
386  a_ptr1 = null;
387 
388  // Testing the deallocFunctorHandleDelete function and DeallocFunctorHandleDelete class
389  a_ptr1 = rcpWithDealloc( new C, deallocFunctorHandleDelete<A>(deallocHandleA) );
390  a_ptr1 = null;
391 
392 #ifdef TEUCHOS_DEBUG
393 
394  if (createCircRefs) {
395  out << "\nCreate a circular reference that will cause a memory leak! ...\n";
396 # if !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
397  // Only trun on tracing if you have to
398  Teuchos::RCPNodeTracer::setTracingActiveRCPNodes(true);
399 # endif
400  RCP<A> a = rcp(new A());
401  RCP<C> c2 = rcp(new C());
402  a->set_C(c2);
403  c2->set_A(a);
404  }
405 
406 #endif // TEUCHOS_DEBUG
407 
408 #ifndef TEUCHOS_DEBUG
409 
410  out << "\nTesting using RCP to wrap an undefined opaque object (no TNT) ...\n";
411  {
412  RCP<UndefinedType> op_ptr =
414  deallocFunctorHandleDelete<UndefinedType> (destroyOpaque),
415  true);
417  }
418  // 2008/08/01: rabartl: Above, we can only wrap an undefined type in
419  // nondebug mode since there is no TypeNameTraits class defined for it and
420  // the default uses typeid(...) which you can't call on an undefined type.
421  // If you define a specialization of TypeNameTraits for this class, then
422  // it will compile just fine! This is related to bug 4016.
423 
424 #endif // not TEUCHOS_DEBUG
425 
426  out << "\nTesting using RCP to wrap an undefined opaque object (with TNT) ...\n";
427  {
428  RCP<UndefinedType2> op_ptr = rcpWithDeallocUndef( createOpaque2(),
429  deallocFunctorHandleDelete<UndefinedType2>(destroyOpaque2) );
431  }
432  // 2008/08/01: rabartl: Above, we can wrap an undefined type in debug mode
433  // as long as we have a TypeNameTraits specialization of it to avoid
434  // calling typeid(...).
435 
436 #ifdef HAVE_TEUCHOS_BOOST
437 
438  out << "\nTesting basic RCP compatibility with boost::shared_ptr ...\n";
439 
440  boost::shared_ptr<A> a_sptr1(new C());
441  RCP<A> a_rsptr1 = rcp(a_sptr1);
442  TEUCHOS_TEST_FOR_EXCEPT( a_rsptr1.get() != a_sptr1.get() );
443  TEUCHOS_TEST_FOR_EXCEPT( a_rsptr1.getRawPtr() != a_sptr1.get() );
444  TEUCHOS_TEST_FOR_EXCEPT( a_rsptr1.get() != a_rsptr1.getRawPtr() );
445  boost::shared_ptr<A> a_sptr2 = shared_pointer(a_rsptr1);
446  // There seems no standard way to test that a shared_ptr shares the same node
447  //TEUCHOS_TEST_FOR_EXCEPT( a_sptr2._internal_equiv(a_sptr1) != true );
448  RCP<A> a_rsptr2 = rcp(a_sptr2);
449  TEUCHOS_TEST_FOR_EXCEPT( a_rsptr2.ptr() != a_rsptr1.ptr() );
450  //TEUCHOS_TEST_FOR_EXCEPT( a_rsptr2 != a_rsptr1 ); // This should work if boost::get_deleter() works correctly!
451  boost::shared_ptr<A> a_sptr3 = shared_pointer(a_rsptr2);
452  TEUCHOS_TEST_FOR_EXCEPT( a_sptr3.get() != a_rsptr2.get() );
453 
454  out << "\nCompatibility with boost::shared_ptr passed ...\n";
455 
456 #endif // HAVE_TEUCHOS_BOOST
457 
458  out << "\nAll tests for RCP seem to check out!\n";
459 
460  } // end try
461  TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success);
462 
463  try {
464  // In debug mode, this should show that the A and C RCP objects are still
465  // around!
466  if (createCircRefs) {
467  out << "\nPrinting the active nodes just to see them!\n";
469 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
471 #endif
472  }
473  } // end try
474  TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success);
475 
476  if(success)
477  out << "\nEnd Result: TEST PASSED" << std::endl;
478 
479  return ( success ? 0 : 1 );
480 
481 }
RCP< T > rcp(const boost::shared_ptr< T > &sptr)
Conversion function that takes in a boost::shared_ptr object and spits out a Teuchos::RCP object...
void destroyOpaque(Opaque_handle *opaque)
Definition: TestClasses.cpp:51
void set_extra_data(const T1 &extra_data, const std::string &name, const Ptr< ArrayRCP< T2 > > &p, EPrePostDestruction destroy_when=POST_DESTROY, bool force_unique=true)
Set extra data associated with a ArrayRCP object.
static int getRank()
The rank of the calling process in MPI_COMM_WORLD.
Ptr< T > inOutArg(T &arg)
create a non-persisting (required or optional) input/output argument for a function call...
RCP< T2 > rcp_static_cast(const RCP< T1 > &p1)
Static cast of underlying RCP type from T1* to T2*.
boost::shared_ptr< T > shared_pointer(const RCP< T > &rcp)
Conversion function that takes in a Teuchos::RCP object and spits out a boost::shared_ptr object...
virtual int A_g()
Definition: TestClasses.hpp:67
T1 & get_extra_data(ArrayRCP< T2 > &p, const std::string &name)
Get a non-const reference to extra data associated with a ArrayRCP object.
Ptr< T1 > get_optional_nonconst_extra_data(RCP< T2 > &p, const std::string &name)
Get a pointer to non-const extra data (if it exists) associated with a RCP object.
RCP< T2 > rcp_dynamic_cast(const RCP< T1 > &p1, bool throw_on_fail=false)
Dynamic cast of underlying RCP type from T1* to T2*.
bool is_null(const std::shared_ptr< T > &p)
Returns true if p.get()==NULL.
basic_ostream&lt;&gt; subclass that does nothing but discard output.
Dealloc_T * get_optional_nonconst_dealloc(const ArrayRCP< T > &p)
Return a pointer to the underlying const deallocator object if it exists.
const T & getConst(T &t)
Return a constant reference to an object given a non-const reference.
const int C_f_return
Definition: TestClasses.hpp:25
const int A_f_return
Definition: TestClasses.hpp:19
const int getOpaqueValue_return
Initialize, finalize, and query the global MPI session.
void destroyOpaque2(Opaque2_handle *opaque)
Definition: TestClasses.cpp:78
bool is_null(const ArrayRCP< T > &p)
Returns true if p.get()==NULL.
RCP< T > rcpWithEmbeddedObj(T *p, const Embedded &embedded, bool owns_mem=true)
Create an RCP with and also put in an embedded object.
const int getOpaque2Value_return
Policy class for deallocator that uses delete to delete a pointer which is used by RCP...
T1 * get_optional_extra_data(ArrayRCP< T2 > &p, const std::string &name)
Get a pointer to non-const extra data (if it exists) associated with a ArrayRCP object.
void deallocHandleA(A **handle)
Definition: TestClasses.cpp:23
const int D_f_return
Definition: TestClasses.hpp:27
RCP< T > rcpWithEmbeddedObjPostDestroy(T *p, const Embedded &embedded, bool owns_mem=true)
Create an RCP with and also put in an embedded object.
RCP< T > rcpWithEmbeddedObjPreDestroy(T *p, const Embedded &embedded, bool owns_mem=true)
Create an RCP with and also put in an embedded object.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
int getOpaqueValue(Opaque_handle opaque)
Definition: TestClasses.cpp:45
#define TEUCHOS_STANDARD_CATCH_STATEMENTS(VERBOSE, ERR_STREAM, SUCCESS_FLAG)
Simple macro that catches and reports standard exceptions and other exceptions.
RCP< T > rcpWithDeallocUndef(T *p, Dealloc_T dealloc, bool owns_mem=true)
Initialize from a raw pointer with a deallocation policy for an undefined type.
Opaque2_handle createOpaque2()
Definition: TestClasses.cpp:64
const Dealloc_T * get_optional_dealloc(const ArrayRCP< T > &p)
Return a pointer to the underlying non-const deallocator object if it exists.
std::string Teuchos_Version()
const int D_g_return
Definition: TestClasses.hpp:26
const int B1_f_return
Definition: TestClasses.hpp:21
int main(int argc, char *argv[])
A MPI utilities class, providing methods for initializing, finalizing, and querying the global MPI se...
Basic command line parser for input from (argc,argv[])
const int B1_g_return
Definition: TestClasses.hpp:20
int getOpaque2Value(Opaque2_handle opaque)
Definition: TestClasses.cpp:72
Opaque_handle createOpaque()
Definition: TestClasses.cpp:37
Smart reference counting pointer class for automatic garbage collection.
#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 ...
RCP< T2 > rcp_const_cast(const RCP< T1 > &p1)
Constant cast of underlying RCP type from T1* to T2*.
RCP< T > rcpWithDealloc(T *p, Dealloc_T dealloc, bool owns_mem=true)
Initialize from a raw pointer with a deallocation policy.
static int numActiveRCPNodes()
Print the number of active RCPNode objects currently being tracked.
Reference-counted pointer class and non-member templated function implementations.
const int A_g_return
Definition: TestClasses.hpp:18
const int E_g_return
Definition: TestClasses.hpp:28
Class that helps parse command line input arguments from (argc,argv[]) and set options.
#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...
const int B2_f_return
Definition: TestClasses.hpp:23
static void printActiveRCPNodes(std::ostream &out)
Print the list of currently active RCP nodes.
void deallocA(A *ptr)
Definition: TestClasses.cpp:16