Chuck Messenger wrote: > > Suppose I have a cyclic dependency between A and B, which are > implemented with the pimpl idiom: > > #include <boost/shared_ptr.hpp> > #include <iostream> > > using namespace boost; > using namespace std; > > > struct B_impl; > > struct B { > shared_ptr<B_impl> pimpl_; > }; > > struct A_impl { > A_impl() { cout << "new A\n"; } > ~A_impl() { cout << "del A\n"; } > B b_; > }; > > struct A { > shared_ptr<A_impl> pimpl_; > B get_B() const { return pimpl_->b_; } > }; > > struct B_impl { > B_impl() { cout << "new B\n"; } > ~B_impl() { cout << "del B\n"; } > A a_; > }; > > A get_A(const B& b) { return b.pimpl_->a_; } > B get_B(const A& a) { return a.pimpl_->b_; } > > A construct_A() { > A a; > a.pimpl_.reset(new A_impl); // a refcount is 1 > B& b = a.pimpl_->b_; > b.pimpl_.reset(new B_impl); // b refcount is 1 > b.pimpl_->a_ = a; // a refcount is 2 > > return a; > } > > int main() { > { > A a = construct_A(); > } > // ex-a's refcount is still 1, so object doesn't die > } > > OK, so we want to solve the problem that A and B keep eachother alive. > > I don't see how a weak_ptr can be used, without breaking the whole way > I'm using A and B -- see get_A() and get_B().
[...] > In general, the abstraction is: you have a group of intra-referential > objects. When any of the group is constructed, they are all > constructed (so that the master count is temporarily > 1), and the > master count is > reset to 1. When the master count goes to 0, the group is destructed. > Hence, the group only remains alive as long as there are any external > references (and as long as the intra-group references remain static). In the situation you describe, A logically contains a B and B logically contains an A, so A and B aren't independent; they actually form an AB object. There is nothing to be gained from separating A and B as this doesn't eliminate a dependency. If A and B are optional (but still tightly coupled) parts of AB, the way I'd express this would probably be class AB { shared_ptr<A_impl> ai_; shared_ptr<B_impl> bi_; }; There are several ways to allow A_impl and B_impl to communicate: store an AB* pointer in each; pass a B_impl* to A_impl's methods that need it; keep a B_impl* or a weak_ptr<B_impl> in A_impl. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost