// ====================================================================== // // Test compilability and basic functionality of Utility/memory.h // // Author: W. E. Brown, 2010-03-19, adapted from the boost library's // shared_ptr and related functionality whose internal attributions bear // the following various notices: // // Copyright (c) 2002, 2003 Peter Dimov // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt // // ====================================================================== #include "CLHEP/Utility/memory.h" #include #include #include using namespace CLHEP; using CLHEP::shared_ptr; using CLHEP::weak_ptr; #if defined(_MSC_VER) && (_MSC_VER >= 1310) # pragma warning (disable : 4675) // suppress ADL warning #endif namespace n_element_type { void f(int &) { } void test() { typedef shared_ptr::element_type T; T t; f(t); } } // namespace n_element_type namespace n_constructors { class incomplete; void default_constructor() { { shared_ptr pi; assert(pi? false: true); assert(!pi); assert(pi.get() == 0); assert(pi.use_count() == 0); } { shared_ptr pv; assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 0); } { shared_ptr px; assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 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; // virtual inheritance stresses the implementation struct Y : public A , public virtual X { static long instances; Y() { ++instances; } ~Y() { --instances; } private: Y(Y const &); Y & operator= (Y const &); }; long Y::instances = 0; template< class T > void pc0_test(T * p) { assert(p == 0); shared_ptr pt(p); assert(pt? false: true); assert(!pt); assert(pt.get() == 0); assert(pt.use_count() == 1); assert(pt.unique()); } void pointer_constructor() { pc0_test(static_cast(0)); pc0_test(static_cast(0)); pc0_test(static_cast(0)); pc0_test(static_cast(0)); { shared_ptr pi(static_cast(0)); assert(pi? false: true); assert(!pi); assert(pi.get() == 0); assert(pi.use_count() == 1); assert(pi.unique()); } { shared_ptr pi(static_cast(0)); assert(pi? false: true); assert(!pi); assert(pi.get() == 0); assert(pi.use_count() == 1); assert(pi.unique()); } { shared_ptr pv(static_cast(0)); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); } { shared_ptr pv(static_cast(0)); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); } pc0_test(static_cast(0)); pc0_test(static_cast(0)); pc0_test(static_cast(0)); pc0_test(static_cast(0)); { shared_ptr px(static_cast(0)); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); } { shared_ptr px(static_cast(0)); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); } { shared_ptr px(static_cast(0)); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); } { shared_ptr pv(static_cast(0)); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); } { shared_ptr pv(static_cast(0)); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); } { int * p = new int(7); shared_ptr pi(p); assert(pi? true: false); assert(!!pi); assert(pi.get() == p); assert(pi.use_count() == 1); assert(pi.unique()); assert(*pi == 7); } { int * p = new int(7); shared_ptr pi(p); assert(pi? true: false); assert(!!pi); assert(pi.get() == p); assert(pi.use_count() == 1); assert(pi.unique()); assert(*pi == 7); } { int * p = new int(7); shared_ptr pv(p); assert(pv? true: false); assert(!!pv); assert(pv.get() == p); assert(pv.use_count() == 1); assert(pv.unique()); } { int * p = new int(7); shared_ptr pv(p); assert(pv? true: false); assert(!!pv); assert(pv.get() == p); assert(pv.use_count() == 1); assert(pv.unique()); } assert(X::instances == 0); { X * p = new X; shared_ptr px(p); assert(px? true: false); assert(!!px); assert(px.get() == p); assert(px.use_count() == 1); assert(px.unique()); assert(X::instances == 1); } assert(X::instances == 0); { X * p = new X; shared_ptr px(p); assert(px? true: false); assert(!!px); assert(px.get() == p); assert(px.use_count() == 1); assert(px.unique()); assert(X::instances == 1); } assert(X::instances == 0); { X * p = new X; shared_ptr pv(p); assert(pv? true: false); assert(!!pv); assert(pv.get() == p); assert(pv.use_count() == 1); assert(pv.unique()); assert(X::instances == 1); } assert(X::instances == 0); { X * p = new X; shared_ptr pv(p); assert(pv? true: false); assert(!!pv); assert(pv.get() == p); assert(pv.use_count() == 1); assert(pv.unique()); assert(X::instances == 1); } assert(X::instances == 0); assert(Y::instances == 0); { Y * p = new Y; shared_ptr px(p); assert(px? true: false); assert(!!px); assert(px.get() == p); assert(px.use_count() == 1); assert(px.unique()); assert(X::instances == 1); assert(Y::instances == 1); } assert(X::instances == 0); assert(Y::instances == 0); { Y * p = new Y; shared_ptr px(p); assert(px? true: false); assert(!!px); assert(px.get() == p); assert(px.use_count() == 1); assert(px.unique()); assert(X::instances == 1); assert(Y::instances == 1); } assert(X::instances == 0); assert(Y::instances == 0); } int m = 0; void deleter(int * p) { assert(p == 0); } void deleter2(int * p) { assert(p == &m); ++*p; } struct deleter3 { void operator()(incomplete * p) { assert(p == 0); } }; incomplete * p0 = 0; void deleter_constructor() { { shared_ptr pi(static_cast(0), deleter); assert(pi? false: true); assert(!pi); assert(pi.get() == 0); assert(pi.use_count() == 1); assert(pi.unique()); } { shared_ptr pv(static_cast(0), &deleter); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); } { shared_ptr pv(static_cast(0), deleter); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); } { shared_ptr px(p0, deleter3()); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); } { shared_ptr pv(p0, deleter3()); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); } { shared_ptr pv(p0, deleter3()); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); } assert(m == 0); { shared_ptr pi(&m, deleter2); assert(pi? true: false); assert(!!pi); assert(pi.get() == &m); assert(pi.use_count() == 1); assert(pi.unique()); } assert(m == 1); { shared_ptr pi(&m, &deleter2); assert(pi? true: false); assert(!!pi); assert(pi.get() == &m); assert(pi.use_count() == 1); assert(pi.unique()); } assert(m == 2); { shared_ptr pv(&m, deleter2); assert(pv? true: false); assert(!!pv); assert(pv.get() == &m); assert(pv.use_count() == 1); assert(pv.unique()); } assert(m == 3); { shared_ptr pv(&m, &deleter2); assert(pv? true: false); assert(!!pv); assert(pv.get() == &m); assert(pv.use_count() == 1); assert(pv.unique()); } assert(m == 4); } void copy_constructor() { { shared_ptr pi; shared_ptr pi2(pi); assert(pi2 == pi); assert(pi2? false: true); assert(!pi2); assert(pi2.get() == 0); assert(pi2.use_count() == pi.use_count()); shared_ptr pi3(pi); assert(pi3 == pi); assert(pi3? false: true); assert(!pi3); assert(pi3.get() == 0); assert(pi3.use_count() == pi.use_count()); shared_ptr pi4(pi3); assert(pi4 == pi3); assert(pi4? false: true); assert(!pi4); assert(pi4.get() == 0); assert(pi4.use_count() == pi3.use_count()); } { shared_ptr pv; shared_ptr pv2(pv); assert(pv2 == pv); assert(pv2? false: true); assert(!pv2); assert(pv2.get() == 0); assert(pv2.use_count() == pv.use_count()); } { shared_ptr px; shared_ptr px2(px); assert(px2 == px); assert(px2? false: true); assert(!px2); assert(px2.get() == 0); assert(px2.use_count() == px.use_count()); shared_ptr px3(px); assert(px3 == px); assert(px3? false: true); assert(!px3); assert(px3.get() == 0); assert(px3.use_count() == px.use_count()); } { shared_ptr pi(static_cast(0)); shared_ptr pi2(pi); assert(pi2 == pi); assert(pi2? false: true); assert(!pi2); assert(pi2.get() == 0); assert(pi2.use_count() == 2); assert(!pi2.unique()); assert(pi2.use_count() == pi.use_count()); assert(!(pi < pi2 || pi2 < pi)); // shared ownership test shared_ptr pi3(pi); assert(pi3 == pi); assert(pi3? false: true); assert(!pi3); assert(pi3.get() == 0); assert(pi3.use_count() == 3); assert(!pi3.unique()); assert(pi3.use_count() == pi.use_count()); assert(!(pi < pi3 || pi3 < pi)); // shared ownership test shared_ptr pi4(pi2); assert(pi4 == pi2); assert(pi4? false: true); assert(!pi4); assert(pi4.get() == 0); assert(pi4.use_count() == 4); assert(!pi4.unique()); assert(pi4.use_count() == pi2.use_count()); assert(!(pi2 < pi4 || pi4 < pi2)); // shared ownership test assert(pi3.use_count() == pi4.use_count()); assert(!(pi3 < pi4 || pi4 < pi3)); // shared ownership test } { shared_ptr px(static_cast(0)); shared_ptr px2(px); assert(px2 == px); assert(px2? false: true); assert(!px2); assert(px2.get() == 0); assert(px2.use_count() == 2); assert(!px2.unique()); assert(px2.use_count() == px.use_count()); assert(!(px < px2 || px2 < px)); // shared ownership test shared_ptr px3(px); assert(px3 == px); assert(px3? false: true); assert(!px3); assert(px3.get() == 0); assert(px3.use_count() == 3); assert(!px3.unique()); assert(px3.use_count() == px.use_count()); assert(!(px < px3 || px3 < px)); // shared ownership test shared_ptr px4(px2); assert(px4 == px2); assert(px4? false: true); assert(!px4); assert(px4.get() == 0); assert(px4.use_count() == 4); assert(!px4.unique()); assert(px4.use_count() == px2.use_count()); assert(!(px2 < px4 || px4 < px2)); // shared ownership test assert(px3.use_count() == px4.use_count()); assert(!(px3 < px4 || px4 < px3)); // shared ownership test } { int * p = new int(7); shared_ptr pi(p); shared_ptr pi2(pi); assert(pi2 == pi); assert(pi2? true: false); assert(!!pi2); assert(pi2.get() == p); assert(pi2.use_count() == 2); assert(!pi2.unique()); assert(*pi2 == 7); assert(pi2.use_count() == pi.use_count()); assert(!(pi < pi2 || pi2 < pi)); // shared ownership test } { int * p = new int(7); shared_ptr pv(p); assert(pv.get() == p); shared_ptr pv2(pv); assert(pv2 == pv); assert(pv2? true: false); assert(!!pv2); assert(pv2.get() == p); assert(pv2.use_count() == 2); assert(!pv2.unique()); assert(pv2.use_count() == pv.use_count()); assert(!(pv < pv2 || pv2 < pv)); // shared ownership test } assert(X::instances == 0); { X * p = new X; shared_ptr px(p); assert(px.get() == p); shared_ptr px2(px); assert(px2 == px); assert(px2? true: false); assert(!!px2); assert(px2.get() == p); assert(px2.use_count() == 2); assert(!px2.unique()); assert(X::instances == 1); assert(px2.use_count() == px.use_count()); assert(!(px < px2 || px2 < px)); // shared ownership test shared_ptr px3(px); assert(px3 == px); assert(px3? true: false); assert(!!px3); assert(px3.get() == p); assert(px3.use_count() == 3); assert(!px3.unique()); assert(px3.use_count() == px.use_count()); assert(!(px < px3 || px3 < px)); // shared ownership test shared_ptr px4(px2); assert(px4 == px2); assert(px4? true: false); assert(!!px4); assert(px4.get() == p); assert(px4.use_count() == 4); assert(!px4.unique()); assert(px4.use_count() == px2.use_count()); assert(!(px2 < px4 || px4 < px2)); // shared ownership test assert(px3.use_count() == px4.use_count()); assert(!(px3 < px4 || px4 < px3)); // shared ownership test } assert(X::instances == 0); assert(Y::instances == 0); { Y * p = new Y; shared_ptr py(p); assert(py.get() == p); shared_ptr px(py); assert(px == py); assert(px? true: false); assert(!!px); assert(px.get() == p); assert(px.use_count() == 2); assert(!px.unique()); assert(px.use_count() == py.use_count()); assert(!(px < py || py < px)); // shared ownership test assert(X::instances == 1); assert(Y::instances == 1); shared_ptr pv(px); assert(pv == px); assert(pv? true: false); assert(!!pv); assert(pv.get() == px.get()); assert(pv.use_count() == 3); assert(!pv.unique()); assert(pv.use_count() == px.use_count()); assert(!(px < pv || pv < px)); // shared ownership test shared_ptr pv2(py); assert(pv2 == py); assert(pv2? true: false); assert(!!pv2); assert(pv2.get() == py.get()); assert(pv2.use_count() == 4); assert(!pv2.unique()); assert(pv2.use_count() == py.use_count()); assert(!(py < pv2 || pv2 < py)); // shared ownership test assert(pv.use_count() == pv2.use_count()); assert(!(pv < pv2 || pv2 < pv)); // shared ownership test } assert(X::instances == 0); assert(Y::instances == 0); } void weak_ptr_constructor() { { weak_ptr wp; assert(wp.use_count() == 0); try { shared_ptr p2(wp); throw "shared_ptr p2(wp) failed to throw"; } catch(bad_weak_ptr) { } try { shared_ptr p3(wp); throw "shared_ptr p3(wp) failed to throw"; } catch(bad_weak_ptr) { } } { shared_ptr p; weak_ptr wp(p); if(wp.use_count() != 0) // 0 allowed but not required { shared_ptr p2(wp); assert(p2.use_count() == wp.use_count()); assert(p2.get() == 0); shared_ptr p3(wp); assert(p3.use_count() == wp.use_count()); assert(p3.get() == 0); } } { shared_ptr p(new Y); weak_ptr wp(p); { shared_ptr p2(wp); assert(p2? true: false); assert(!!p2); assert(p2.get() == p.get()); assert(p2.use_count() == 2); assert(!p2.unique()); assert(p2.use_count() == wp.use_count()); assert(p.use_count() == p2.use_count()); assert(!(p < p2 || p2 < p)); // shared ownership test shared_ptr p3(wp); assert(p3? true: false); assert(!!p3); assert(p3.get() == p.get()); assert(p3.use_count() == 3); assert(!p3.unique()); assert(p3.use_count() == wp.use_count()); assert(p.use_count() == p3.use_count()); } p.reset(); assert(wp.use_count() == 0); try { shared_ptr p2(wp); throw "shared_ptr p2(wp) failed to throw"; } catch(bad_weak_ptr) { } try { shared_ptr p3(wp); throw "shared_ptr p3(wp) failed to throw"; } catch(bad_weak_ptr) { } } } void auto_ptr_constructor() { { std::auto_ptr p; shared_ptr pi(p); assert(pi? false: true); assert(!pi); assert(pi.get() == 0); assert(pi.use_count() == 1); assert(pi.unique()); assert(p.get() == 0); } { std::auto_ptr p; shared_ptr pi(p); assert(pi? false: true); assert(!pi); assert(pi.get() == 0); assert(pi.use_count() == 1); assert(pi.unique()); assert(p.get() == 0); } { std::auto_ptr p; shared_ptr pv(p); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); assert(p.get() == 0); } { std::auto_ptr p; shared_ptr pv(p); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); assert(p.get() == 0); } { std::auto_ptr p; shared_ptr px(p); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); assert(p.get() == 0); } { std::auto_ptr p; shared_ptr px(p); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); assert(p.get() == 0); } { std::auto_ptr p; shared_ptr px(p); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); assert(p.get() == 0); } { std::auto_ptr p; shared_ptr px(p); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); assert(p.get() == 0); } { std::auto_ptr p; shared_ptr pv(p); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); assert(p.get() == 0); } { std::auto_ptr p; shared_ptr pv(p); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); assert(p.get() == 0); } { std::auto_ptr p(new int(7)); int * q = p.get(); shared_ptr pi(p); assert(pi? true: false); assert(!!pi); assert(pi.get() == q); assert(pi.use_count() == 1); assert(pi.unique()); assert(*pi == 7); assert(p.get() == 0); } { std::auto_ptr p(new int(7)); int * q = p.get(); shared_ptr pi(p); assert(pi? true: false); assert(!!pi); assert(pi.get() == q); assert(pi.use_count() == 1); assert(pi.unique()); assert(*pi == 7); assert(p.get() == 0); } { std::auto_ptr p(new int(7)); int * q = p.get(); shared_ptr pv(p); assert(pv? true: false); assert(!!pv); assert(pv.get() == q); assert(pv.use_count() == 1); assert(pv.unique()); assert(p.get() == 0); } { std::auto_ptr p(new int(7)); int * q = p.get(); shared_ptr pv(p); assert(pv? true: false); assert(!!pv); assert(pv.get() == q); assert(pv.use_count() == 1); assert(pv.unique()); assert(p.get() == 0); } assert(X::instances == 0); { std::auto_ptr p(new X); X * q = p.get(); shared_ptr px(p); assert(px? true: false); assert(!!px); assert(px.get() == q); assert(px.use_count() == 1); assert(px.unique()); assert(X::instances == 1); assert(p.get() == 0); } assert(X::instances == 0); { std::auto_ptr p(new X); X * q = p.get(); shared_ptr px(p); assert(px? true: false); assert(!!px); assert(px.get() == q); assert(px.use_count() == 1); assert(px.unique()); assert(X::instances == 1); assert(p.get() == 0); } assert(X::instances == 0); { std::auto_ptr p(new X); X * q = p.get(); shared_ptr pv(p); assert(pv? true: false); assert(!!pv); assert(pv.get() == q); assert(pv.use_count() == 1); assert(pv.unique()); assert(X::instances == 1); assert(p.get() == 0); } assert(X::instances == 0); { std::auto_ptr p(new X); X * q = p.get(); shared_ptr pv(p); assert(pv? true: false); assert(!!pv); assert(pv.get() == q); assert(pv.use_count() == 1); assert(pv.unique()); assert(X::instances == 1); assert(p.get() == 0); } assert(X::instances == 0); assert(Y::instances == 0); { std::auto_ptr p(new Y); Y * q = p.get(); shared_ptr px(p); assert(px? true: false); assert(!!px); assert(px.get() == q); assert(px.use_count() == 1); assert(px.unique()); assert(X::instances == 1); assert(Y::instances == 1); assert(p.get() == 0); } assert(X::instances == 0); assert(Y::instances == 0); { std::auto_ptr p(new Y); Y * q = p.get(); shared_ptr px(p); assert(px? true: false); assert(!!px); assert(px.get() == q); assert(px.use_count() == 1); assert(px.unique()); assert(X::instances == 1); assert(Y::instances == 1); assert(p.get() == 0); } assert(X::instances == 0); assert(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 virtual X { static long instances; Y() { ++instances; } ~Y() { --instances; } private: Y(Y const &); Y & operator= (Y const &); }; long Y::instances = 0; void copy_assignment() { { shared_ptr p1; p1 = p1; assert(p1 == p1); assert(p1? false: true); assert(!p1); assert(p1.get() == 0); shared_ptr p2; p1 = p2; assert(p1 == p2); assert(p1? false: true); assert(!p1); assert(p1.get() == 0); shared_ptr p3(p1); p1 = p3; assert(p1 == p3); assert(p1? false: true); assert(!p1); assert(p1.get() == 0); } { shared_ptr p1; p1 = p1; assert(p1 == p1); assert(p1? false: true); assert(!p1); assert(p1.get() == 0); shared_ptr p2; p1 = p2; assert(p1 == p2); assert(p1? false: true); assert(!p1); assert(p1.get() == 0); shared_ptr p3(p1); p1 = p3; assert(p1 == p3); assert(p1? false: true); assert(!p1); assert(p1.get() == 0); shared_ptr p4(new int); assert(p4.use_count() == 1); p1 = p4; assert(p1 == p4); assert(!(p1 < p4 || p4 < p1)); assert(p1.use_count() == 2); assert(p4.use_count() == 2); p1 = p3; assert(p1 == p3); assert(p4.use_count() == 1); } { shared_ptr p1; p1 = p1; assert(p1 == p1); assert(p1? false: true); assert(!p1); assert(p1.get() == 0); shared_ptr p2; p1 = p2; assert(p1 == p2); assert(p1? false: true); assert(!p1); assert(p1.get() == 0); shared_ptr p3(p1); p1 = p3; assert(p1 == p3); assert(p1? false: true); assert(!p1); assert(p1.get() == 0); assert(X::instances == 0); shared_ptr p4(new X); assert(X::instances == 1); p1 = p4; assert(X::instances == 1); assert(p1 == p4); assert(!(p1 < p4 || p4 < p1)); assert(p1.use_count() == 2); p1 = p2; assert(p1 == p2); assert(X::instances == 1); p4 = p3; assert(p4 == p3); assert(X::instances == 0); } } void conversion_assignment() { { shared_ptr p1; shared_ptr p2; p1 = p2; assert(p1 == p2); assert(p1? false: true); assert(!p1); assert(p1.get() == 0); shared_ptr p4(new int); assert(p4.use_count() == 1); shared_ptr p5(p4); assert(p4.use_count() == 2); p1 = p4; assert(p1 == p4); assert(!(p1 < p5 || p5 < p1)); assert(p1.use_count() == 3); assert(p4.use_count() == 3); p1 = p2; assert(p1 == p2); assert(p4.use_count() == 2); } { shared_ptr p1; shared_ptr p2; p1 = p2; assert(p1 == p2); assert(p1? false: true); assert(!p1); assert(p1.get() == 0); assert(X::instances == 0); assert(Y::instances == 0); shared_ptr p4(new Y); assert(X::instances == 1); assert(Y::instances == 1); assert(p4.use_count() == 1); shared_ptr p5(p4); assert(p4.use_count() == 2); p1 = p4; assert(X::instances == 1); assert(Y::instances == 1); assert(p1 == p4); assert(!(p1 < p5 || p5 < p1)); assert(p1.use_count() == 3); assert(p4.use_count() == 3); p1 = p2; assert(p1 == p2); assert(X::instances == 1); assert(Y::instances == 1); assert(p4.use_count() == 2); p4 = p2; p5 = p2; assert(p4 == p2); assert(X::instances == 0); assert(Y::instances == 0); } } void auto_ptr_assignment() { { shared_ptr p1; std::auto_ptr p2; p1 = p2; assert(p1? false: true); assert(!p1); assert(p1.get() == 0); assert(p1.use_count() == 1); int * p = new int; std::auto_ptr p3(p); p1 = p3; assert(p1.get() == p); assert(p1.use_count() == 1); assert(p3.get() == 0); p1 = p2; assert(p1? false: true); assert(!p1); assert(p1.get() == 0); assert(p1.use_count() == 1); } { shared_ptr p1; std::auto_ptr p2; p1 = p2; assert(p1? false: true); assert(!p1); assert(p1.get() == 0); assert(p1.use_count() == 1); int * p = new int; std::auto_ptr p3(p); p1 = p3; assert(p1.get() == p); assert(p1.use_count() == 1); assert(p3.get() == 0); p1 = p2; assert(p1? false: true); assert(!p1); assert(p1.get() == 0); assert(p1.use_count() == 1); } { shared_ptr p1; std::auto_ptr p2; p1 = p2; assert(p1? false: true); assert(!p1); assert(p1.get() == 0); assert(p1.use_count() == 1); assert(X::instances == 0); assert(Y::instances == 0); Y * p = new Y; std::auto_ptr p3(p); assert(X::instances == 1); assert(Y::instances == 1); p1 = p3; assert(p1.get() == p); assert(p1.use_count() == 1); assert(X::instances == 1); assert(Y::instances == 1); assert(p3.get() == 0); p1 = p2; assert(p1? false: true); assert(!p1); assert(p1.get() == 0); assert(p1.use_count() == 1); assert(X::instances == 0); assert(Y::instances == 0); } } void test() { copy_assignment(); conversion_assignment(); auto_ptr_assignment(); } } // namespace n_assignment namespace n_reset { class incomplete; incomplete * p0 = 0; void deleter(incomplete *) { } struct X { static long instances; X() { ++instances; } ~X() { --instances; } private: X(X const &); X & operator= (X const &); }; long X::instances = 0; void plain_reset() { { shared_ptr pi; pi.reset(); assert(pi? false: true); assert(!pi); assert(pi.get() == 0); assert(pi.use_count() == 0); } { shared_ptr pi(static_cast(0)); pi.reset(); assert(pi? false: true); assert(!pi); assert(pi.get() == 0); assert(pi.use_count() == 0); } { shared_ptr pi(new int); pi.reset(); assert(pi? false: true); assert(!pi); assert(pi.get() == 0); assert(pi.use_count() == 0); } { shared_ptr px; px.reset(); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 0); } { shared_ptr px(p0, deleter); px.reset(); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 0); } { shared_ptr px; px.reset(); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 0); } { assert(X::instances == 0); shared_ptr px(new X); assert(X::instances == 1); px.reset(); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 0); assert(X::instances == 0); } { shared_ptr pv; pv.reset(); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 0); } { assert(X::instances == 0); shared_ptr pv(new X); assert(X::instances == 1); pv.reset(); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 0); assert(X::instances == 0); } } struct A { int dummy; }; struct Y : public A , public virtual X { static long instances; Y() { ++instances; } ~Y() { --instances; } private: Y(Y const &); Y & operator= (Y const &); }; long Y::instances = 0; void pointer_reset() { { shared_ptr pi; pi.reset(static_cast(0)); assert(pi? false: true); assert(!pi); assert(pi.get() == 0); assert(pi.use_count() == 1); assert(pi.unique()); int * p = new int; pi.reset(p); assert(pi? true: false); assert(!!pi); assert(pi.get() == p); assert(pi.use_count() == 1); assert(pi.unique()); pi.reset(static_cast(0)); assert(pi? false: true); assert(!pi); assert(pi.get() == 0); assert(pi.use_count() == 1); assert(pi.unique()); } { shared_ptr px; px.reset(static_cast(0)); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); assert(X::instances == 0); X * p = new X; px.reset(p); assert(px? true: false); assert(!!px); assert(px.get() == p); assert(px.use_count() == 1); assert(px.unique()); assert(X::instances == 1); px.reset(static_cast(0)); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); assert(X::instances == 0); assert(Y::instances == 0); Y * q = new Y; px.reset(q); assert(px? true: false); assert(!!px); assert(px.get() == q); assert(px.use_count() == 1); assert(px.unique()); assert(X::instances == 1); assert(Y::instances == 1); px.reset(static_cast(0)); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); assert(X::instances == 0); assert(Y::instances == 0); } { shared_ptr pv; pv.reset(static_cast(0)); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); assert(X::instances == 0); X * p = new X; pv.reset(p); assert(pv? true: false); assert(!!pv); assert(pv.get() == p); assert(pv.use_count() == 1); assert(pv.unique()); assert(X::instances == 1); pv.reset(static_cast(0)); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); assert(X::instances == 0); assert(Y::instances == 0); Y * q = new Y; pv.reset(q); assert(pv? true: false); assert(!!pv); assert(pv.get() == q); assert(pv.use_count() == 1); assert(pv.unique()); assert(X::instances == 1); assert(Y::instances == 1); pv.reset(static_cast(0)); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); assert(X::instances == 0); assert(Y::instances == 0); } } void * deleted = 0; void deleter2(void * p) { deleted = p; } void deleter_reset() { { shared_ptr pi; pi.reset(static_cast(0), deleter2); assert(pi? false: true); assert(!pi); assert(pi.get() == 0); assert(pi.use_count() == 1); assert(pi.unique()); deleted = π int m = 0; pi.reset(&m, deleter2); assert(deleted == 0); assert(pi? true: false); assert(!!pi); assert(pi.get() == &m); assert(pi.use_count() == 1); assert(pi.unique()); pi.reset(static_cast(0), deleter2); assert(deleted == &m); assert(pi? false: true); assert(!pi); assert(pi.get() == 0); assert(pi.use_count() == 1); assert(pi.unique()); pi.reset(); assert(deleted == 0); } { shared_ptr px; px.reset(static_cast(0), deleter2); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); deleted = &px; X x; px.reset(&x, deleter2); assert(deleted == 0); assert(px? true: false); assert(!!px); assert(px.get() == &x); assert(px.use_count() == 1); assert(px.unique()); px.reset(static_cast(0), deleter2); assert(deleted == &x); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); Y y; px.reset(&y, deleter2); assert(deleted == 0); assert(px? true: false); assert(!!px); assert(px.get() == &y); assert(px.use_count() == 1); assert(px.unique()); px.reset(static_cast(0), deleter2); assert(deleted == &y); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); px.reset(); assert(deleted == 0); } { shared_ptr pv; pv.reset(static_cast(0), deleter2); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); deleted = &pv; X x; pv.reset(&x, deleter2); assert(deleted == 0); assert(pv? true: false); assert(!!pv); assert(pv.get() == &x); assert(pv.use_count() == 1); assert(pv.unique()); pv.reset(static_cast(0), deleter2); assert(deleted == &x); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); Y y; pv.reset(&y, deleter2); assert(deleted == 0); assert(pv? true: false); assert(!!pv); assert(pv.get() == &y); assert(pv.use_count() == 1); assert(pv.unique()); pv.reset(static_cast(0), deleter2); assert(deleted == &y); assert(pv? false: true); assert(!pv); assert(pv.get() == 0); assert(pv.use_count() == 1); assert(pv.unique()); pv.reset(); assert(deleted == 0); } { shared_ptr px; px.reset(p0, deleter2); assert(px? false: true); assert(!px); assert(px.get() == 0); assert(px.use_count() == 1); assert(px.unique()); deleted = &px; px.reset(p0, deleter2); assert(deleted == 0); } } void test() { plain_reset(); pointer_reset(); deleter_reset(); } } // namespace n_reset namespace n_access { struct X { }; void test() { { shared_ptr px; assert(px.get() == 0); assert(px? false: true); assert(!px); assert(get_pointer(px) == px.get()); } { shared_ptr px(static_cast(0)); assert(px.get() == 0); assert(px? false: true); assert(!px); assert(get_pointer(px) == px.get()); } #if 0 { shared_ptr px(static_cast(0), checked_deleter()); assert(px.get() == 0); assert(px? false: true); assert(!px); assert(get_pointer(px) == px.get()); } #endif // 0 { X * p = new X; shared_ptr px(p); assert(px.get() == p); assert(px? true: false); assert(!!px); assert(&*px == px.get()); assert(px.operator ->() == px.get()); assert(get_pointer(px) == px.get()); } #if 0 { X * p = new X; shared_ptr px(p, checked_deleter()); assert(px.get() == p); assert(px? true: false); assert(!!px); assert(&*px == px.get()); assert(px.operator ->() == px.get()); assert(get_pointer(px) == px.get()); } #endif // 0 } } // namespace n_access namespace n_use_count { struct X { }; void test() { { shared_ptr px(static_cast(0)); assert(px.use_count() == 1); assert(px.unique()); shared_ptr px2(px); assert(px2.use_count() == 2); assert(!px2.unique()); assert(px.use_count() == 2); assert(!px.unique()); } { shared_ptr px(new X); assert(px.use_count() == 1); assert(px.unique()); shared_ptr px2(px); assert(px2.use_count() == 2); assert(!px2.unique()); assert(px.use_count() == 2); assert(!px.unique()); } #if 0 { shared_ptr px(new X, checked_deleter()); assert(px.use_count() == 1); assert(px.unique()); shared_ptr px2(px); assert(px2.use_count() == 2); assert(!px2.unique()); assert(px.use_count() == 2); assert(!px.unique()); } #endif // 0 } } // namespace n_use_count namespace n_swap { struct X { }; void test() { { shared_ptr px; shared_ptr px2; px.swap(px2); assert(px.get() == 0); assert(px2.get() == 0); using std::swap; swap(px, px2); assert(px.get() == 0); assert(px2.get() == 0); } { X * p = new X; shared_ptr px; shared_ptr px2(p); shared_ptr px3(px2); px.swap(px2); assert(px.get() == p); assert(px.use_count() == 2); assert(px2.get() == 0); assert(px3.get() == p); assert(px3.use_count() == 2); using std::swap; swap(px, px2); assert(px.get() == 0); assert(px2.get() == p); assert(px2.use_count() == 2); assert(px3.get() == p); assert(px3.use_count() == 2); } { X * p1 = new X; X * p2 = new X; shared_ptr px(p1); shared_ptr px2(p2); shared_ptr px3(px2); px.swap(px2); assert(px.get() == p2); assert(px.use_count() == 2); assert(px2.get() == p1); assert(px2.use_count() == 1); assert(px3.get() == p2); assert(px3.use_count() == 2); using std::swap; swap(px, px2); assert(px.get() == p1); assert(px.use_count() == 1); assert(px2.get() == p2); assert(px2.use_count() == 2); assert(px3.get() == p2); assert(px3.use_count() == 2); } } } // namespace n_swap namespace n_comparison { struct X { int dummy; }; struct Y { int dummy2; }; struct Z : public X , public virtual Y { }; void test() { { shared_ptr px; assert(px == px); assert(!(px != px)); assert(!(px < px)); shared_ptr px2; assert(px.get() == px2.get()); assert(px == px2); assert(!(px != px2)); assert(!(px < px2 && px2 < px)); } { shared_ptr px; shared_ptr px2(px); assert(px2 == px2); assert(!(px2 != px2)); assert(!(px2 < px2)); assert(px.get() == px2.get()); assert(px == px2); assert(!(px != px2)); assert(!(px < px2 && px2 < px)); } { shared_ptr px; shared_ptr px2(new X); assert(px2 == px2); assert(!(px2 != px2)); assert(!(px2 < px2)); assert(px.get() != px2.get()); assert(px != px2); assert(!(px == px2)); assert(px < px2 || px2 < px); assert(!(px < px2 && px2 < px)); } { shared_ptr px(new X); shared_ptr px2(new X); assert(px.get() != px2.get()); assert(px != px2); assert(!(px == px2)); assert(px < px2 || px2 < px); assert(!(px < px2 && px2 < px)); } { shared_ptr px(new X); shared_ptr px2(px); assert(px2 == px2); assert(!(px2 != px2)); assert(!(px2 < px2)); assert(px.get() == px2.get()); assert(px == px2); assert(!(px != px2)); assert(!(px < px2 || px2 < px)); } { shared_ptr px(new X); shared_ptr py(new Y); shared_ptr pz(new Z); assert(px.get() != pz.get()); assert(px != pz); assert(!(px == pz)); assert(py.get() != pz.get()); assert(py != pz); assert(!(py == pz)); assert(px < py || py < px); assert(px < pz || pz < px); assert(py < pz || pz < py); assert(!(px < py && py < px)); assert(!(px < pz && pz < px)); assert(!(py < pz && pz < py)); shared_ptr pvx(px); assert(pvx == pvx); assert(!(pvx != pvx)); assert(!(pvx < pvx)); shared_ptr pvy(py); shared_ptr pvz(pz); assert(pvx < pvy || pvy < pvx); assert(pvx < pvz || pvz < pvx); assert(pvy < pvz || pvz < pvy); assert(!(pvx < pvy && pvy < pvx)); assert(!(pvx < pvz && pvz < pvx)); assert(!(pvy < pvz && pvz < pvy)); } { shared_ptr pz(new Z); shared_ptr px(pz); assert(px == px); assert(!(px != px)); assert(!(px < px)); shared_ptr py(pz); assert(px.get() == pz.get()); assert(px == pz); assert(!(px != pz)); assert(py.get() == pz.get()); assert(py == pz); assert(!(py != pz)); assert(!(px < py || py < px)); assert(!(px < pz || pz < px)); assert(!(py < pz || pz < py)); shared_ptr pvx(px); shared_ptr pvy(py); shared_ptr pvz(pz); // pvx and pvy aren't equal... assert(pvx.get() != pvy.get()); assert(pvx != pvy); assert(!(pvx == pvy)); // ... but they share ownership ... assert(!(pvx < pvy || pvy < pvx)); // ... with pvz assert(!(pvx < pvz || pvz < pvx)); assert(!(pvy < pvz || pvz < pvy)); } } } // namespace n_comparison namespace n_static_cast { struct X { }; struct Y : public X { }; void test() { { shared_ptr pv; shared_ptr pi = static_pointer_cast(pv); assert(pi.get() == 0); shared_ptr px = static_pointer_cast(pv); assert(px.get() == 0); } { shared_ptr pi(new int); shared_ptr pv(pi); shared_ptr pi2 = static_pointer_cast(pv); assert(pi.get() == pi2.get()); assert(!(pi < pi2 || pi2 < pi)); assert(pi.use_count() == 3); assert(pv.use_count() == 3); assert(pi2.use_count() == 3); } { shared_ptr px(new X); shared_ptr pv(px); shared_ptr px2 = static_pointer_cast(pv); assert(px.get() == px2.get()); assert(!(px < px2 || px2 < px)); assert(px.use_count() == 3); assert(pv.use_count() == 3); assert(px2.use_count() == 3); } { shared_ptr px(new Y); shared_ptr py = static_pointer_cast(px); assert(px.get() == py.get()); assert(px.use_count() == 2); assert(py.use_count() == 2); shared_ptr px2(py); assert(!(px < px2 || px2 < px)); } } } // namespace n_static_cast namespace n_const_cast { struct X; void test() { { shared_ptr px; shared_ptr px2 = const_pointer_cast(px); assert(px2.get() == 0); } { shared_ptr px; shared_ptr px2 = const_pointer_cast(px); assert(px2.get() == 0); } { shared_ptr px; shared_ptr px2 = const_pointer_cast(px); assert(px2.get() == 0); } { shared_ptr px(new int); shared_ptr px2 = const_pointer_cast(px); assert(px.get() == px2.get()); assert(!(px < px2 || px2 < px)); assert(px.use_count() == 2); assert(px2.use_count() == 2); } { shared_ptr px(new int); shared_ptr px2 = const_pointer_cast(px); assert(px.get() == px2.get()); assert(!(px < px2 || px2 < px)); assert(px.use_count() == 2); assert(px2.use_count() == 2); } } } // namespace n_const_cast namespace n_dynamic_cast { struct V { virtual ~V() {} }; struct W : public V { }; void test() { { shared_ptr pv; shared_ptr pw = dynamic_pointer_cast(pv); assert(pw.get() == 0); } { shared_ptr pv(static_cast(0)); shared_ptr pw = dynamic_pointer_cast(pv); assert(pw.get() == 0); shared_ptr pv2(pw); assert(pv < pv2 || pv2 < pv); } { shared_ptr pv(static_cast(0)); shared_ptr pw = dynamic_pointer_cast(pv); assert(pw.get() == 0); shared_ptr pv2(pw); assert(pv < pv2 || pv2 < pv); } { shared_ptr pv(new V); shared_ptr pw = dynamic_pointer_cast(pv); assert(pw.get() == 0); shared_ptr pv2(pw); assert(pv < pv2 || pv2 < pv); } { shared_ptr pv(new W); shared_ptr pw = dynamic_pointer_cast(pv); assert(pw.get() == pv.get()); assert(pv.use_count() == 2); assert(pw.use_count() == 2); shared_ptr pv2(pw); assert(!(pv < pv2 || pv2 < pv)); } } } // namespace n_dynamic_cast namespace n_map { struct X { }; void test() { std::vector< shared_ptr > vi; { shared_ptr pi1(new int); shared_ptr pi2(new int); 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< shared_ptr > vx; { shared_ptr px1(new X); shared_ptr px2(new X); 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< shared_ptr, long > m; { for(std::vector< shared_ptr >::iterator i = vi.begin(); i != vi.end(); ++i) { ++m[*i]; } } { for(std::vector< shared_ptr >::iterator i = vx.begin(); i != vx.end(); ++i) { ++m[*i]; } } { for(std::map< shared_ptr, long >::iterator i = m.begin(); i != m.end(); ++i) { assert(i->first.use_count() == i->second + 1); } } } } // namespace n_map namespace n_transitive { struct X { X(): next() {} shared_ptr next; }; void test() { shared_ptr p(new X); p->next = shared_ptr(new X); assert(!p->next->next); p = p->next; assert(!p->next); } } // namespace n_transitive #if 0 namespace n_report_1 { class foo { public: foo(): m_self(this) { } void suicide() { m_self.reset(); } private: shared_ptr m_self; }; void test() { foo * foo_ptr = new foo; foo_ptr->suicide(); } } // namespace n_report_1 #endif // 0 // Test case by Per Kristensen namespace n_report_2 { class foo { public: void setWeak(shared_ptr s) { w = s; } private: weak_ptr w; }; class deleter { public: deleter(): lock(0) { } ~deleter() { assert(lock == 0); } void operator() (foo * p) { ++lock; delete p; --lock; } private: int lock; }; void test() { shared_ptr s(new foo, deleter()); s->setWeak(s); s.reset(); } } // namespace n_report_2 namespace n_spt_incomplete { class file; shared_ptr fopen(char const * name, char const * mode); void fread(shared_ptr f, void * data, long size); int file_instances = 0; void test() { assert(file_instances == 0); { shared_ptr pf = fopen("name", "mode"); assert(file_instances == 1); fread(pf, 0, 17041); } assert(file_instances == 0); } } // namespace n_spt_incomplete namespace n_spt_pimpl { class file { private: class impl; 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() { assert(file_instances == 0); { file f("name", "mode"); assert(file_instances == 1); f.read(0, 152); file f2(f); assert(file_instances == 1); f2.read(0, 894); assert(f.total_size() == 152+894); { file f3("name2", "mode2"); assert(file_instances == 2); } assert(file_instances == 1); } assert(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() {} }; shared_ptr createX(); int X_instances = 0; void test() { assert(X_instances == 0); { shared_ptr px = createX(); assert(X_instances == 1); px->f(18); px->f(152); assert(px->g() == 170); } assert(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 shared_ptr create() { shared_ptr px(new X, X::deleter()); return px; } }; void test() { assert(X_instances == 0); { shared_ptr px = X::create(); assert(X_instances == 1); } assert(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() { assert(X_instances == 0); #if 0 { shared_ptr px(new X[4], checked_array_deleter()); assert(X_instances == 4); } #endif // 0 assert(X_instances == 0); } } // namespace n_spt_array namespace n_spt_static { class X { public: X() { } private: void operator delete(void *) { throw "n_spt_static::X::operator delete() called."; } }; struct null_deleter { void operator()(void const *) const { } }; static X x; void test() { shared_ptr px(&x, null_deleter()); } } // namespace n_spt_static namespace n_spt_intrusive { int X_instances = 0; struct X { long count; X(): count(0) { ++X_instances; } ~X() { --X_instances; } }; void intrusive_ptr_add_ref(X * p) { ++p->count; } void intrusive_ptr_release(X * p) { if(--p->count == 0) delete p; } template< class T > struct intrusive_deleter { void operator()(T * p) { if(p != 0) intrusive_ptr_release(p); } }; shared_ptr make_shared_from_intrusive(X * p) { if(p != 0) intrusive_ptr_add_ref(p); shared_ptr px(p, intrusive_deleter()); return px; } void test() { assert(X_instances == 0); { X * p = new X; assert(X_instances == 1); assert(p->count == 0); shared_ptr px = make_shared_from_intrusive(p); assert(px.get() == p); assert(p->count == 1); shared_ptr px2(px); assert(px2.get() == p); assert(p->count == 1); } assert(X_instances == 0); } } // namespace n_spt_intrusive namespace n_spt_another_sp { template< class T > class another_ptr : private shared_ptr { private: typedef shared_ptr base_type; public: explicit another_ptr(T * p = 0): base_type(p) { } void reset() { base_type::reset(); } T * get() const { return base_type::get(); } }; class event_handler { public: virtual ~event_handler() {} virtual void begin() = 0; virtual void handle(int event) = 0; virtual void end() = 0; }; int begin_called = 0; int handle_called = 0; int end_called = 0; class event_handler_impl : public event_handler { public: virtual void begin() { ++begin_called; } virtual void handle(int event) { handle_called = event; } virtual void end() { ++end_called; } }; another_ptr get_event_handler() { another_ptr p(new event_handler_impl); return p; } shared_ptr current_handler; void install_event_handler(shared_ptr p) { p->begin(); current_handler = p; } void handle_event(int event) { current_handler->handle(event); } void remove_event_handler() { current_handler->end(); current_handler.reset(); } template< class P > class smart_pointer_deleter { private: P p_; public: smart_pointer_deleter(P const & p): p_(p) { } void operator()(void const *) { p_.reset(); } }; void test() { another_ptr p = get_event_handler(); shared_ptr q(p.get(), smart_pointer_deleter< another_ptr >(p)); p.reset(); assert(begin_called == 0); install_event_handler(q); assert(begin_called == 1); assert(handle_called == 0); handle_event(17041); assert(handle_called == 17041); assert(end_called == 0); remove_event_handler(); assert(end_called == 1); } } // namespace n_spt_another_sp #if 0 namespace n_spt_shared_from_this { class X { public: virtual void f() = 0; protected: ~X() {} }; class Y { public: virtual shared_ptr getX() = 0; protected: ~Y() {} }; class impl : public X, public Y { private: weak_ptr weak_this; impl(impl const &); impl & operator=(impl const &); impl() {} public: static shared_ptr create() { shared_ptr pi(new impl); pi->weak_this = pi; return pi; } virtual void f() {} virtual shared_ptr getX() { shared_ptr px = weak_this.lock(); return px; } }; void test() { shared_ptr py = impl::create(); assert(py.get() != 0); assert(py.use_count() == 1); shared_ptr px = py->getX(); assert(px.get() != 0); assert(py.use_count() == 2); shared_ptr py2 = dynamic_pointer_cast(px); assert(py.get() == py2.get()); assert(!(py < py2 || py2 < py)); assert(py.use_count() == 3); } } // namespace n_spt_shared_from_this #endif // 0 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_const_cast::test(); n_dynamic_cast::test(); n_map::test(); n_transitive::test(); #if 0 n_report_1::test(); #endif // 0 n_report_2::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_wrap::test(); return 0; } namespace n_spt_incomplete { class file { public: file(): fread_called(false) { ++file_instances; } ~file() { assert(fread_called); --file_instances; } bool fread_called; }; shared_ptr fopen(char const *, char const *) { shared_ptr pf(new file); return pf; } void fread(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_; } }; shared_ptr createX() { shared_ptr px(new X_impl); return px; } } // namespace n_spt_abstract