[C++-sig] pyplusplus bug related to boost::equality_comparable (and possibly other operators as well)

Jakub Zytka kubol at kormoran.net
Fri Sep 10 10:28:34 CEST 2010


On 09/09/10 20:08, Roman Yakovenko wrote:
> I don't think fixing py++ is the right approach.

>> I'm also considering a workaround of
>> checking bases for all the classes and add missing "self != self" for all
>> those which derive from equality_comparable;
>> Perhaps there is the same problem with less_than_comparable and others.
>
> I would implement the following solution:
> 1. Introduce new "def_visitor" (
> http://www.boost.org/doc/libs/1_44_0/libs/python/doc/v2/def_visitor.html
> ) - so it will register all member function from the appropriate class
>     In our case, equality_comparable, the visitor will register == and !=
>    ( this code could be contributed later to the Boost.Python )
>
> 2. Apply that visitors on all relevant classes using py++
>
> Does it help?
Partially ;)
I don't understand the concept with a new visitor. Creating a visitor for eg. 
equality_comparable doesn't solve the problem in general (and btw, 
equality_comparable doesn't provide member functions)
I think all the needed visitors are already there (eg. boost::python::self != 
boost::python::self). The problem is that pyplusplus doesn't use them (or - to 
be specific - it *sometimes* doesn't use them).

Why I consider it as a py++ bug? The problem is *sometimes* py++ adds some 
visitors to a class, and sometimes not. I suspect (not 100% verified) it doesn't 
work if an operator is declared as a non member function. I haven't found such 
warning in the docs, thus my surprise. If it is there, well, my fault. It 
escaped me.
The uncertainty about operator== and operator!= is very unfortunate, because in 
python you have == or != by default, and in python code you don't know whether 
you're using pythonic comparison or the one you've defined in C++.
So perhaps it is at least worth pointing out in docs (if it is not there, and 
didn't escape ;).
I'd also add a tip that for each class_ one may (or should) define __cmp__ to 
raise some fancy exception in order to avoid problems as below:
b1 = BoundClass(...)
b2 = BoundClass(...)
b1 == b2 # are we using pythonic pointer comparison or C++ defined one?

If __cmp__ is defined to raise exception:
1. if operator== is defined in C++ and correct visitor is applied then python's 
__eq__ will be used, and comparison works as expected (that is: as in C++)
2. if operator== is not defined or no visitor has been applied (__eq__ is not 
defined) __cmp__ will be called and exception will happen. There will be no need 
to trace bugs that occurred in seemingly impossible branches.

In my case I applied point 2 as a workaround: I look for all the operators 
(member or not) and apply related visitors on the classes that are parameters of 
these operators. This is far for ideal, but works in most cases.
Having exception raising __cmp__ I'm able to spot problems immediately.

regards,
Kuba


More information about the Cplusplus-sig mailing list