
Oleg Fedtchenko wrote:
shared_ptr<Tree> Parse( shared_ptr<DocActiveX> ptrOwner) { shared_ptr<Tree> ptrMember( &m_Tree, ptrOwner); return ptrMember; }
And corresponding ctor that passes over a deletable pointer to an owner (ptrOwner) of a class member (p):
template <class Y, class Z> shared_ptr( Y * p, shared_ptr<Z>& ptrOwner) : px(p), pn(ptrOwner.pn) {...}
But it's good if this class will never be used as an object (nondynamic) data-member inside another owner.
Also it's good when we create shared_ptr using ptrOwner outside a class because we can pass in a shared_ptr of any owner.
Larry Evans wrote:
This is unclear to me. Could you provide an example?
The Parse above is a function-member of a class DocActiveX (I forgot to specify this). Therefore shared_ptr ptrOwner has DocActiveX as its parameter. But if an object of DocActiveX is a member of another class like this: class Superclass { public: DocActiveX doc; }; then parameter ptrOwner in the function DocActiveX::Parse (see above) must be of type shared_ptr<Superclass>: shared_ptr<Tree> Parse( shared_ptr<Superclass> ptrOwner) { shared_ptr<Tree> ptrMember( &m_Tree, ptrOwner); return ptrMember; } because ptrOwner is what ought to be deleted when all shared_ptr's to m_Tree are released. To resolve this issue the function Parse accepting owner of any type can be written in a templated form: template <class Z> shared_ptr<Tree> Parse( shared_ptr<Z> ptrOwner) { shared_ptr<Tree> ptrMember( &m_Tree, ptrOwner); return ptrMember; } But such a templated function has its own drawbacks, and there is an alternative to it. Please, read this email http://lists.boost.org/MailArchives/boost/msg73234.php on that. The issue about the owner type doesn't raise when shared_ptr to a member is created outside a class containing that member (e.g. inside an actual owner): Tree* Parse() { Tree* ptrMember = &m_Tree; return ptrMember; } void SomeClass::SomeFunc() { ... shared_ptr<Superclass> pSuper(new Superclass); ... shared_ptr<Tree> ptrTreeHere( pSuper->doc.Parse(), pSuper); ptrTreeHere->SomeFunc(); ... } But we can easily by mistake put some wrong owner instead of *pSuper*: shared_ptr<Tree> ptrTreeHere( pSuper->doc.Parse(), this); // it's wrong because *this* cannot be deleted on destructing ptrTreeHere // // only dynamically allocated owner can be passed in the Parse // and *this* can point to an object data-member (nondeletable using // op *delete*) of some other class And the next is clearer, isn't it? And Parse below can have the only instance (as it's not templated). member_ptr<Tree> Parse() { member_ptr<Tree> ptrMember( &m_Tree); return ptrMember; // deletable owner of m_Tree gets into ptrMember // from m_Tree inside its CTOR } void Superclass::SomeFunc() { ... doc.Parse()->SomeFunc(); ... } The proposed smart pointer member_ptr is described at http://boostoleg.narod.ru/member_ptr.html Oleg Fedtchenko recommended thread entry http://lists.boost.org/MailArchives/boost/msg73168.php