#include #if defined(BOOST_MSVC) #pragma warning(disable: 4786) // identifier truncated in debug info #pragma warning(disable: 4710) // function not inlined #pragma warning(disable: 4711) // function selected for automatic inline expansion #pragma warning(disable: 4514) // unreferenced inline removed #pragma warning(disable: 4355) // 'this' : used in base member initializer list #if (BOOST_MSVC >= 1310) #pragma warning(disable: 4675) // resolved overload found with Koenig lookup #endif #endif #if defined(__GNUC__) && __GNUC__ > 4 # pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" #endif // // shared_ptr_basic_test.cpp // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #include #include #include 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 = p.lock(); 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)); } template void test_shared(boost::weak_ptr const & a, boost::weak_ptr const & b) { BOOST_TEST(!(a < b)); BOOST_TEST(!(b < a)); } template 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); } int main() { using namespace boost; { shared_ptr p(new Y); shared_ptr p2(new X); test_is_nonzero(p); test_is_nonzero(p2); test_is_Y(p); test_is_X(p2); test_ne(p, p2); { shared_ptr q(p); test_eq(p, q); } #if !defined( BOOST_NO_RTTI ) shared_ptr p3 = dynamic_pointer_cast(p); shared_ptr p4 = dynamic_pointer_cast(p2); test_is_nonzero(p3); test_is_zero(p4); BOOST_TEST(p.use_count() == 2); BOOST_TEST(p2.use_count() == 1); BOOST_TEST(p3.use_count() == 2); test_is_Y(p3); test_eq2(p, p3); test_ne2(p2, p4); #endif shared_ptr p5(p); test_is_nonzero(p5); test_eq2(p, p5); weak_ptr wp1(p2); BOOST_TEST(!wp1.expired()); BOOST_TEST(wp1.use_count() != 0); p.reset(); p2.reset(); #if !defined( BOOST_NO_RTTI ) p3.reset(); p4.reset(); #endif test_is_zero(p); test_is_zero(p2); #if !defined( BOOST_NO_RTTI ) test_is_zero(p3); test_is_zero(p4); #endif BOOST_TEST(p5.use_count() == 1); BOOST_TEST(wp1.expired()); BOOST_TEST(wp1.use_count() == 0); try { shared_ptr sp1(wp1); BOOST_ERROR("shared_ptr sp1(wp1) failed to throw"); } catch(boost::bad_weak_ptr const &) { } test_is_zero(wp1.lock()); weak_ptr wp2 = static_pointer_cast(p5); BOOST_TEST(wp2.use_count() == 1); test_is_Y(wp2); test_nonshared(wp1, wp2); // Scoped to not affect the subsequent use_count() tests. { shared_ptr sp2(wp2); test_is_nonzero(wp2.lock()); } #if !defined( BOOST_NO_RTTI ) weak_ptr wp3 = dynamic_pointer_cast(wp2.lock()); BOOST_TEST(wp3.use_count() == 1); test_shared(wp2, wp3); weak_ptr wp4(wp3); BOOST_TEST(wp4.use_count() == 1); test_shared(wp2, wp4); #endif wp1 = p2; test_is_zero(wp1.lock()); #if !defined( BOOST_NO_RTTI ) wp1 = p4; wp1 = wp3; #endif wp1 = wp2; BOOST_TEST(wp1.use_count() == 1); test_shared(wp1, wp2); weak_ptr wp5; bool b1 = wp1 < wp5; bool b2 = wp5 < wp1; p5.reset(); BOOST_TEST(wp1.use_count() == 0); BOOST_TEST(wp2.use_count() == 0); #if !defined( BOOST_NO_RTTI ) BOOST_TEST(wp3.use_count() == 0); #endif // Test operator< stability for std::set< weak_ptr<> > // Thanks to Joe Gottman for pointing this out BOOST_TEST(b1 == (wp1 < wp5)); BOOST_TEST(b2 == (wp5 < wp1)); { // note that both get_object and release_object deal with int* shared_ptr p6(get_object(), release_object); } } BOOST_TEST(cnt == 0); return boost::report_errors(); }