
Howdy everyone. I have some code that uses pointers to member variables that I want to switch to using boost::shared_ptrs, some of the code looks like this. class Bar {}; class Foo { public: Bar bar; }; ... Foo * fooptr = new Foo; Bar * barptr = &Foo.bar; ... So to make this work with shared_ptrs I can do this: class Bar {} class Foo { public: Foo() : bar(new Bar) {} shared_ptr<Bar> bar; }; ... shared_ptr<Foo> fooptr(new Foo); shared_ptr<Bar> barptr = fooptr->bar; ... But this means I have to change each of the classes... which is a bit ugly. Also it has unlinked the lifetime of the Bar and Foo objects. So the solution I've come up with means that the Foo object only gets destroyed when both the barptr and the fooptr are destroyed. Unfortunately this requires additions to the shared_ptr class (the patch is below). The changes are _very_ similar to what is used for handling the pointer conversions and casts. Anyway I was wondering whether this is useful to anyone else, and whether there was any pitfalls I might have missed.... Thanks, Mike Anderson Example Usage : #include <iostream> #include "boost/shared_ptr.hpp" class Foo { public: double m; Foo() : m(1.0) { std::cout<<"creating Foo @ "<<this<<std::endl; } ~Foo() { std::cout<<"destroying Foo @ "<<this<<std::endl; } }; int main() { { boost::shared_ptr<Foo> fooptr( new Foo ); { boost::shared_ptr<double> mptr = boost::member_pointer(fooptr, &fooptr->m); } // Foo destroyed here... } { boost::shared_ptr<double> mptr; { boost::shared_ptr<Foo> fooptr( new Foo ); mptr = boost::member_pointer(fooptr, &fooptr->m); } // Foo destroyed here... even though mptr is a pointer to double. } } class Bar {}; class Foo { public: Bar bar; }; shared_ptr<Foo> fooptr(new Foo); shared_ptr<Bar> barptr = boost::member_ptr(fooptr, &fooptr->bar); Patch : (not from the recent trunk of boost....) --- shared_ptr.hpp +++ shared_ptr.hpp @@ -50,6 +50,7 @@ struct const_cast_tag {}; struct dynamic_cast_tag {}; struct polymorphic_cast_tag {}; +struct memberpointer_tag {}; template<class T> struct shared_ptr_traits { @@ -191,6 +192,12 @@ } } + template<class Y, class M> + shared_ptr(shared_ptr<Y> const & r, M* member_ptr, detail::memberpointer_tag) : px( member_ptr ), pn(r.pn) + { + + } + #ifndef BOOST_NO_AUTO_PTR template<class Y> @@ -410,6 +417,11 @@ return shared_static_cast<T>(r); } +template<class T, class M> shared_ptr<M> member_pointer( shared_ptr<T> const & t, M* m) +{ + return shared_ptr<M>(t,m, detail::memberpointer_tag() ); +} + // get_pointer() enables boost::mem_fn to recognize shared_ptr template<class T> inline T * get_pointer(shared_ptr<T> const & p) -- Michael Anderson Chief Technology Officer -- p. +61 8 8400 6496 [Adelaide, Australia] michael.anderson@risingsunresearch.com -- Rising Sun Research p. +61 8 8400 6494 - f. +61 8 8400 6401 www.risingsunresearch.com