views:

127

answers:

2

I'm having some trouble seeing what the best way to wrap a series of classes with Boost.Python while avoiding messy inheritance problems. Say I have the classes A, B, and C with the following structure:

struct A {
    virtual void foo();
    virtual void bar();
    virtual void baz();
};

struct B : public A {
    virtual void quux();
};

struct C : public A {
    virtual void foobar();
};

I want to wrap all classes A, B, and C such that they are extendable from Python. The normal method for accomplishing this would be along the lines of:

struct A_Wrapper : public A, boost::python::wrapper<A> {
    //dispatch logic for virtual functions
};

Now for classes B and C which extend from A I would like to be able to inherit and share the wrapping implementation for A. So I'd like to be able to do something along the lines of:

struct B_Wrapper : public B, public A_Wrapper, public boost::python::wrapper<B> {
    //dispatch logic specific for B
};

struct C_Wrapper : public C, public A_Wrapper, public boost::python::wrapper<C> {
    //dispatch logic specific for C
}

However, it seems like that would introduce all manner of nastiness with the double inheritance of the boost wrapper base and the double inheritance of A in the B_Wrapper and C_Wrapper objects. Is there a common way that this instance is solved that I'm missing?

thanks.

+1  A: 

One approach is to derive virtually:

struct B : virtual public A, ... { };
struct C : virtual public A, ... { };
struct A_Wrapper : virtual public A, ... { };

See the relevant C++ FAQ Lite items for notes and what this implies.

wilhelmtell
Thanks for your response.What about in the case where I can't necessarily modify the inheritance relationships to take advantage of virtual inheritance? This solution had occurred to me also, but it isn't super-attractive and is overly intrusive. Surely this is a fairly common operation, i.e. wrapping a type hierarchy where multiple non-leaf points in the hierarchy may be extended through Python, but I have been unable to find any discussion of it.
+1  A: 

I had exactly the same problem, and I simply didn't inherited B_Wrapper from A_Wrapper (copy and paste was sufficient for my needs). I think it is possible to share the common implementation in a helper class:

template<class ADERIVED>
struct A_Implem: public ADERIVED, public wrapper<ADERIVED>
{
    // dispatch logic
};

And then:

struct A_Wrapper: public A_Implem<A>
{
// ...
};


struct B_Wrapper: public A_Implem<B>
{
// ...
};
rafak
Yes, this is actually the solution I have at the moment. It's workable but just seems rather clumsy to me. I was hoping that there was something I was just missing. But perhaps this is the only non-intrusive option.