
Michael: This is exactly what aliasing is for. I don't use boost::shared_ptr, but just looking at it I can't find any mention of aliasing. Maybe the library authors will reply to you. Meanwhile, I believe that aliasing is much more general than sharing accesses to members. The usual examples are about pointer to a temporary buffer (e.g. for I/O) and various pointers pointing inside the buffer, or a pointer to buffers in an I/O vec chain, or iterator/node pointers inside a list, all of which must live at least as long as the buffer / chain / list to which they're members of. I know that the shared pointer at my firm supports aliasing and that is a very useful and widely used feature. I'm surprised it wouldn't be supported by boost. Cheers, -- Herve On Feb 28, 2007, at 12:22 AM, Michael Anderson wrote:
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
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/ listinfo.cgi/boost