
After experiencing some troubles with boost::python and enable_shared_from_this (as already reported in the past by someone to Peter Dimov), I started looking at the new (not documented) class enable_shared_from_this2. I made two changes in init_weak_once and now it seems to support shared_from_this in constructors and shared pointers "reinitialization". The original code (from boost 1.40): void init_weak_once() const { if( weak_this_._empty() ) { shared_this_.reset(static_cast< T* >( 0 ), detail::esft2_deleter_wrapper()); weak_this_ = shared_this_; } } The "patched" code: void init_weak_once() const { // Reinitialization support if( weak_this_.expired() ) { // shared_from_this in costructors support shared_this_.reset(static_cast <T*>(const_cast<enable_shared_from_this2>(this)), detail::esft2_deleter_wrapper()); weak_this_ = shared_this_; } } I know that the static_cast/const_cast is "problematic" on VC6 (and maybe other compilers) but it could be solved using an offset from enable_shared_from_this2 * to T *. I've attached a testcase that shows the problems with the current enable_shared_from_this2 implementation (with the proposed patch it works). Any feedback about this? struct null_deleter { template <typename T> inline void operator()(T *p) const { } }; class EnableThisPtrTester : public boost::enable_shared_from_this2<EnableThisPtrTester> { public: EnableThisPtrTester() { } EnableThisPtrTester(shared_ptr<EnableThisPtrTester> &ptr) { ptr = shared_from_this(); BOOST_CHECK(ptr); } }; BOOST_AUTO_TEST_CASE(test_enable_this_ptr) { { shared_ptr<EnableThisPtrTester> ptr1; shared_ptr<EnableThisPtrTester> ptr2(new EnableThisPtrTester(ptr1)); BOOST_CHECK(ptr1 == ptr2); BOOST_CHECK(ptr1.use_count() == ptr2.use_count()); BOOST_CHECK(ptr1->shared_from_this() == ptr1); BOOST_CHECK(ptr1->shared_from_this().use_count() == ptr1.use_count()); shared_ptr<EnableThisPtrTester> ptr3 = ptr2->shared_from_this(); BOOST_CHECK(ptr2 == ptr3); BOOST_CHECK(ptr2.use_count() == ptr3.use_count()); BOOST_CHECK(ptr1->shared_from_this().use_count() == ptr1.use_count()); } { shared_ptr<EnableThisPtrTester> ptr1; EnableThisPtrTester tester(ptr1); shared_ptr<EnableThisPtrTester> ptr2 = tester.shared_from_this(); BOOST_CHECK(ptr1 == ptr2); BOOST_CHECK(ptr1.use_count() == ptr2.use_count()); ptr1.reset(); ptr2.reset(); } { EnableThisPtrTester tester; { shared_ptr<EnableThisPtrTester> ptr1 = tester.shared_from_this(); shared_ptr<EnableThisPtrTester> ptr2 = tester.shared_from_this(); BOOST_CHECK(ptr1 == ptr2); BOOST_CHECK(ptr1.use_count() == ptr2.use_count()); shared_ptr<EnableThisPtrTester> ptr3(&tester, null_deleter()); BOOST_CHECK(ptr1 == ptr3); BOOST_CHECK(ptr1.use_count() == ptr3.use_count()); shared_ptr<EnableThisPtrTester> ptr4 = tester.shared_from_this(); BOOST_CHECK(ptr4 == ptr1); BOOST_CHECK(ptr4 == ptr3); BOOST_CHECK(ptr1.use_count() == ptr4.use_count()); BOOST_CHECK(ptr3.use_count() == ptr4.use_count()); } BOOST_CHECK(tester.shared_from_this()); } }