diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 28a6286..bea9e11 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -313,6 +313,28 @@ 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/shared_ptr_test.cpp b/shared_ptr_test.cpp index f96dfc6..6113d26 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -112,6 +112,16 @@ public: std::cout << "Z(" << this << ")::~Z()\n"; } + boost::shared_ptr shared_this() + { + return boost::shared_from_this(this); + } + + boost::shared_ptr shared_this() const + { + return boost::shared_from_this(this); + } + private: Z(Z const &); @@ -331,9 +341,24 @@ int test_main(int, char * []) { // test intrusive counting - boost::shared_ptr pv(new Z); + + 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()); } }