#if defined(_MSC_VER) && !defined(__ICL) && !defined(__COMO__) #pragma warning(disable: 4786) // identifier truncated in debug info #pragma warning(disable: 4710) // function not inlined #pragma warning(disable: 4711) // function selected for automatic inline expansion #pragma warning(disable: 4514) // unreferenced inline removed #pragma warning(disable: 4355) // 'this' : used in base member initializer list #endif // // shared_ptr_test.cpp - a test for shared_ptr.hpp and weak_ptr.hpp // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // #include #include #include #include #include // namespace n_element_type { void f(int &) { } void test() { typedef boost::shared_ptr::element_type T; T t; f(t); } } // namespace n_element_type namespace n_constructors { class incomplete; void default_constructor() { { boost::shared_ptr pi; BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); } { boost::shared_ptr pv; BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); } { boost::shared_ptr px; BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); } } struct A { int dummy; }; struct X { static long instances; X() { ++instances; } ~X() { --instances; } private: X(X const &); X & operator= (X const &); }; long X::instances = 0; struct Y: public A, public X { static long instances; Y() { ++instances; } ~Y() { --instances; } private: Y(Y const &); Y & operator= (Y const &); }; long Y::instances = 0; void pointer_constructor() { { boost::shared_ptr pi(static_cast(0)); BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); BOOST_TEST(pi.use_count() == 1); BOOST_TEST(pi.unique()); } { boost::shared_ptr pi(static_cast(0)); BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); BOOST_TEST(pi.use_count() == 1); BOOST_TEST(pi.unique()); } { boost::shared_ptr pv(static_cast(0)); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); } { boost::shared_ptr pv(static_cast(0)); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); } { boost::shared_ptr px(static_cast(0)); BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); } { boost::shared_ptr px(static_cast(0)); BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); } { boost::shared_ptr px(static_cast(0)); BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); } { boost::shared_ptr px(static_cast(0)); BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); } { boost::shared_ptr pv(static_cast(0)); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); } { boost::shared_ptr pv(static_cast(0)); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); } { int * p = new int(7); boost::shared_ptr pi(p); BOOST_TEST(pi? true: false); BOOST_TEST(!!pi); BOOST_TEST(pi.get() == p); BOOST_TEST(pi.use_count() == 1); BOOST_TEST(pi.unique()); BOOST_TEST(*pi == 7); } { int * p = new int(7); boost::shared_ptr pi(p); BOOST_TEST(pi? true: false); BOOST_TEST(!!pi); BOOST_TEST(pi.get() == p); BOOST_TEST(pi.use_count() == 1); BOOST_TEST(pi.unique()); BOOST_TEST(*pi == 7); } { int * p = new int(7); boost::shared_ptr pv(p); BOOST_TEST(pv? true: false); BOOST_TEST(!!pv); BOOST_TEST(pv.get() == p); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); } { int * p = new int(7); boost::shared_ptr pv(p); BOOST_TEST(pv? true: false); BOOST_TEST(!!pv); BOOST_TEST(pv.get() == p); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); } BOOST_TEST(X::instances == 0); { X * p = new X; boost::shared_ptr px(p); BOOST_TEST(px? true: false); BOOST_TEST(!!px); BOOST_TEST(px.get() == p); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); BOOST_TEST(X::instances == 1); } BOOST_TEST(X::instances == 0); { X * p = new X; boost::shared_ptr px(p); BOOST_TEST(px? true: false); BOOST_TEST(!!px); BOOST_TEST(px.get() == p); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); BOOST_TEST(X::instances == 1); } BOOST_TEST(X::instances == 0); { X * p = new X; boost::shared_ptr pv(p); BOOST_TEST(pv? true: false); BOOST_TEST(!!pv); BOOST_TEST(pv.get() == p); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); BOOST_TEST(X::instances == 1); } BOOST_TEST(X::instances == 0); { X * p = new X; boost::shared_ptr pv(p); BOOST_TEST(pv? true: false); BOOST_TEST(!!pv); BOOST_TEST(pv.get() == p); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); BOOST_TEST(X::instances == 1); } BOOST_TEST(X::instances == 0); BOOST_TEST(Y::instances == 0); { Y * p = new Y; boost::shared_ptr px(p); BOOST_TEST(px? true: false); BOOST_TEST(!!px); BOOST_TEST(px.get() == p); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); BOOST_TEST(X::instances == 1); BOOST_TEST(Y::instances == 1); } BOOST_TEST(X::instances == 0); BOOST_TEST(Y::instances == 0); { Y * p = new Y; boost::shared_ptr px(p); BOOST_TEST(px? true: false); BOOST_TEST(!!px); BOOST_TEST(px.get() == p); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); BOOST_TEST(X::instances == 1); BOOST_TEST(Y::instances == 1); } BOOST_TEST(X::instances == 0); BOOST_TEST(Y::instances == 0); } int m = 0; void deleter(int * p) { BOOST_TEST(p == 0); } void deleter2(int * p) { BOOST_TEST(p == &m); ++*p; } struct deleter3 { void operator()(incomplete * p) { BOOST_TEST(p == 0); } }; // Borland C++ 5.5.1 fails on static_cast(0) incomplete * p0 = 0; void deleter_constructor() { { boost::shared_ptr pi(static_cast(0), deleter); BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); BOOST_TEST(pi.use_count() == 1); BOOST_TEST(pi.unique()); } { boost::shared_ptr pv(static_cast(0), &deleter); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); } { boost::shared_ptr pv(static_cast(0), deleter); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); } { boost::shared_ptr px(p0, deleter3()); BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); } { boost::shared_ptr pv(p0, deleter3()); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); } { boost::shared_ptr pv(p0, deleter3()); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); } BOOST_TEST(m == 0); { boost::shared_ptr pi(&m, deleter2); BOOST_TEST(pi? true: false); BOOST_TEST(!!pi); BOOST_TEST(pi.get() == &m); BOOST_TEST(pi.use_count() == 1); BOOST_TEST(pi.unique()); } BOOST_TEST(m == 1); { boost::shared_ptr pi(&m, &deleter2); BOOST_TEST(pi? true: false); BOOST_TEST(!!pi); BOOST_TEST(pi.get() == &m); BOOST_TEST(pi.use_count() == 1); BOOST_TEST(pi.unique()); } BOOST_TEST(m == 2); { boost::shared_ptr pv(&m, deleter2); BOOST_TEST(pv? true: false); BOOST_TEST(!!pv); BOOST_TEST(pv.get() == &m); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); } BOOST_TEST(m == 3); { boost::shared_ptr pv(&m, &deleter2); BOOST_TEST(pv? true: false); BOOST_TEST(!!pv); BOOST_TEST(pv.get() == &m); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); } BOOST_TEST(m == 4); } void copy_constructor() { { boost::shared_ptr pi; boost::shared_ptr pi2(pi); BOOST_TEST(pi2 == pi); BOOST_TEST(pi2? false: true); BOOST_TEST(!pi2); BOOST_TEST(pi2.get() == 0); boost::shared_ptr pi3(pi); BOOST_TEST(pi3 == pi); BOOST_TEST(pi3? false: true); BOOST_TEST(!pi3); BOOST_TEST(pi3.get() == 0); boost::shared_ptr pi4(pi3); BOOST_TEST(pi4 == pi3); BOOST_TEST(pi4? false: true); BOOST_TEST(!pi4); BOOST_TEST(pi4.get() == 0); } { boost::shared_ptr pv; boost::shared_ptr pv2(pv); BOOST_TEST(pv2 == pv); BOOST_TEST(pv2? false: true); BOOST_TEST(!pv2); BOOST_TEST(pv2.get() == 0); } { boost::shared_ptr px; boost::shared_ptr px2(px); BOOST_TEST(px2 == px); BOOST_TEST(px2? false: true); BOOST_TEST(!px2); BOOST_TEST(px2.get() == 0); boost::shared_ptr px3(px); BOOST_TEST(px3 == px); BOOST_TEST(px3? false: true); BOOST_TEST(!px3); BOOST_TEST(px3.get() == 0); } { boost::shared_ptr pi(static_cast(0)); boost::shared_ptr pi2(pi); BOOST_TEST(pi2 == pi); BOOST_TEST(pi2? false: true); BOOST_TEST(!pi2); BOOST_TEST(pi2.get() == 0); BOOST_TEST(pi2.use_count() == 2); BOOST_TEST(!pi2.unique()); BOOST_TEST(pi.use_count() == pi2.use_count()); BOOST_TEST(!(pi < pi2 || pi2 < pi)); // shared ownership test boost::shared_ptr pi3(pi); BOOST_TEST(pi3 == pi); BOOST_TEST(pi3? false: true); BOOST_TEST(!pi3); BOOST_TEST(pi3.get() == 0); BOOST_TEST(pi3.use_count() == 3); BOOST_TEST(!pi3.unique()); boost::shared_ptr pi4(pi2); BOOST_TEST(pi4 == pi2); BOOST_TEST(pi4? false: true); BOOST_TEST(!pi4); BOOST_TEST(pi4.get() == 0); BOOST_TEST(pi4.use_count() == 4); BOOST_TEST(!pi4.unique()); BOOST_TEST(pi3.use_count() == pi4.use_count()); BOOST_TEST(!(pi3 < pi4 || pi4 < pi3)); // shared ownership test } { boost::shared_ptr px(static_cast(0)); boost::shared_ptr px2(px); BOOST_TEST(px2 == px); BOOST_TEST(px2? false: true); BOOST_TEST(!px2); BOOST_TEST(px2.get() == 0); BOOST_TEST(px2.use_count() == 2); BOOST_TEST(!px2.unique()); BOOST_TEST(px.use_count() == px2.use_count()); BOOST_TEST(!(px < px2 || px2 < px)); // shared ownership test boost::shared_ptr px3(px); BOOST_TEST(px3 == px); BOOST_TEST(px3? false: true); BOOST_TEST(!px3); BOOST_TEST(px3.get() == 0); BOOST_TEST(px3.use_count() == 3); BOOST_TEST(!px3.unique()); boost::shared_ptr px4(px2); BOOST_TEST(px4 == px2); BOOST_TEST(px4? false: true); BOOST_TEST(!px4); BOOST_TEST(px4.get() == 0); BOOST_TEST(px4.use_count() == 4); BOOST_TEST(!px4.unique()); BOOST_TEST(px3.use_count() == px4.use_count()); BOOST_TEST(!(px3 < px4 || px4 < px3)); // shared ownership test } { int * p = new int(7); boost::shared_ptr pi(p); boost::shared_ptr pi2(pi); BOOST_TEST(pi2 == pi); BOOST_TEST(pi2? true: false); BOOST_TEST(!!pi2); BOOST_TEST(pi2.get() == p); BOOST_TEST(pi2.use_count() == 2); BOOST_TEST(!pi2.unique()); BOOST_TEST(*pi2 == 7); BOOST_TEST(pi.use_count() == pi2.use_count()); BOOST_TEST(!(pi < pi2 || pi2 < pi)); // shared ownership test } { int * p = new int(7); boost::shared_ptr pv(p); BOOST_TEST(pv.get() == p); boost::shared_ptr pv2(pv); BOOST_TEST(pv2 == pv); BOOST_TEST(pv2? true: false); BOOST_TEST(!!pv2); BOOST_TEST(pv2.get() == p); BOOST_TEST(pv2.use_count() == 2); BOOST_TEST(!pv2.unique()); BOOST_TEST(pv.use_count() == pv2.use_count()); BOOST_TEST(!(pv < pv2 || pv2 < pv)); // shared ownership test } BOOST_TEST(X::instances == 0); { X * p = new X; boost::shared_ptr px(p); BOOST_TEST(px.get() == p); boost::shared_ptr px2(px); BOOST_TEST(px2 == px); BOOST_TEST(px2? true: false); BOOST_TEST(!!px2); BOOST_TEST(px2.get() == p); BOOST_TEST(px2.use_count() == 2); BOOST_TEST(!px2.unique()); BOOST_TEST(X::instances == 1); BOOST_TEST(px.use_count() == px2.use_count()); BOOST_TEST(!(px < px2 || px2 < px)); // shared ownership test boost::shared_ptr px3(px); BOOST_TEST(px3 == px); BOOST_TEST(px3? true: false); BOOST_TEST(!!px3); BOOST_TEST(px3.get() == p); BOOST_TEST(px3.use_count() == 3); BOOST_TEST(!px3.unique()); boost::shared_ptr px4(px2); BOOST_TEST(px4 == px2); BOOST_TEST(px4? true: false); BOOST_TEST(!!px4); BOOST_TEST(px4.get() == p); BOOST_TEST(px4.use_count() == 4); BOOST_TEST(!px4.unique()); BOOST_TEST(px3.use_count() == px4.use_count()); BOOST_TEST(!(px3 < px4 || px4 < px3)); // shared ownership test } BOOST_TEST(X::instances == 0); BOOST_TEST(Y::instances == 0); { Y * p = new Y; boost::shared_ptr py(p); BOOST_TEST(py.get() == p); boost::shared_ptr px(py); BOOST_TEST(px == py); BOOST_TEST(px? true: false); BOOST_TEST(!!px); BOOST_TEST(px.get() == p); BOOST_TEST(px.use_count() == 2); BOOST_TEST(!px.unique()); BOOST_TEST(X::instances == 1); BOOST_TEST(Y::instances == 1); boost::shared_ptr pv(px); BOOST_TEST(pv == px); BOOST_TEST(pv? true: false); BOOST_TEST(!!pv); BOOST_TEST(pv.get() == px.get()); BOOST_TEST(pv.use_count() == 3); BOOST_TEST(!pv.unique()); boost::shared_ptr pv2(py); BOOST_TEST(pv2 == py); BOOST_TEST(pv2? true: false); BOOST_TEST(!!pv2); BOOST_TEST(pv2.get() == py.get()); BOOST_TEST(pv2.use_count() == 4); BOOST_TEST(!pv2.unique()); BOOST_TEST(pv.use_count() == pv2.use_count()); BOOST_TEST(!(pv < pv2 || pv2 < pv)); // shared ownership test } BOOST_TEST(X::instances == 0); BOOST_TEST(Y::instances == 0); } void weak_ptr_constructor() { boost::shared_ptr p(new Y); boost::weak_ptr wp(p); { boost::shared_ptr p2(wp); BOOST_TEST(p2? true: false); BOOST_TEST(!!p2); BOOST_TEST(p2.get() == p.get()); BOOST_TEST(p2.use_count() == 2); BOOST_TEST(!p2.unique()); BOOST_TEST(p.use_count() == p2.use_count()); BOOST_TEST(!(p < p2 || p2 < p)); // shared ownership test boost::shared_ptr p3(wp); BOOST_TEST(p3? true: false); BOOST_TEST(!!p3); BOOST_TEST(p3.get() == p.get()); BOOST_TEST(p3.use_count() == 3); BOOST_TEST(!p3.unique()); BOOST_TEST(p.use_count() == p3.use_count()); } p.reset(); try { boost::shared_ptr p2(wp); BOOST_ERROR("shared_ptr p2(wp) failed to throw"); } catch(boost::bad_weak_ptr) { } try { boost::shared_ptr p3(wp); BOOST_ERROR("shared_ptr p3(wp) failed to throw"); } catch(boost::bad_weak_ptr) { } } void auto_ptr_constructor() { { std::auto_ptr p; boost::shared_ptr pi(p); BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); BOOST_TEST(pi.use_count() == 1); BOOST_TEST(pi.unique()); BOOST_TEST(p.get() == 0); } { std::auto_ptr p; boost::shared_ptr pi(p); BOOST_TEST(pi? false: true); BOOST_TEST(!pi); BOOST_TEST(pi.get() == 0); BOOST_TEST(pi.use_count() == 1); BOOST_TEST(pi.unique()); BOOST_TEST(p.get() == 0); } { std::auto_ptr p; boost::shared_ptr pv(p); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); BOOST_TEST(p.get() == 0); } { std::auto_ptr p; boost::shared_ptr pv(p); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); BOOST_TEST(p.get() == 0); } { std::auto_ptr p; boost::shared_ptr px(p); BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); BOOST_TEST(p.get() == 0); } { std::auto_ptr p; boost::shared_ptr px(p); BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); BOOST_TEST(p.get() == 0); } { std::auto_ptr p; boost::shared_ptr px(p); BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); BOOST_TEST(p.get() == 0); } { std::auto_ptr p; boost::shared_ptr px(p); BOOST_TEST(px? false: true); BOOST_TEST(!px); BOOST_TEST(px.get() == 0); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); BOOST_TEST(p.get() == 0); } { std::auto_ptr p; boost::shared_ptr pv(p); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); BOOST_TEST(p.get() == 0); } { std::auto_ptr p; boost::shared_ptr pv(p); BOOST_TEST(pv? false: true); BOOST_TEST(!pv); BOOST_TEST(pv.get() == 0); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); BOOST_TEST(p.get() == 0); } { std::auto_ptr p(new int(7)); int * q = p.get(); boost::shared_ptr pi(p); BOOST_TEST(pi? true: false); BOOST_TEST(!!pi); BOOST_TEST(pi.get() == q); BOOST_TEST(pi.use_count() == 1); BOOST_TEST(pi.unique()); BOOST_TEST(*pi == 7); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p.get() == 0); #endif } { std::auto_ptr p(new int(7)); int * q = p.get(); boost::shared_ptr pi(p); BOOST_TEST(pi? true: false); BOOST_TEST(!!pi); BOOST_TEST(pi.get() == q); BOOST_TEST(pi.use_count() == 1); BOOST_TEST(pi.unique()); BOOST_TEST(*pi == 7); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p.get() == 0); #endif } { std::auto_ptr p(new int(7)); int * q = p.get(); boost::shared_ptr pv(p); BOOST_TEST(pv? true: false); BOOST_TEST(!!pv); BOOST_TEST(pv.get() == q); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p.get() == 0); #endif } { std::auto_ptr p(new int(7)); int * q = p.get(); boost::shared_ptr pv(p); BOOST_TEST(pv? true: false); BOOST_TEST(!!pv); BOOST_TEST(pv.get() == q); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p.get() == 0); #endif } BOOST_TEST(X::instances == 0); { std::auto_ptr p(new X); X * q = p.get(); boost::shared_ptr px(p); BOOST_TEST(px? true: false); BOOST_TEST(!!px); BOOST_TEST(px.get() == q); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); BOOST_TEST(X::instances == 1); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p.get() == 0); #endif } BOOST_TEST(X::instances == 0); { std::auto_ptr p(new X); X * q = p.get(); boost::shared_ptr px(p); BOOST_TEST(px? true: false); BOOST_TEST(!!px); BOOST_TEST(px.get() == q); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); BOOST_TEST(X::instances == 1); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p.get() == 0); #endif } BOOST_TEST(X::instances == 0); { std::auto_ptr p(new X); X * q = p.get(); boost::shared_ptr pv(p); BOOST_TEST(pv? true: false); BOOST_TEST(!!pv); BOOST_TEST(pv.get() == q); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); BOOST_TEST(X::instances == 1); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p.get() == 0); #endif } BOOST_TEST(X::instances == 0); { std::auto_ptr p(new X); X * q = p.get(); boost::shared_ptr pv(p); BOOST_TEST(pv? true: false); BOOST_TEST(!!pv); BOOST_TEST(pv.get() == q); BOOST_TEST(pv.use_count() == 1); BOOST_TEST(pv.unique()); BOOST_TEST(X::instances == 1); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p.get() == 0); #endif } BOOST_TEST(X::instances == 0); BOOST_TEST(Y::instances == 0); { std::auto_ptr p(new Y); Y * q = p.get(); boost::shared_ptr px(p); BOOST_TEST(px? true: false); BOOST_TEST(!!px); BOOST_TEST(px.get() == q); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); BOOST_TEST(X::instances == 1); BOOST_TEST(Y::instances == 1); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p.get() == 0); #endif } BOOST_TEST(X::instances == 0); BOOST_TEST(Y::instances == 0); { std::auto_ptr p(new Y); Y * q = p.get(); boost::shared_ptr px(p); BOOST_TEST(px? true: false); BOOST_TEST(!!px); BOOST_TEST(px.get() == q); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); BOOST_TEST(X::instances == 1); BOOST_TEST(Y::instances == 1); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p.get() == 0); #endif } BOOST_TEST(X::instances == 0); BOOST_TEST(Y::instances == 0); } void test() { default_constructor(); pointer_constructor(); deleter_constructor(); copy_constructor(); weak_ptr_constructor(); auto_ptr_constructor(); } } // namespace n_constructors namespace n_assignment { class incomplete; struct A { int dummy; }; struct X { static long instances; X() { ++instances; } ~X() { --instances; } private: X(X const &); X & operator= (X const &); }; long X::instances = 0; struct Y: public A, public X { static long instances; Y() { ++instances; } ~Y() { --instances; } private: Y(Y const &); Y & operator= (Y const &); }; long Y::instances = 0; void copy_assignment() { { boost::shared_ptr p1; p1 = p1; BOOST_TEST(p1 == p1); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); boost::shared_ptr p2; p1 = p2; BOOST_TEST(p1 == p2); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); boost::shared_ptr p3(p1); p1 = p3; BOOST_TEST(p1 == p3); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); } { boost::shared_ptr p1; p1 = p1; BOOST_TEST(p1 == p1); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); boost::shared_ptr p2; p1 = p2; BOOST_TEST(p1 == p2); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); boost::shared_ptr p3(p1); p1 = p3; BOOST_TEST(p1 == p3); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); boost::shared_ptr p4(new int); BOOST_TEST(p4.use_count() == 1); p1 = p4; BOOST_TEST(p1 == p4); BOOST_TEST(!(p1 < p4 || p4 < p1)); BOOST_TEST(p1.use_count() == 2); BOOST_TEST(p4.use_count() == 2); p1 = p3; BOOST_TEST(p1 == p3); BOOST_TEST(p4.use_count() == 1); } { boost::shared_ptr p1; p1 = p1; BOOST_TEST(p1 == p1); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); boost::shared_ptr p2; p1 = p2; BOOST_TEST(p1 == p2); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); boost::shared_ptr p3(p1); p1 = p3; BOOST_TEST(p1 == p3); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); BOOST_TEST(X::instances == 0); boost::shared_ptr p4(new X); BOOST_TEST(X::instances == 1); p1 = p4; BOOST_TEST(X::instances == 1); BOOST_TEST(p1 == p4); BOOST_TEST(!(p1 < p4 || p4 < p1)); BOOST_TEST(p1.use_count() == 2); p1 = p2; BOOST_TEST(p1 == p2); BOOST_TEST(X::instances == 1); p4 = p3; BOOST_TEST(p4 == p3); BOOST_TEST(X::instances == 0); } } void conversion_assignment() { { boost::shared_ptr p1; boost::shared_ptr p2; p1 = p2; BOOST_TEST(p1 == p2); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); boost::shared_ptr p4(new int); BOOST_TEST(p4.use_count() == 1); boost::shared_ptr p5(p4); BOOST_TEST(p4.use_count() == 2); p1 = p4; BOOST_TEST(p1 == p4); BOOST_TEST(!(p1 < p5 || p5 < p1)); BOOST_TEST(p1.use_count() == 3); BOOST_TEST(p4.use_count() == 3); p1 = p2; BOOST_TEST(p1 == p2); BOOST_TEST(p4.use_count() == 2); } { boost::shared_ptr p1; boost::shared_ptr p2; p1 = p2; BOOST_TEST(p1 == p2); BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); BOOST_TEST(X::instances == 0); BOOST_TEST(Y::instances == 0); boost::shared_ptr p4(new Y); BOOST_TEST(X::instances == 1); BOOST_TEST(Y::instances == 1); BOOST_TEST(p4.use_count() == 1); boost::shared_ptr p5(p4); BOOST_TEST(p4.use_count() == 2); p1 = p4; BOOST_TEST(X::instances == 1); BOOST_TEST(Y::instances == 1); BOOST_TEST(p1 == p4); BOOST_TEST(!(p1 < p5 || p5 < p1)); BOOST_TEST(p1.use_count() == 3); BOOST_TEST(p4.use_count() == 3); p1 = p2; BOOST_TEST(p1 == p2); BOOST_TEST(X::instances == 1); BOOST_TEST(Y::instances == 1); BOOST_TEST(p4.use_count() == 2); p4 = p2; p5 = p2; BOOST_TEST(p4 == p2); BOOST_TEST(X::instances == 0); BOOST_TEST(Y::instances == 0); } } void auto_ptr_assignment() { { boost::shared_ptr p1; std::auto_ptr p2; p1 = p2; BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); BOOST_TEST(p1.use_count() == 1); int * p = new int; std::auto_ptr p3(p); p1 = p3; BOOST_TEST(p1.get() == p); BOOST_TEST(p1.use_count() == 1); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p3.get() == 0); #endif p1 = p2; BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); BOOST_TEST(p1.use_count() == 1); } { boost::shared_ptr p1; std::auto_ptr p2; p1 = p2; BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); BOOST_TEST(p1.use_count() == 1); int * p = new int; std::auto_ptr p3(p); p1 = p3; BOOST_TEST(p1.get() == p); BOOST_TEST(p1.use_count() == 1); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p3.get() == 0); #endif p1 = p2; BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); BOOST_TEST(p1.use_count() == 1); } { boost::shared_ptr p1; std::auto_ptr p2; p1 = p2; BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); BOOST_TEST(p1.use_count() == 1); BOOST_TEST(X::instances == 0); BOOST_TEST(Y::instances == 0); Y * p = new Y; std::auto_ptr p3(p); BOOST_TEST(X::instances == 1); BOOST_TEST(Y::instances == 1); p1 = p3; BOOST_TEST(p1.get() == p); BOOST_TEST(p1.use_count() == 1); BOOST_TEST(X::instances == 1); BOOST_TEST(Y::instances == 1); #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) BOOST_TEST(p3.get() == 0); #endif p1 = p2; BOOST_TEST(p1? false: true); BOOST_TEST(!p1); BOOST_TEST(p1.get() == 0); BOOST_TEST(p1.use_count() == 1); BOOST_TEST(X::instances == 0); BOOST_TEST(Y::instances == 0); } } void test() { copy_assignment(); conversion_assignment(); auto_ptr_assignment(); } } // namespace n_assignment namespace n_reset { void plain_reset() { } void pointer_reset() { } void deleter_reset() { } void test() { plain_reset(); pointer_reset(); deleter_reset(); } } // namespace n_reset namespace n_access { struct X { }; void test() { { boost::shared_ptr px; BOOST_TEST(px.get() == 0); BOOST_TEST(px? false: true); BOOST_TEST(!px); #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) using boost::get_pointer; #endif BOOST_TEST(get_pointer(px) == px.get()); } { boost::shared_ptr px(static_cast(0)); BOOST_TEST(px.get() == 0); BOOST_TEST(px? false: true); BOOST_TEST(!px); #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) using boost::get_pointer; #endif BOOST_TEST(get_pointer(px) == px.get()); } { boost::shared_ptr px(static_cast(0), boost::checked_deleter()); BOOST_TEST(px.get() == 0); BOOST_TEST(px? false: true); BOOST_TEST(!px); #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) using boost::get_pointer; #endif BOOST_TEST(get_pointer(px) == px.get()); } { X * p = new X; boost::shared_ptr px(p); BOOST_TEST(px.get() == p); BOOST_TEST(px? true: false); BOOST_TEST(!!px); BOOST_TEST(&*px == px.get()); BOOST_TEST(px.operator ->() == px.get()); #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) using boost::get_pointer; #endif BOOST_TEST(get_pointer(px) == px.get()); } { X * p = new X; boost::shared_ptr px(p, boost::checked_deleter()); BOOST_TEST(px.get() == p); BOOST_TEST(px? true: false); BOOST_TEST(!!px); BOOST_TEST(&*px == px.get()); BOOST_TEST(px.operator ->() == px.get()); #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) using boost::get_pointer; #endif BOOST_TEST(get_pointer(px) == px.get()); } } } // namespace n_access namespace n_use_count { struct X { }; void test() { { boost::shared_ptr px(static_cast(0)); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); boost::shared_ptr px2(px); BOOST_TEST(px2.use_count() == 2); BOOST_TEST(!px2.unique()); BOOST_TEST(px.use_count() == 2); BOOST_TEST(!px.unique()); } { boost::shared_ptr px(new X); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); boost::shared_ptr px2(px); BOOST_TEST(px2.use_count() == 2); BOOST_TEST(!px2.unique()); BOOST_TEST(px.use_count() == 2); BOOST_TEST(!px.unique()); } { boost::shared_ptr px(new X, boost::checked_deleter()); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px.unique()); boost::shared_ptr px2(px); BOOST_TEST(px2.use_count() == 2); BOOST_TEST(!px2.unique()); BOOST_TEST(px.use_count() == 2); BOOST_TEST(!px.unique()); } } } // namespace n_use_count namespace n_swap { struct X { }; void test() { { boost::shared_ptr px; boost::shared_ptr px2; px.swap(px2); BOOST_TEST(px.get() == 0); BOOST_TEST(px2.get() == 0); using std::swap; swap(px, px2); BOOST_TEST(px.get() == 0); BOOST_TEST(px2.get() == 0); } { X * p = new X; boost::shared_ptr px; boost::shared_ptr px2(p); boost::shared_ptr px3(px2); px.swap(px2); BOOST_TEST(px.get() == p); BOOST_TEST(px.use_count() == 2); BOOST_TEST(px2.get() == 0); BOOST_TEST(px3.get() == p); BOOST_TEST(px3.use_count() == 2); using std::swap; swap(px, px2); BOOST_TEST(px.get() == 0); BOOST_TEST(px2.get() == p); BOOST_TEST(px2.use_count() == 2); BOOST_TEST(px3.get() == p); BOOST_TEST(px3.use_count() == 2); } { X * p1 = new X; X * p2 = new X; boost::shared_ptr px(p1); boost::shared_ptr px2(p2); boost::shared_ptr px3(px2); px.swap(px2); BOOST_TEST(px.get() == p2); BOOST_TEST(px.use_count() == 2); BOOST_TEST(px2.get() == p1); BOOST_TEST(px2.use_count() == 1); BOOST_TEST(px3.get() == p2); BOOST_TEST(px3.use_count() == 2); using std::swap; swap(px, px2); BOOST_TEST(px.get() == p1); BOOST_TEST(px.use_count() == 1); BOOST_TEST(px2.get() == p2); BOOST_TEST(px2.use_count() == 2); BOOST_TEST(px3.get() == p2); BOOST_TEST(px3.use_count() == 2); } } } // namespace n_swap namespace n_comparison { struct X { int dummy; }; struct Y { int dummy2; }; struct Z: public X, public Y { }; void test() { { boost::shared_ptr px; BOOST_TEST(px == px); BOOST_TEST(!(px != px)); BOOST_TEST(!(px < px)); boost::shared_ptr px2; BOOST_TEST(px.get() == px2.get()); BOOST_TEST(px == px2); BOOST_TEST(!(px != px2)); BOOST_TEST(!(px < px2 && px2 < px)); } { boost::shared_ptr px; boost::shared_ptr px2(px); BOOST_TEST(px2 == px2); BOOST_TEST(!(px2 != px2)); BOOST_TEST(!(px2 < px2)); BOOST_TEST(px.get() == px2.get()); BOOST_TEST(px == px2); BOOST_TEST(!(px != px2)); BOOST_TEST(!(px < px2 && px2 < px)); } { boost::shared_ptr px; boost::shared_ptr px2(new X); BOOST_TEST(px2 == px2); BOOST_TEST(!(px2 != px2)); BOOST_TEST(!(px2 < px2)); BOOST_TEST(px.get() != px2.get()); BOOST_TEST(px != px2); BOOST_TEST(!(px == px2)); BOOST_TEST(px < px2 || px2 < px); BOOST_TEST(!(px < px2 && px2 < px)); } { boost::shared_ptr px(new X); boost::shared_ptr px2(new X); BOOST_TEST(px.get() != px2.get()); BOOST_TEST(px != px2); BOOST_TEST(!(px == px2)); BOOST_TEST(px < px2 || px2 < px); BOOST_TEST(!(px < px2 && px2 < px)); } { boost::shared_ptr px(new X); boost::shared_ptr px2(px); BOOST_TEST(px2 == px2); BOOST_TEST(!(px2 != px2)); BOOST_TEST(!(px2 < px2)); BOOST_TEST(px.get() == px2.get()); BOOST_TEST(px == px2); BOOST_TEST(!(px != px2)); BOOST_TEST(!(px < px2 || px2 < px)); } { boost::shared_ptr px(new X); boost::shared_ptr py(new Y); boost::shared_ptr pz(new Z); BOOST_TEST(px.get() != pz.get()); BOOST_TEST(px != pz); BOOST_TEST(!(px == pz)); BOOST_TEST(py.get() != pz.get()); BOOST_TEST(py != pz); BOOST_TEST(!(py == pz)); boost::shared_ptr pvx(px); BOOST_TEST(pvx == pvx); BOOST_TEST(!(pvx != pvx)); BOOST_TEST(!(pvx < pvx)); boost::shared_ptr pvy(py); boost::shared_ptr pvz(pz); BOOST_TEST(pvx < pvy || pvy < pvx); BOOST_TEST(pvx < pvz || pvz < pvx); BOOST_TEST(pvy < pvz || pvz < pvy); BOOST_TEST(!(pvx < pvy && pvy < pvx)); BOOST_TEST(!(pvx < pvz && pvz < pvx)); BOOST_TEST(!(pvy < pvz && pvz < pvy)); } { boost::shared_ptr pz(new Z); boost::shared_ptr px(pz); BOOST_TEST(px == px); BOOST_TEST(!(px != px)); BOOST_TEST(!(px < px)); boost::shared_ptr py(pz); BOOST_TEST(px.get() == pz.get()); BOOST_TEST(px == pz); BOOST_TEST(!(px != pz)); BOOST_TEST(py.get() == pz.get()); BOOST_TEST(py == pz); BOOST_TEST(!(py != pz)); boost::shared_ptr pvx(px); boost::shared_ptr pvy(py); boost::shared_ptr pvz(pz); // pvx and pvy aren't equal... BOOST_TEST(pvx.get() != pvy.get()); BOOST_TEST(pvx != pvy); BOOST_TEST(!(pvx == pvy)); // ... but they share ownership ... BOOST_TEST(!(pvx < pvy || pvy < pvx)); // ... with pvz BOOST_TEST(!(pvx < pvz || pvz < pvx)); BOOST_TEST(!(pvy < pvz || pvz < pvy)); } } } // namespace n_comparison namespace n_static_cast { struct X { }; struct Y: public X { }; void test() { { boost::shared_ptr pv; boost::shared_ptr pi = boost::static_pointer_cast(pv); BOOST_TEST(pi.get() == 0); boost::shared_ptr px = boost::static_pointer_cast(pv); BOOST_TEST(px.get() == 0); } { boost::shared_ptr pi(new int); boost::shared_ptr pv(pi); boost::shared_ptr pi2 = boost::static_pointer_cast(pv); BOOST_TEST(pi.get() == pi2.get()); BOOST_TEST(!(pi < pi2 || pi2 < pi)); BOOST_TEST(pi.use_count() == 3); BOOST_TEST(pv.use_count() == 3); BOOST_TEST(pi2.use_count() == 3); } { boost::shared_ptr px(new X); boost::shared_ptr pv(px); boost::shared_ptr px2 = boost::static_pointer_cast(pv); BOOST_TEST(px.get() == px2.get()); BOOST_TEST(!(px < px2 || px2 < px)); BOOST_TEST(px.use_count() == 3); BOOST_TEST(pv.use_count() == 3); BOOST_TEST(px2.use_count() == 3); } { boost::shared_ptr px(new Y); boost::shared_ptr py = boost::static_pointer_cast(px); BOOST_TEST(px.get() == py.get()); BOOST_TEST(px.use_count() == 2); BOOST_TEST(py.use_count() == 2); boost::shared_ptr px2(py); BOOST_TEST(!(px < px2 || px2 < px)); } } } // namespace n_static_cast namespace n_dynamic_cast { struct V { virtual ~V() {} }; struct W: public V { }; void test() { { boost::shared_ptr pv; boost::shared_ptr pw = boost::dynamic_pointer_cast(pv); BOOST_TEST(pw.get() == 0); } { boost::shared_ptr pv(static_cast(0)); boost::shared_ptr pw = boost::dynamic_pointer_cast(pv); BOOST_TEST(pw.get() == 0); boost::shared_ptr pv2(pw); BOOST_TEST(pv < pv2 || pv2 < pv); } { boost::shared_ptr pv(static_cast(0)); boost::shared_ptr pw = boost::dynamic_pointer_cast(pv); BOOST_TEST(pw.get() == 0); boost::shared_ptr pv2(pw); BOOST_TEST(pv < pv2 || pv2 < pv); } { boost::shared_ptr pv(new V); boost::shared_ptr pw = boost::dynamic_pointer_cast(pv); BOOST_TEST(pw.get() == 0); boost::shared_ptr pv2(pw); BOOST_TEST(pv < pv2 || pv2 < pv); } { boost::shared_ptr pv(new W); boost::shared_ptr pw = boost::dynamic_pointer_cast(pv); BOOST_TEST(pw.get() == pv.get()); BOOST_TEST(pv.use_count() == 2); BOOST_TEST(pw.use_count() == 2); boost::shared_ptr pv2(pw); BOOST_TEST(!(pv < pv2 || pv2 < pv)); } } } // namespace n_dynamic_cast namespace n_map { struct X { }; void test() { std::vector< boost::shared_ptr > vi; { boost::shared_ptr pi1(new int); boost::shared_ptr pi2(new int); boost::shared_ptr pi3(new int); vi.push_back(pi1); vi.push_back(pi1); vi.push_back(pi1); vi.push_back(pi2); vi.push_back(pi1); vi.push_back(pi2); vi.push_back(pi1); vi.push_back(pi3); vi.push_back(pi3); vi.push_back(pi2); vi.push_back(pi1); } std::vector< boost::shared_ptr > vx; { boost::shared_ptr px1(new X); boost::shared_ptr px2(new X); boost::shared_ptr px3(new X); vx.push_back(px2); vx.push_back(px2); vx.push_back(px1); vx.push_back(px2); vx.push_back(px1); vx.push_back(px1); vx.push_back(px1); vx.push_back(px2); vx.push_back(px1); vx.push_back(px3); vx.push_back(px2); } std::map< boost::shared_ptr, long > m; { for(std::vector< boost::shared_ptr >::iterator i = vi.begin(); i != vi.end(); ++i) { ++m[*i]; } } { for(std::vector< boost::shared_ptr >::iterator i = vx.begin(); i != vx.end(); ++i) { ++m[*i]; } } { for(std::map< boost::shared_ptr, long >::iterator i = m.begin(); i != m.end(); ++i) { BOOST_TEST(i->first.use_count() == i->second + 1); } } } } // namespace n_map namespace n_transitive { struct X { X(): next() {} boost::shared_ptr next; }; void test() { boost::shared_ptr p(new X); p->next = boost::shared_ptr(new X); BOOST_TEST(!p->next->next); p = p->next; BOOST_TEST(!p->next); } } // namespace n_transitive namespace n_report_1 { class foo { public: foo(): m_self(this) { } void suicide() { m_self.reset(); } private: boost::shared_ptr m_self; }; void test() { foo * foo_ptr = new foo; foo_ptr->suicide(); } } // namespace n_report_1 // Test case by Per Kristensen namespace n_report_2 { class foo { public: void setWeak(boost::shared_ptr s) { w = s; } private: boost::weak_ptr w; }; class deleter { public: deleter(): lock(0) { } ~deleter() { BOOST_TEST(lock == 0); } void operator() (foo * p) { ++lock; delete p; --lock; } private: int lock; }; void test() { boost::shared_ptr s(new foo, deleter()); s->setWeak(s); s.reset(); } } // namespace n_report_2 namespace n_old { int cnt = 0; struct X { X() { ++cnt; } ~X() // virtual destructor deliberately omitted { --cnt; } virtual int id() const { return 1; } private: X(X const &); X & operator= (X const &); }; struct Y: public X { Y() { ++cnt; } ~Y() { --cnt; } virtual int id() const { return 2; } private: Y(Y const &); Y & operator= (Y const &); }; int * get_object() { ++cnt; return &cnt; } void release_object(int * p) { BOOST_TEST(p == &cnt); --cnt; } template void test_is_X(boost::shared_ptr const & p) { BOOST_TEST(p->id() == 1); BOOST_TEST((*p).id() == 1); } template void test_is_X(boost::weak_ptr const & p) { BOOST_TEST(p.get() != 0); BOOST_TEST(p.get()->id() == 1); } template void test_is_Y(boost::shared_ptr const & p) { BOOST_TEST(p->id() == 2); BOOST_TEST((*p).id() == 2); } template void test_is_Y(boost::weak_ptr const & p) { boost::shared_ptr q = boost::make_shared(p); BOOST_TEST(q.get() != 0); BOOST_TEST(q->id() == 2); } template void test_eq(T const & a, T const & b) { BOOST_TEST(a == b); BOOST_TEST(!(a != b)); BOOST_TEST(!(a < b)); BOOST_TEST(!(b < a)); } template void test_ne(T const & a, T const & b) { BOOST_TEST(!(a == b)); BOOST_TEST(a != b); BOOST_TEST(a < b || b < a); BOOST_TEST(!(a < b && b < a)); } void test_shared(boost::weak_ptr const & a, boost::weak_ptr const & b) { BOOST_TEST(!(a < b)); BOOST_TEST(!(b < a)); } void test_nonshared(boost::weak_ptr const & a, boost::weak_ptr const & b) { BOOST_TEST(a < b || b < a); BOOST_TEST(!(a < b && b < a)); } template void test_eq2(T const & a, U const & b) { BOOST_TEST(a == b); BOOST_TEST(!(a != b)); } template void test_ne2(T const & a, U const & b) { BOOST_TEST(!(a == b)); BOOST_TEST(a != b); } template void test_is_zero(boost::shared_ptr const & p) { BOOST_TEST(!p); BOOST_TEST(p.get() == 0); } template void test_is_nonzero(boost::shared_ptr const & p) { // p? true: false is used to test p in a boolean context. // BOOST_TEST(p) is not guaranteed to test the conversion, // as the macro might test !!p instead. BOOST_TEST(p? true: false); BOOST_TEST(p.get() != 0); } void test() { using namespace boost; { shared_ptr p(new Y); shared_ptr p2(new X); test_is_nonzero(p); test_is_nonzero(p2); test_is_Y(p); test_is_X(p2); test_ne(p, p2); { shared_ptr q(p); test_eq(p, q); } shared_ptr p3 = dynamic_pointer_cast(p); shared_ptr p4 = dynamic_pointer_cast(p2); test_is_nonzero(p3); test_is_zero(p4); BOOST_TEST(p.use_count() == 2); BOOST_TEST(p2.use_count() == 1); BOOST_TEST(p3.use_count() == 2); test_is_Y(p3); test_eq2(p, p3); test_ne2(p2, p4); shared_ptr p5(p); test_is_nonzero(p5); test_eq2(p, p5); weak_ptr wp1(p2); BOOST_TEST(!wp1.expired()); BOOST_TEST(wp1.use_count() != 0); p.reset(); p2.reset(); p3.reset(); p4.reset(); test_is_zero(p); test_is_zero(p2); test_is_zero(p3); test_is_zero(p4); BOOST_TEST(p5.use_count() == 1); BOOST_TEST(wp1.expired()); BOOST_TEST(wp1.use_count() == 0); try { shared_ptr sp1(wp1); BOOST_ERROR("shared_ptr sp1(wp1) failed to throw"); } catch(boost::bad_weak_ptr const &) { } test_is_zero(boost::make_shared(wp1)); weak_ptr wp2 = static_pointer_cast(p5); BOOST_TEST(wp2.use_count() == 1); test_is_Y(wp2); test_nonshared(wp1, wp2); // Scoped to not affect the subsequent use_count() tests. { shared_ptr sp2(wp2); test_is_nonzero(boost::make_shared(wp2)); } weak_ptr wp3 = dynamic_pointer_cast(boost::make_shared(wp2)); BOOST_TEST(wp3.use_count() == 1); test_shared(wp2, wp3); weak_ptr wp4(wp3); BOOST_TEST(wp4.use_count() == 1); test_shared(wp2, wp4); wp1 = p2; test_is_zero(boost::make_shared(wp1)); wp1 = p4; wp1 = wp3; wp1 = wp2; BOOST_TEST(wp1.use_count() == 1); test_shared(wp1, wp2); weak_ptr wp5; bool b1 = wp1 < wp5; bool b2 = wp5 < wp1; p5.reset(); BOOST_TEST(wp1.use_count() == 0); BOOST_TEST(wp2.use_count() == 0); BOOST_TEST(wp3.use_count() == 0); // Test operator< stability for std::set< weak_ptr<> > // Thanks to Joe Gottman for pointing this out BOOST_TEST(b1 == (wp1 < wp5)); BOOST_TEST(b2 == (wp5 < wp1)); { // note that both get_object and release_object deal with int* shared_ptr p6(get_object(), release_object); } } BOOST_TEST(cnt == 0); } } // namespace n_old namespace n_spt_incomplete { class file; boost::shared_ptr fopen(char const * name, char const * mode); void fread(boost::shared_ptr f, void * data, long size); int file_instances = 0; void test() { BOOST_TEST(file_instances == 0); { boost::shared_ptr pf = fopen("name", "mode"); BOOST_TEST(file_instances == 1); fread(pf, 0, 17041); } BOOST_TEST(file_instances == 0); } } // namespace n_spt_incomplete namespace n_spt_pimpl { class file { private: class impl; boost::shared_ptr pimpl_; public: file(char const * name, char const * mode); // compiler generated members are fine and useful void read(void * data, long size); long total_size() const; }; int file_instances = 0; void test() { BOOST_TEST(file_instances == 0); { file f("name", "mode"); BOOST_TEST(file_instances == 1); f.read(0, 152); file f2(f); BOOST_TEST(file_instances == 1); f2.read(0, 894); BOOST_TEST(f.total_size() == 152+894); { file f3("name2", "mode2"); BOOST_TEST(file_instances == 2); } BOOST_TEST(file_instances == 1); } BOOST_TEST(file_instances == 0); } } // namespace n_spt_pimpl namespace n_spt_abstract { class X { public: virtual void f(int) = 0; virtual int g() = 0; protected: ~X() {} }; boost::shared_ptr createX(); int X_instances = 0; void test() { BOOST_TEST(X_instances == 0); { boost::shared_ptr px = createX(); BOOST_TEST(X_instances == 1); px->f(18); px->f(152); BOOST_TEST(px->g() == 170); } BOOST_TEST(X_instances == 0); } } // namespace n_spt_abstract namespace n_spt_preventing_delete { int X_instances = 0; class X { private: X() { ++X_instances; } ~X() { --X_instances; } class deleter; friend class deleter; class deleter { public: void operator()(X * p) { delete p; } }; public: static boost::shared_ptr create() { boost::shared_ptr px(new X, X::deleter()); return px; } }; void test() { BOOST_TEST(X_instances == 0); { boost::shared_ptr px = X::create(); BOOST_TEST(X_instances == 1); } BOOST_TEST(X_instances == 0); } } // namespace n_spt_preventing_delete namespace n_spt_array { int X_instances = 0; struct X { X() { ++X_instances; } ~X() { --X_instances; } }; void test() { BOOST_TEST(X_instances == 0); { boost::shared_ptr px(new X[4], boost::checked_array_deleter()); BOOST_TEST(X_instances == 4); } BOOST_TEST(X_instances == 0); } } // namespace n_spt_array namespace n_spt_static { class X { public: X() { } private: void operator delete(void *); }; struct null_deleter { void operator()(void const *) const { } }; static X x; void test() { boost::shared_ptr px(&x, null_deleter()); } } // namespace n_spt_static namespace n_spt_intrusive { void test() { } } // namespace n_spt_intrusive namespace n_spt_another_sp { void test() { } } // namespace n_spt_another_sp namespace n_spt_shared_from_this { class X { public: virtual void f() = 0; protected: ~X() {} }; class Y { public: virtual boost::shared_ptr getX() = 0; protected: ~Y() {} }; class impl: public X, public Y { private: boost::weak_ptr weak_this; impl(impl const &); impl & operator=(impl const &); impl() {} public: static boost::shared_ptr create() { boost::shared_ptr pi(new impl); pi->weak_this = pi; return pi; } virtual void f() {} virtual boost::shared_ptr getX() { boost::shared_ptr px = boost::make_shared(weak_this); return px; } }; void test() { boost::shared_ptr py = impl::create(); BOOST_TEST(py.get() != 0); BOOST_TEST(py.use_count() == 1); boost::shared_ptr px = py->getX(); BOOST_TEST(px.get() != 0); BOOST_TEST(py.use_count() == 2); boost::shared_ptr py2 = boost::dynamic_pointer_cast(px); BOOST_TEST(py.get() == py2.get()); BOOST_TEST(!(py < py2 || py2 < py)); BOOST_TEST(py.use_count() == 3); } } // namespace n_spt_shared_from_this namespace n_spt_wrap { void test() { } } // namespace n_spt_wrap int main() { n_element_type::test(); n_constructors::test(); n_assignment::test(); n_reset::test(); n_access::test(); n_use_count::test(); n_swap::test(); n_comparison::test(); n_static_cast::test(); n_dynamic_cast::test(); n_map::test(); n_transitive::test(); n_report_1::test(); n_report_2::test(); n_old::test(); n_spt_incomplete::test(); n_spt_pimpl::test(); n_spt_abstract::test(); n_spt_preventing_delete::test(); n_spt_array::test(); n_spt_static::test(); n_spt_intrusive::test(); n_spt_another_sp::test(); n_spt_shared_from_this::test(); // n_spt_post_constructors::test(); n_spt_wrap::test(); return boost::report_errors(); } namespace n_spt_incomplete { class file { public: file(): fread_called(false) { ++file_instances; } ~file() { BOOST_TEST(fread_called); --file_instances; } bool fread_called; }; boost::shared_ptr fopen(char const *, char const *) { boost::shared_ptr pf(new file); return pf; } void fread(boost::shared_ptr pf, void *, long) { pf->fread_called = true; } } // namespace n_spt_incomplete namespace n_spt_pimpl { class file::impl { private: impl(impl const &); impl & operator=(impl const &); long total_size_; public: impl(char const *, char const *): total_size_(0) { ++file_instances; } ~impl() { --file_instances; } void read(void *, long size) { total_size_ += size; } long total_size() const { return total_size_; } }; file::file(char const * name, char const * mode): pimpl_(new impl(name, mode)) { } void file::read(void * data, long size) { pimpl_->read(data, size); } long file::total_size() const { return pimpl_->total_size(); } } // namespace n_spt_pimpl namespace n_spt_abstract { class X_impl: public X { private: X_impl(X_impl const &); X_impl & operator=(X_impl const &); int n_; public: X_impl(): n_(0) { ++X_instances; } ~X_impl() { --X_instances; } virtual void f(int n) { n_ += n; } virtual int g() { return n_; } }; boost::shared_ptr createX() { boost::shared_ptr px(new X_impl); return px; } } // namespace n_spt_abstract