diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index afdb42b..c5178c7 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -40,7 +40,7 @@ namespace boost // The standard library that comes with Borland C++ 5.5.1 // defines std::exception and its members as having C calling -// convention (-pc). When the definition of use_count_is_zero +// convention (-pc). When the definition of bad_weak_ptr // is compiled with -ps, the compiler issues an error. // Hence, the temporary #pragma option -pc below. The version // check is deliberately conservative. @@ -49,13 +49,13 @@ namespace boost # pragma option push -pc #endif -class use_count_is_zero: public std::exception +class bad_weak_ptr: public std::exception { public: virtual char const * what() const throw() { - return "boost::use_count_is_zero"; + return "boost::bad_weak_ptr"; } }; @@ -63,6 +63,9 @@ public: # pragma option pop #endif +namespace detail +{ + class counted_base { private: @@ -109,50 +112,36 @@ public: void add_ref() { -#ifdef BOOST_HAS_THREADS +#if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif - if(use_count_ == 0 && weak_count_ != 0) boost::throw_exception(boost::use_count_is_zero()); + if(use_count_ == 0 && weak_count_ != 0) boost::throw_exception(boost::bad_weak_ptr()); ++use_count_; ++weak_count_; } void release() // nothrow { - long new_use_count; - long new_weak_count = 0; - { -#ifdef BOOST_HAS_THREADS +#if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif - new_use_count = --use_count_; + long new_use_count = --use_count_; if(new_use_count != 0) { - new_weak_count = --weak_count_; + --weak_count_; + return; } } - if(new_use_count == 0) - { - dispose(); - -#ifdef BOOST_HAS_THREADS - mutex_type::scoped_lock lock(mtx_); -#endif - new_weak_count = --weak_count_; - } - - if(new_weak_count == 0) - { - destruct(); - } + dispose(); + weak_release(); } void weak_add_ref() // nothrow { -#ifdef BOOST_HAS_THREADS +#if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif ++weak_count_; @@ -163,7 +152,7 @@ public: long new_weak_count; { -#ifdef BOOST_HAS_THREADS +#if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif new_weak_count = --weak_count_; @@ -177,7 +166,7 @@ public: long use_count() const // nothrow { -#ifdef BOOST_HAS_THREADS +#if defined(BOOST_HAS_THREADS) mutex_type::scoped_lock lock(mtx_); #endif return use_count_; @@ -193,29 +182,16 @@ private: long use_count_; long weak_count_; -#ifdef BOOST_HAS_THREADS +#if defined(BOOST_HAS_THREADS) mutable mutex_type mtx_; #endif }; -inline void intrusive_ptr_add_ref(counted_base * p) -{ - p->add_ref(); -} - -inline void intrusive_ptr_release(counted_base * p) -{ - p->release(); -} - -namespace detail -{ - // // Borland's Codeguard trips up over the -Vx- option here: // #ifdef __CODEGUARD__ -#pragma option push -Vx- +# pragma option push -Vx- #endif template class counted_base_impl: public counted_base @@ -273,16 +249,11 @@ private: public: - shared_count(): pi_(new counted_base(1, 1)) + shared_count(): pi_(0) // (new counted_base(1, 1)) { } - explicit shared_count(counted_base * pi): pi_(pi) // never throws - { - pi_->add_ref(); - } - - template shared_count(P p, D d, void const * = 0): pi_(0) + template shared_count(P p, D d): pi_(0) { #ifndef BOOST_NO_EXCEPTIONS @@ -309,11 +280,6 @@ public: #endif } - template shared_count(P, D, counted_base * pi): pi_(pi) - { - pi_->add_ref(); - } - #ifndef BOOST_NO_AUTO_PTR // auto_ptr is special cased to provide the strong guarantee @@ -328,21 +294,21 @@ public: ~shared_count() // nothrow { - pi_->release(); + if(pi_ != 0) pi_->release(); } shared_count(shared_count const & r): pi_(r.pi_) // nothrow { - pi_->add_ref(); + if(pi_ != 0) pi_->add_ref(); } - explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0 + explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 shared_count & operator= (shared_count const & r) // nothrow { counted_base * tmp = r.pi_; - tmp->add_ref(); - pi_->release(); + if(tmp != 0) tmp->add_ref(); + if(pi_ != 0) pi_->release(); pi_ = tmp; return *this; @@ -357,12 +323,12 @@ public: long use_count() const // nothrow { - return pi_->use_count(); + return pi_ != 0? pi_->use_count(): 42; // '42' is an example of 'unspecified' } bool unique() const // nothrow { - return pi_->use_count() == 1; + return use_count() == 1; } friend inline bool operator==(shared_count const & a, shared_count const & b) @@ -377,7 +343,7 @@ public: }; #ifdef __CODEGUARD__ -#pragma option pop +# pragma option pop #endif @@ -391,30 +357,30 @@ private: public: - weak_count(): pi_(new counted_base(0, 1)) // can throw + weak_count(): pi_(0) // nothrow // (new counted_base(0, 1)) // can throw { } weak_count(shared_count const & r): pi_(r.pi_) // nothrow { - pi_->weak_add_ref(); + if(pi_ != 0) pi_->weak_add_ref(); } weak_count(weak_count const & r): pi_(r.pi_) // nothrow { - pi_->weak_add_ref(); + if(pi_ != 0) pi_->weak_add_ref(); } ~weak_count() // nothrow { - pi_->weak_release(); + if(pi_ != 0) pi_->weak_release(); } weak_count & operator= (shared_count const & r) // nothrow { counted_base * tmp = r.pi_; - tmp->weak_add_ref(); - pi_->weak_release(); + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); pi_ = tmp; return *this; @@ -423,8 +389,8 @@ public: weak_count & operator= (weak_count const & r) // nothrow { counted_base * tmp = r.pi_; - tmp->weak_add_ref(); - pi_->weak_release(); + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); pi_ = tmp; return *this; @@ -439,7 +405,7 @@ public: long use_count() const // nothrow { - return pi_->use_count(); + return pi_ != 0? pi_->use_count(): 804; // '804' is an example of 'unspecified' } friend inline bool operator==(weak_count const & a, weak_count const & b) @@ -455,7 +421,7 @@ public: inline shared_count::shared_count(weak_count const & r): pi_(r.pi_) { - pi_->add_ref(); + if(pi_ != 0) pi_->add_ref(); } } // namespace detail diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp new file mode 100644 index 0000000..199725a --- /dev/null +++ b/include/boost/enable_shared_from_this.hpp @@ -0,0 +1,51 @@ +#ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED +#define BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED + +// +// enable_shared_from_this.hpp +// +// Copyright (c) 2002 Peter Dimov +// +// 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. +// +// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html +// + +#include +#include +#include + +namespace boost +{ + +template class enable_shared_from_this +{ +public: + + shared_ptr shared_from_this() + { + return shared_ptr(weak_this); + } + + shared_ptr shared_from_this() const + { + return shared_ptr(weak_this); + } + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + +private: + + template friend class shared_ptr; + +#endif + + weak_ptr weak_this; +}; + +} // namespace boost + +#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 11202f4..6357fff 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -76,8 +76,14 @@ template<> struct shared_ptr_traits // is destroyed or reset. // +#if defined(BOOST_SP_ENABLE_CONSTRUCTOR_HOOK) + +void shared_ptr_constructor_hook(void * p); + +#endif + template class weak_ptr; -template class intrusive_ptr; +template class enable_shared_from_this; template class shared_ptr { @@ -87,18 +93,36 @@ private: // typedef checked_deleter deleter; typedef shared_ptr this_type; + // enable_shared_from_this support + + template void sp_enable_shared_from_this(boost::enable_shared_from_this * q) + { + q->weak_this = *this; + } + + void sp_enable_shared_from_this(void *) + { + } + public: typedef T element_type; typedef T value_type; + typedef T * pointer; + typedef typename detail::shared_ptr_traits::reference reference; shared_ptr(): px(0), pn() { } template - explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter(), p) // Y must be complete + explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter()) // Y must be complete { + sp_enable_shared_from_this(p); + +#if defined(BOOST_SP_ENABLE_CONSTRUCTOR_HOOK) + shared_ptr_constructor_hook(p); +#endif } // @@ -109,6 +133,7 @@ public: template shared_ptr(Y * p, D d): px(p), pn(p, d) { + sp_enable_shared_from_this(p); } // generated copy constructor, assignment, destructor are fine @@ -123,11 +148,6 @@ public: { } - template - shared_ptr(intrusive_ptr const & r): px(r.get()), pn(r.get()) // never throws - { - } - template shared_ptr(shared_ptr const & r, detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) { @@ -154,8 +174,11 @@ public: #ifndef BOOST_NO_AUTO_PTR template - explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn(r) + explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn() { + Y * tmp = r.get(); + pn = detail::shared_count(r); + sp_enable_shared_from_this(tmp); } #endif @@ -199,7 +222,7 @@ public: this_type(p, d).swap(*this); } - typename detail::shared_ptr_traits::reference operator* () const // never throws + reference operator* () const // never throws { BOOST_ASSERT(px != 0); return *px; @@ -246,6 +269,11 @@ public: pn.swap(other.pn); } + bool less(this_type const & rhs) const // implementation detail, never throws + { + return pn < rhs.pn; + } + // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) @@ -287,7 +315,7 @@ template inline bool operator!=(shared_ptr const & a, shared_ptr template inline bool operator<(shared_ptr const & a, shared_ptr const & b) { - return std::less()(a.get(), b.get()); + return a.less(b); } template inline void swap(shared_ptr & a, shared_ptr & b) @@ -295,6 +323,18 @@ template inline void swap(shared_ptr & a, shared_ptr & b) a.swap(b); } +template shared_ptr static_pointer_cast(shared_ptr const & r) +{ + return shared_ptr(r, detail::static_cast_tag()); +} + +template shared_ptr dynamic_pointer_cast(shared_ptr const & r) +{ + return shared_ptr(r, detail::dynamic_cast_tag()); +} + +// shared_*_cast names are deprecated. Use *_pointer_cast instead. + template shared_ptr shared_static_cast(shared_ptr const & r) { return shared_ptr(r, detail::static_cast_tag()); @@ -323,28 +363,6 @@ template inline T * get_pointer(shared_ptr const & p) return p.get(); } -// shared_from_this() creates a shared_ptr from a raw pointer (usually 'this') - -namespace detail -{ - -inline void sp_assert_counted_base(boost::counted_base const *) -{ -} - -template inline T * sp_remove_const(T const * p) -{ - return const_cast(p); -} - -} // namespace detail - -template shared_ptr shared_from_this(T * p) -{ - detail::sp_assert_counted_base(p); - return shared_ptr(detail::sp_remove_const(p)); -} - } // namespace boost #ifdef BOOST_MSVC diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index e17a9f7..b65309e 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -76,11 +76,6 @@ public: this_type().swap(*this); } - T * get() const // never throws; deprecated, removal pending, don't use - { - return pn.use_count() == 0? 0: px; - } - long use_count() const // never throws { return pn.use_count(); @@ -119,27 +114,6 @@ private: }; // weak_ptr -template inline bool operator==(weak_ptr const & a, weak_ptr const & b) -{ - return a.get() == b.get(); -} - -template inline bool operator!=(weak_ptr const & a, weak_ptr const & b) -{ - return a.get() != b.get(); -} - -#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 - -// Resolve the ambiguity between our op!= and the one in rel_ops - -template inline bool operator!=(weak_ptr const & a, weak_ptr const & b) -{ - return a.get() != b.get(); -} - -#endif - template inline bool operator<(weak_ptr const & a, weak_ptr const & b) { return a.less(b); @@ -152,6 +126,8 @@ template void swap(weak_ptr & a, weak_ptr & b) template shared_ptr make_shared(weak_ptr const & r) // never throws { +#if defined(BOOST_HAS_THREADS) + // optimization: avoid throw overhead if(r.use_count() == 0) { @@ -162,15 +138,20 @@ template shared_ptr make_shared(weak_ptr const & r) // never thro { return shared_ptr(r); } - catch(use_count_is_zero const &) + catch(bad_weak_ptr const &) { + // Q: how can we get here? + // A: another thread may have invalidated r after the use_count test above. return shared_ptr(); } -} -// Note: there is no get_pointer overload for weak_ptr. -// This is intentional. Even get() will disappear in a -// future release; these accessors are too error-prone. +#else + + // optimization: avoid try/catch overhead when single threaded + return r.use_count() == 0? shared_ptr(): shared_ptr(r); + +#endif +} } // namespace boost diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 3b0ec5e..7ebb4d2 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -3,6 +3,7 @@ #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 // @@ -21,35 +22,73 @@ #include #include -#include +#include +#include -bool boost_error(char const *, char const *, char const *, long) +// + +namespace n_element_type +{ + +void f(int &) { - return true; } -namespace +void test() { - int cnt = 0; + 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() { - ++cnt; - std::cout << "X(" << this << ")::X()\n"; + ++instances; } - ~X() // virtual destructor deliberately omitted + ~X() { - --cnt; - std::cout << "X(" << this << ")::~X()\n"; - } - - virtual int id() const - { - return 1; + --instances; } private: @@ -58,23 +97,20 @@ private: X & operator= (X const &); }; -struct Y: public X +long X::instances = 0; + +struct Y: public A, public X { + static long instances; + Y() { - ++cnt; - std::cout << "Y(" << this << ")::Y()\n"; + ++instances; } ~Y() { - --cnt; - std::cout << "Y(" << this << ")::~Y()\n"; - } - - virtual int id() const - { - return 2; + --instances; } private: @@ -83,118 +119,1519 @@ private: Y & operator= (Y const &); }; -int * get_object() +long Y::instances = 0; + +void pointer_constructor() { - ++cnt; - std::cout << "get_object()\n"; - return &cnt; + { + 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); } -void release_object(int * p) +int m = 0; + +void deleter(int * p) { - BOOST_TEST(p == &cnt); - --cnt; - std::cout << "release_object()\n"; + BOOST_TEST(p == 0); } -class Z: public virtual boost::counted_base +void deleter2(int * p) { -public: + BOOST_TEST(p == &m); + ++*p; +} - Z() +void deleter3(incomplete * p) +{ + BOOST_TEST(p == 0); +} + +// Borland C++ 5.5.1 fails on static_cast(0) + +incomplete * p0 = 0; + +void deleter_constructor() +{ { - ++cnt; - std::cout << "Z(" << this << ")::Z()\n"; + 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()); } - ~Z() { - --cnt; - std::cout << "Z(" << this << ")::~Z()\n"; + 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 shared_this() { - return boost::shared_from_this(this); + 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 shared_this() const { - return boost::shared_from_this(this); + 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? false: true); + BOOST_TEST(!pi2); + BOOST_TEST(pi2.get() == 0); + + boost::shared_ptr pi3(pi); + BOOST_TEST(pi3? false: true); + BOOST_TEST(!pi3); + BOOST_TEST(pi3.get() == 0); + + boost::shared_ptr 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? false: true); + BOOST_TEST(!pv2); + BOOST_TEST(pv2.get() == 0); + } + + { + boost::shared_ptr px; + + boost::shared_ptr px2(px); + BOOST_TEST(px2? false: true); + BOOST_TEST(!px2); + BOOST_TEST(px2.get() == 0); + + boost::shared_ptr 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? 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? 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? 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? 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? 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? 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? 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::shared_ptr 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::shared_ptr 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? 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? 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::shared_ptr 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? 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? 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 +{ + +void test() +{ +} + +} // namespace n_assignment + +namespace n_reset +{ + +void test() +{ +} + +} // 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::shared_ptr px2; + + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(px == px2); + BOOST_TEST(!(px != px2)); + } + + { + boost::shared_ptr px; + boost::shared_ptr px2(px); + + BOOST_TEST(px.get() == px2.get()); + BOOST_TEST(px == px2); + BOOST_TEST(!(px != px2)); + } + + { + boost::shared_ptr px; + 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::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::shared_ptr px(new X); + boost::shared_ptr px2(px); + + 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::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::shared_ptr pz(new Z); + boost::shared_ptr px(pz); + 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: - Z(Z const &); - Z & operator= (Z const &); -}; + boost::shared_ptr m_self; +}; -template void test_is_X(boost::shared_ptr const & p) +void test() { - BOOST_TEST(p->id() == 1); - BOOST_TEST((*p).id() == 1); -} + foo * foo_ptr = new foo; + foo_ptr->suicide(); +} -template void test_is_X(boost::weak_ptr const & p) -{ - BOOST_TEST(p.get() != 0); - BOOST_TEST(p.get()->id() == 1); -} +} // namespace n_report_1 -template void test_is_Y(boost::shared_ptr const & p) +// Test case by Per Kristensen +namespace n_report_2 { - BOOST_TEST(p->id() == 2); - BOOST_TEST((*p).id() == 2); -} - -template void test_is_Y(boost::weak_ptr const & p) -{ - BOOST_TEST(p.get() != 0); - BOOST_TEST(p.get()->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)); -} - -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); -} class foo { @@ -235,7 +1672,159 @@ private: int lock; }; -int main() +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; @@ -254,8 +1843,8 @@ int main() test_eq(p, q); } - shared_ptr p3 = shared_dynamic_cast(p); - shared_ptr p4 = shared_dynamic_cast(p2); + shared_ptr p3 = dynamic_pointer_cast(p); + shared_ptr p4 = dynamic_pointer_cast(p2); test_is_nonzero(p3); test_is_zero(p4); @@ -263,7 +1852,6 @@ int main() BOOST_TEST(p.use_count() == 2); BOOST_TEST(p2.use_count() == 1); BOOST_TEST(p3.use_count() == 2); - BOOST_TEST(p4.use_count() == 1); test_is_Y(p3); test_eq2(p, p3); @@ -274,7 +1862,10 @@ int main() test_is_nonzero(p5); test_eq2(p, p5); - std::cout << "--\n"; + weak_ptr wp1(p2); + + BOOST_TEST(!wp1.expired()); + BOOST_TEST(wp1.use_count() != 0); p.reset(); p2.reset(); @@ -286,32 +1877,27 @@ int main() test_is_zero(p3); test_is_zero(p4); - std::cout << "--\n"; - BOOST_TEST(p5.use_count() == 1); - weak_ptr wp1; - + BOOST_TEST(wp1.expired()); BOOST_TEST(wp1.use_count() == 0); - BOOST_TEST(wp1.get() == 0); try { shared_ptr sp1(wp1); BOOST_ERROR("shared_ptr sp1(wp1) failed to throw"); } - catch(boost::use_count_is_zero const &) + catch(boost::bad_weak_ptr const &) { } test_is_zero(boost::make_shared(wp1)); - weak_ptr wp2 = shared_static_cast(p5); + weak_ptr wp2 = static_pointer_cast(p5); BOOST_TEST(wp2.use_count() == 1); - BOOST_TEST(wp2.get() != 0); test_is_Y(wp2); - test_ne(wp1, wp2); + test_nonshared(wp1, wp2); // Scoped to not affect the subsequent use_count() tests. { @@ -319,41 +1905,25 @@ int main() test_is_nonzero(boost::make_shared(wp2)); } - weak_ptr wp3 = shared_dynamic_cast(boost::make_shared(wp2)); + weak_ptr wp3 = dynamic_pointer_cast(boost::make_shared(wp2)); BOOST_TEST(wp3.use_count() == 1); - BOOST_TEST(wp3.get() != 0); - test_eq2(wp2, wp3); + test_shared(wp2, wp3); weak_ptr wp4(wp3); BOOST_TEST(wp4.use_count() == 1); - BOOST_TEST(wp4.get() != 0); - test_eq(wp2, wp4); + test_shared(wp2, wp4); wp1 = p2; - BOOST_TEST(wp1.get() == 0); - - // Note the following test. Construction succeeds, - // but make_shared() returns a null shared_ptr with - // use_count() == 2. - - shared_ptr sp1(wp1); test_is_zero(boost::make_shared(wp1)); - BOOST_TEST(p2.use_count() == 2); - BOOST_TEST(sp1.use_count() == 2); - BOOST_TEST(wp1.use_count() == 2); - - // - wp1 = p4; wp1 = wp3; wp1 = wp2; BOOST_TEST(wp1.use_count() == 1); - BOOST_TEST(wp1.get() != 0); - test_eq(wp1, wp2); + test_shared(wp1, wp2); weak_ptr wp5; @@ -363,13 +1933,8 @@ int main() p5.reset(); BOOST_TEST(wp1.use_count() == 0); - BOOST_TEST(wp1.get() == 0); - BOOST_TEST(wp2.use_count() == 0); - BOOST_TEST(wp2.get() == 0); - BOOST_TEST(wp3.use_count() == 0); - BOOST_TEST(wp3.get() == 0); // Test operator< stability for std::set< weak_ptr<> > // Thanks to Joe Gottman for pointing this out @@ -381,38 +1946,497 @@ int main() // note that both get_object and release_object deal with int* shared_ptr p6(get_object(), release_object); } - - { - // test intrusive counting - - boost::shared_ptr pv(new Z); - boost::shared_ptr pz = boost::shared_static_cast(pv); - BOOST_TEST(pz.use_count() == pz->use_count()); - - // test shared_from_this - - boost::shared_ptr pz2 = pz->shared_this(); - - Z const & z = *pz2; - - boost::shared_ptr pz3 = z.shared_this(); - - BOOST_TEST(pz.use_count() == pz->use_count()); - BOOST_TEST(pz2.use_count() == pz2->use_count()); - BOOST_TEST(pz3.use_count() == pz3->use_count()); - BOOST_TEST(pz.use_count() == pz2.use_count()); - BOOST_TEST(pz.use_count() == pz3.use_count()); - } } 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); - // Test case by Per Kristensen { - boost::shared_ptr s(new foo, deleter()); - s->setWeak(s); - s.reset(); + 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 +{ +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 diff --git a/smart_ptr_test.cpp b/smart_ptr_test.cpp index 0d02f8b..0dad8e9 100644 --- a/smart_ptr_test.cpp +++ b/smart_ptr_test.cpp @@ -24,11 +24,6 @@ #include #include -bool boost_error(char const *, char const *, char const *, long) -{ - return true; // fail with assert() -} - class Incomplete; Incomplete * get_ptr( boost::shared_ptr& incomplete ) @@ -164,7 +159,6 @@ void test() cp.reset(); BOOST_TEST( cp2.use_count() == 2 ); BOOST_TEST( cp3.use_count() == 2 ); - BOOST_TEST( cp.use_count() == 1 ); cp.reset( new int ); *cp = 98765; BOOST_TEST( *cp == 98765 );