Boost logo

Boost :

From: Oleg Fedtchenko (BoostOleg_at_[hidden])
Date: 2004-10-15 03:12:32


>> 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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk