[C++-sig] Re: Boost.Python << & >> bug

Niall Douglas s_sourceforge at nedprod.com
Tue Aug 5 00:54:18 CEST 2003


On 3 Aug 2003 at 21:41, David Abrahams wrote:

> > Enclosed is the condensed example as requested. 
> 
> I assume you're referring to the enclosure in the other message?

Yeah my email program mangled it :(

> No this is a failure of your wrapping code.  Very simply,
> 
>     class_< FX::FXId >("FXId", no_init)
>         .def( other< FX::FXStream >() << self )
>         .def( other< FX::FXStream >() >> self )
> 
> Attempts to wrap two operator expressions which take an FXStream on
> the lhs and and FXId on the rhs.  But you don't have anything which
> would match those expressions.  Try it:
> 
>       // C++ code
>       FXStream x;
>       FXId y;
>       x << y;  // <== error
> 
>    friend FX::FXStream& operator<<(FX::FXStream& store,const FXId*
>    obj){return store;} friend FX::FXStream& operator>>(FX::FXStream&
>    store,FXId*& obj){return store;}
> 
> These declare operators which take an FXId* on the rhs:
> 
>       x << &y;

Yeah sorry about that - I had actually corrected this but forgot to 
recorrect it after another pyste cycle. However if you change the << 
overload in FXId to take a reference, it's the same problem. See 
attached.

> > Here because FXStream does not provide an overload for anything in
> > boost, it can't know it's really an unsigned char.
> 
> I don't know what that means either.

I meant that the compiler when faced with "a << b" where there is no 
direct overload for operator<<(a,b) must cast either a or b to 
something else to find an overload which can accept them.

I had assumed that boost.python provides template<class type> class 
wrapper { ... operator type() const; in order for the wrapper classes 
to cast down to their containing types so that the overloads provided 
by the code being wrapped can do their work. Or I suppose the wrapper 
could also inherit publicly from the wrapped type, but this would 
probably be less flexible.

> The problem you're seeing above may be due to a documentation bug on
> my part.  These operator wrapping facilities are only suitable for
> wrapping operators which work on rvalue arguments.   If you want to
> wrap your operators which work on non-const lvalues, you should write
> something more like:
> 
>        FXStream& (FXStream::*pmf)(FXchar&) = &FXStream::operator<<;
> 
>        ...
>           .def('__lshift__', pmf, return_self());

Ok, maybe if I explain what FXStream is: FXStream is like an 
iostream, or most accurately like QDataStream in Qt. You read and 
write variables from and to whatever backs it.

Therefore usage would be as follows:
FXStream s;
s << 5;
int foo;
s >> foo;
etc.

Can boost.python wrap this sort of usage?

> FWIW, Wrapping all these different operators for lots of different
> integer types is probably a waste of time because Python only has one
> int type.  Wrapping overloads on int and ushort, for example, is
> redundant.

Mmm. This is a problem I was going to tackle eventually. I can't use 
python's pickle for various reasons so I have to really interface 
python directly with this. And I most certainly need to write short 
ints for example.

Personally I'd envisage an ideal wrap as exposing as much as possible 
of the underlying interface. You'd almost certainly never use 85% of 
it as at a python level you'd keep pretty high-level. But 
occasionally you would need to get down & dirty, especially if for 
example the end-user didn't have access to the source.

Cheers,
Niall





More information about the Cplusplus-sig mailing list