简体   繁体   中英

Using Boost Python, I can wrap C++ overloaded operators “+=”, “-=”, “*=”, but not “/=”?

Boost Python has a pretty straightforward method of wrapping overloaded operators. The tutorial for exposing C++ classes, methods, etc. at boost.org ( https://www.boost.org/doc/libs/1_66_0/libs/python/doc/html/tutorial/tutorial/exposing.html ) gives this example:

The overloaded C++ operators for an example class, FilePos:

class FilePos { /*...*/ };

FilePos     operator+(FilePos, int);
FilePos     operator+(int, FilePos);
int         operator-(FilePos, FilePos);
FilePos     operator-(FilePos, int);
FilePos&    operator+=(FilePos&, int);
FilePos&    operator-=(FilePos&, int);
bool        operator<(FilePos, FilePos);

How to map them to Python:

class_<FilePos>("FilePos")
    .def(self + int())          // __add__
    .def(int() + self)          // __radd__
    .def(self - self)           // __sub__
    .def(self - int())          // __sub__
    .def(self += int())         // __iadd__
    .def(self -= other<int>())
    .def(self < self);          // __lt__

I have a C++ class called "Angle" that represents an angle. It has overloaded operators including "+=", "-=", "*=" and "/=". Each overloaded operator is designed to add, subtract, multiply, or divide some input of type double to the degree value held by the Angle class. The Angle class wrapper maps these overloaded operators in exactly the same manner depicted in the above example. When I test the addition, subtraction and multiplication operators in Python, they work wonderfully. The division operator, not so. When I run a simple test like so:

A = Angle(1) # instantiate Angle object with magnitude of 1 radian
A /= 2.0 # attempt to divide the radian measurement by 2

I get the following error:

TypeError: unsupported operand type(s) for /=: 'Angle' and 'float'

Based on this question:

Error when trying to overload an operator "/"

I see that Python3 (the version I'm using) has a unique way of understanding the "/" character. However, this solution doesn't work for me as the class I'm using is a wrapped C++ class.

My question: is there a way to map the overloaded operator "/=" from C++ to python using boost in such a way that retains the same syntax (ie not writing a thin wrapper in C++ called "selfdiv" that performs the same operation, but must be called with "Angle.selfdiv()")? Perhaps some way to override how Python interprets that forward slash character?

Python 3 changed the way the division operator is defined, and Boost.Python's auto-generated version uses the old Python 2 style for in-place division, which no longer works. This seems to be an oversight, since the non-in-place version has been updated to Python 3's __truediv__ magic method. There is an open GitHub issue about this very thing. Until it gets fixed you can define __itruediv__ and/or __ifloordiv__ like you would any other class member function:

class_<Foo>("Foo")
    .def(
        "__itruediv__",
        &Foo::operator/=,
        return_self<>{}
    );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM