[C++-sig] Re: Inheritance with B/P

David Abrahams dave at boost-consulting.com
Tue Feb 11 01:54:22 CET 2003


Bruce Lowery <bruce_lowery at yahoo.com> writes:

> --- David Abrahams <dave at boost-consulting.com> wrote:
>> Bruce Lowery <bruce_lowery at yahoo.com> writes:
>> 
>> >> > Is there a better way to do this?
>> >> 
>> >> Does 
>> >> 
>> >>      implicitly_convertible<
>> >>          std::auto_ptr<Derived>
>> >>        , std::auto_ptr<Base>
>> >>      >();
>> >> 
>> >> , placed in your module init function, help?
>> >> 
>> >
>> > Although this would be an improvement over what I'm doing now, it still
>> > requires a 'implicitly_convertible' for each derived class, doesn't it?  
>> 
>> Yep.  I could try to create auto_ptr conversions automatically, but
>> the system is designed to work on all kinds of smart pointer and
>> generalizing the mechanism would be very difficult.  Maybe I shouldn't
>> worry about that.
>> 
>
>
> Perhaps a better way is to avoid the use of auto_ptr altogether.
> Recall that I needed to use it because I'm wrapping some methods
> that take ownership of a passed-in pointer.  Is it possible to
> invent a new policy to represent this semantic information and that
> would cause b/p to set 'thisown=0' on the python object wrapping the
> pointer?

I don't think it's possible without replicating the same work as I
detailed above.  There is basically only one way a pointer ever gets
wrapped "raw", with no expectation that the referent's lifetime is
tied to that of a Python object, and that's when you use
reference_existing_object.

The _only_ way a Python object holds a pointer whose ownership it can
"give away" to your wrapped function, is when it holds that pointer by
auto_ptr.

Now, it's easy enough to find out that there is a Base* in the object,
even when the object holds an auto_ptr<Derived>.  The problem is
getting the object to release ownership.  To do that, I have to
somehow talk to the auto_ptr<Derived> object, i.e. to call its
release() function, or to copy it into an auto_ptr<Base> object.

I guess one possibility would be to hold owned pointers not by
auto_ptr, but by something like this:

    struct owner_base
    {
       owner_base(void* p) : m_p(p) {}
       void* release() { void* p = m_p; m_p = 0; return p; }
       void* get() const { return m_p; }
     private
       void* m_p;
    };

    template <class T>
    struct owner : owner_base
    {
       owner(T* p) : owner_base(p) {}
       ~owner() { delete get(); }
       T* get() const { return static_cast<T*>(this->owner_base::get()); }
     private:
       void operator=(owner const&);
       owner(owner const&);
    };

Then once you know there's a Base* and an owner_base in the object you
can ask the owner_base to release().  Whew, it's complicated, though.

Further, call policies don't currently control how conversions occur;
the stuff that handles ownership is currently just working on Python
objects in precall() and postcall() routines (look it up; you'll see
what I mean). This looks like an achievable but difficult
modification; not one I can see having time to do in the near future
as long as I have other paying work I can do ;-)

It looks like it would be easier to get the auto_ptr thing working,
though I realize that's not an ideal solution for you.

Sorry,
Dave

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com





More information about the Cplusplus-sig mailing list