[C++-sig] automatic downcasting with V2

Daniel Paull dlp at fractaltechnologies.com
Thu Dec 19 03:14:17 CET 2002


Hi Dave,

> 
> Well, I said I was going to do something about it, but then never
> actually did ;-)

Happens to be best of us :)

> 
>     struct A { virtual ~A(); };
>     struct B : A {};
>     struct C : B {};
> 
>     A* factory(int x) { return x == 0 ? new A : x == 1 ? new B : new
C; }
> 
> and
> 
>     #include <boost/python.hpp>
>     using namespace boost::python;
>     BOOST_PYTHON_MODULE(test)
>     {
>         def("factory", factory,
return_value_policy<manage_new_object>());
> 
>         class_<A>("A");
>         class_<B, bases<B> >("B");
>         // note, C not registered.
>     }
> 
> Now, clearly:
> 
>     >>> from test import *
>     >>> type(factory(0))
>     test.A
> 
> And, after my changes:
> 
>     >>> type(factory(1))
>     test.B
> 
> But, what's the result of:
> 
>     >>> type(factory(2))
> 

I think that this should fall back to returning "A" for simplicities
sake.

Alternatively, you could (optionally) make this an error condition.
That way you won't get any surprises if you're expecting all derived
objects to be convertible to Python.

What about cross module support - I assume (fingers crossed) it will
work automatically.  In the case above, "A" might be defined in one
module, but "B" is defined in a completely different module.  Would the
downcast still succeed?  (assuming both modules are imported in python)

> Furthermore, C++ inheritance hierarchies in general form a DAG.  If
> the actual type of the object isn't registered, there may not be any
> single most-derived type which is registered:
> 
>        A
>       / \
>      B   C  <= B and C are registered
>       \ /
>        D    <= D is not.
> 
> 
> So, what about cases like this one?

If you try to convert "D*" to python, you'd get a wrapped up "A*", just
like before.

The ambiguous case above sets a precedent for which downcasts can be
performed automatically.  I'll quote the online tutorial:

   Remember the Zen, Luke:

   "Explicit is better than implicit"
   "In the face of ambiguity, refuse the temptation to guess"

Given this, I think that a sensible set of caveats on the use of
automatic downcasts can be formed.

Looking back at the DAG and keeping with this philosophy, I think you
have to take the approach that and instance of "D" returned as an "A*"
must:

1) be converted to a wrapped "D*"
2) if (1) fails (eg, D is not registered), either return a wrapped "A*",
or,
3) signal an error.

This sort of scheme would be perfect for my needs.

Cheers,

Dan






More information about the Cplusplus-sig mailing list